From d1f82a18ddb96d3c7daa03e897093c38fb07b612 Mon Sep 17 00:00:00 2001 From: mejango Date: Thu, 18 May 2023 11:57:56 -0400 Subject: [PATCH 1/3] must send project ownership to multisig --- deploy/v3_1.js | 6 +++++- lib/forge-std | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/deploy/v3_1.js b/deploy/v3_1.js index ccab7a12c..15f221b34 100644 --- a/deploy/v3_1.js +++ b/deploy/v3_1.js @@ -155,7 +155,7 @@ module.exports = async ({ deployments, getChainId }) => { const jbDirectoryContract = new ethers.Contract(JBDirectory.address, JBDirectory.abi); const jbPricesContract = new ethers.Contract(JBPrices.address, JBPrices.abi); const jbControllerContract = new ethers.Contract(JBController.address, JBController.abi); - const jbProjects = new ethers.Contract(JBProjects.address, JBProjects.abi); + const jbProjectsContract = new ethers.Contract(JBProjects.address, JBProjects.abi); const jbCurrenciesLibrary = new ethers.Contract(JBCurrencies.address, JBCurrencies.abi); // Get a reference to USD and ETH currency indexes. @@ -212,6 +212,10 @@ module.exports = async ({ deployments, getChainId }) => { if ((await jbPricesContract.connect(deployer).owner()) != multisigAddress) await jbPricesContract.connect(deployer).transferOwnership(multisigAddress); + // If needed, transfer the ownership of the JBProjects to to the multisig. + if ((await jbProjectsContract.connect(deployer).owner()) != multisigAddress) + await jbProjectsContract.connect(deployer).transferOwnership(multisigAddress); + let isAllowedToSetFirstController = await jbDirectoryContract .connect(deployer) .isAllowedToSetFirstController(JBController.address); diff --git a/lib/forge-std b/lib/forge-std index a2edd39db..066ff16c5 160000 --- a/lib/forge-std +++ b/lib/forge-std @@ -1 +1 @@ -Subproject commit a2edd39db95df7e9dd3f9ef9edc8c55fefddb6df +Subproject commit 066ff16c5c03e6f931cd041fd366bc4be1fae82a From fa6aebaa4df0006ed37005207751b562aff2e261 Mon Sep 17 00:00:00 2001 From: mejango Date: Thu, 18 May 2023 11:58:38 -0400 Subject: [PATCH 2/3] multisig => governance --- deploy/v3_1.js | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/deploy/v3_1.js b/deploy/v3_1.js index 15f221b34..c05f84403 100644 --- a/deploy/v3_1.js +++ b/deploy/v3_1.js @@ -13,7 +13,7 @@ module.exports = async ({ deployments, getChainId }) => { const { deploy } = deployments; const [deployer] = await ethers.getSigners(); - let multisigAddress; + let governanceAddress; let chainlinkV2UsdEthPriceFeed; let chainId = await getChainId(); let baseDeployArgs = { @@ -28,24 +28,24 @@ module.exports = async ({ deployments, getChainId }) => { switch (chainId) { // mainnet case '1': - multisigAddress = '0xAF28bcB48C40dBC86f52D459A6562F658fc94B1e'; + governanceAddress = '0xAF28bcB48C40dBC86f52D459A6562F658fc94B1e'; chainlinkV2UsdEthPriceFeed = '0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419'; protocolProjectStartsAtOrAfter = 1664047173; break; // Goerli case '5': - multisigAddress = '0x46D623731E179FAF971CdA04fF8c499C95461b3c'; + governanceAddress = '0x46D623731E179FAF971CdA04fF8c499C95461b3c'; chainlinkV2UsdEthPriceFeed = '0xD4a33860578De61DBAbDc8BFdb98FD742fA7028e'; protocolProjectStartsAtOrAfter = 0; break; // hardhat / localhost case '31337': - multisigAddress = deployer.address; + governanceAddress = deployer.address; protocolProjectStartsAtOrAfter = 0; break; } - console.log({ multisigAddress, protocolProjectStartsAtOrAfter }); + console.log({ governanceAddress, protocolProjectStartsAtOrAfter }); // Deploy a JBOperatorStore contract. const JBOperatorStore = await deploy('JBOperatorStore', { @@ -174,7 +174,7 @@ module.exports = async ({ deployments, getChainId }) => { JBSplitStore.address, JBPrices.address, JBSingleTokenPaymentTerminalStore.address, - multisigAddress, + governanceAddress, ], }); @@ -209,12 +209,12 @@ module.exports = async ({ deployments, getChainId }) => { } // If needed, transfer the ownership of the JBPrices to to the multisig. - if ((await jbPricesContract.connect(deployer).owner()) != multisigAddress) - await jbPricesContract.connect(deployer).transferOwnership(multisigAddress); + if ((await jbPricesContract.connect(deployer).owner()) != governanceAddress) + await jbPricesContract.connect(deployer).transferOwnership(governanceAddress); // If needed, transfer the ownership of the JBProjects to to the multisig. - if ((await jbProjectsContract.connect(deployer).owner()) != multisigAddress) - await jbProjectsContract.connect(deployer).transferOwnership(multisigAddress); + if ((await jbProjectsContract.connect(deployer).owner()) != governanceAddress) + await jbProjectsContract.connect(deployer).transferOwnership(governanceAddress); let isAllowedToSetFirstController = await jbDirectoryContract .connect(deployer) @@ -231,8 +231,8 @@ module.exports = async ({ deployments, getChainId }) => { } // If needed, transfer the ownership of the JBDirectory contract to the multisig. - if ((await jbDirectoryContract.connect(deployer).owner()) != multisigAddress) { - let tx = await jbDirectoryContract.connect(deployer).transferOwnership(multisigAddress); + if ((await jbDirectoryContract.connect(deployer).owner()) != governanceAddress) { + let tx = await jbDirectoryContract.connect(deployer).transferOwnership(governanceAddress); await tx.wait(); } From 5b0ada67c46a37f9aae5dc17e590606b7fae2a38 Mon Sep 17 00:00:00 2001 From: mejango Date: Thu, 18 May 2023 12:49:16 -0400 Subject: [PATCH 3/3] ETH => GAS_TOKEN --- .solcover.js | 2 +- ...er.sol => JBGasTokenERC20ProjectPayer.sol} | 32 +-- ...> JBGasTokenERC20ProjectPayerDeployer.sol} | 13 +- ...yer.sol => JBGasTokenERC20SplitsPayer.sol} | 54 ++-- ...=> JBGasTokenERC20SplitsPayerDeployer.sol} | 14 +- ...inal.sol => JBGasTokenPaymentTerminal.sol} | 16 +- ...1.sol => JBGasTokenPaymentTerminal3_1.sol} | 16 +- .../JBSingleTokenPaymentTerminalStore.sol | 41 ++- .../JBSingleTokenPaymentTerminalStore3_1.sol | 41 ++- .../JBPayoutRedemptionPaymentTerminal.sol | 67 ++--- .../JBPayoutRedemptionPaymentTerminal3_1.sol | 88 +++--- .../IJBETHERC20ProjectPayerDeployer.sol | 2 +- .../IJBETHERC20SplitsPayerDeployer.sol | 2 +- contracts/libraries/JBCurrencies.sol | 2 +- contracts/libraries/JBSplitsGroups.sol | 2 +- contracts/libraries/JBTokens.sol | 4 +- deploy/1.js | 16 +- deploy/splits_and_project_payer.js | 14 +- deploy/v3_1.js | 140 +++++++-- .../JBETHERC20ProjectPayerDeployer.json | 4 +- .../goerli/JBETHERC20SplitsPayerDeployer.json | 4 +- deployments/goerli/JBETHPaymentTerminal.json | 2 +- .../goerli/JBETHPaymentTerminal3_1.json | 2 +- .../JBSingleTokenPaymentTerminalStore.json | 2 +- .../JBSingleTokenPaymentTerminalStore3_1.json | 2 +- .../7271447540576b6e014cf146f777e938.json | 36 +-- .../7f5ae5369c2a685c882e67f75315b841.json | 36 +-- .../9d8f961b8d6848d1dd32ae08288e8c6a.json | 36 +-- .../c01efb3c94c1f18d90d0889134c73f7b.json | 32 +-- .../e87fd161fb98793b8dd4dcaee81afb88.json | 36 +-- .../ed590828cf2d3bd8e9fe992c4f52dc83.json | 36 +-- .../JBETHERC20ProjectPayerDeployer.json | 4 +- .../JBETHERC20SplitsPayerDeployer.json | 4 +- deployments/mainnet/JBETHPaymentTerminal.json | 2 +- .../mainnet/JBETHPaymentTerminal3_1.json | 2 +- .../JBSingleTokenPaymentTerminalStore.json | 2 +- .../JBSingleTokenPaymentTerminalStore3_1.json | 2 +- .../153d6bc38185326110a6246705507380.json | 34 +-- .../2558f6dc599ebc1f13c79797e151bc24.json | 30 +- .../36426b5abae189028f71abc80f5dc8b7.json | 54 ++-- .../4138c0c854528929e18f6ccc34d600b0.json | 54 ++-- .../60cd95dca5edde649565e9f7f43720b6.json | 36 +-- .../7f5ae5369c2a685c882e67f75315b841.json | 36 +-- .../87acdcf5deeaa43ae3ecf62f45455645.json | 40 +-- .../a1f674e02c4866a16e5bde886a31b82e.json | 34 +-- .../ba079c3b841cf131865f97c4e38baa17.json | 34 +-- .../c01efb3c94c1f18d90d0889134c73f7b.json | 32 +-- .../e74c031977287ddc5a2bef1107c54b87.json | 32 +-- .../e87fd161fb98793b8dd4dcaee81afb88.json | 36 +-- .../ed590828cf2d3bd8e9fe992c4f52dc83.json | 36 +-- forge_tests/TestController3_0_1.sol | 2 +- forge_tests/TestDelegates.sol | 4 +- forge_tests/TestEIP165.sol | 272 +++++++++--------- forge_tests/TestMigrationOperator.sol | 8 +- forge_tests/TestPlanetable.sol | 18 +- forge_tests/TestTerminal3_1.sol | 18 +- forge_tests/helpers/AccessJBLib.sol | 60 ++-- .../add_to_balance.test.js | 6 +- test/jb_eth_erc20_project_payer/pay.test.js | 6 +- .../set_default_values.test.js | 4 +- .../add_to_balance.test.js | 8 +- .../deploy_project_payer.test.js | 4 +- .../pay.test.js | 8 +- .../set_default_values.test.js | 6 +- .../add_to_balance.test.js | 150 +++++----- test/jb_eth_erc20_splits_payer/pay.test.js | 102 +++---- .../jb_eth_erc20_splits_payer/receive.test.js | 126 ++++---- .../set_default_splits.test.js | 28 +- .../set_default_splits_reference.test.js | 28 +- .../add_to_balance.test.js | 8 +- .../deploy_split_payer.test.js | 2 +- .../deploy_split_payer_with_splits.test.js | 2 +- .../pay.test.js | 8 +- .../receive.test.js | 8 +- .../add_to_balance_of.test.js | 2 +- .../current_eth_overflow_of.test.js | 2 +- .../distribute_payouts_of.test.js | 2 +- test/jb_payment_terminal/migrate.test.js | 4 +- .../redeem_tokens_of.test.js | 14 +- test/jb_payment_terminal/set_fee.test.js | 2 +- .../jb_payment_terminal/set_fee_gauge.test.js | 2 +- .../set_feeless_terminal.test.js | 2 +- .../use_allowance_of.test.js | 16 +- test/jb_payment_terminal/view.test.js | 2 +- .../add_to_balance_of.test.js | 154 +++++----- .../current_eth_overflow_of.test.js | 2 +- .../distribute_payouts_of.test.js | 44 +-- test/jb_payment_terminal_3_1/migrate.test.js | 4 +- .../redeem_tokens_of.test.js | 14 +- test/jb_payment_terminal_3_1/set_fee.test.js | 2 +- .../set_fee_gauge.test.js | 2 +- .../set_feeless_terminal.test.js | 2 +- .../use_allowance_of.test.js | 16 +- test/jb_payment_terminal_3_1/view.test.js | 2 +- .../current_overflow_of.test.js | 2 +- .../current_reclaimable_overflow_of.test.js | 2 +- .../current_total_overflow_of.test.js | 2 +- .../record_distribution_for.test.js | 2 +- .../record_redemption_for.test.js | 2 +- .../record_used_allowance_of.test.js | 2 +- 100 files changed, 1273 insertions(+), 1213 deletions(-) rename contracts/{JBETHERC20ProjectPayer.sol => JBGasTokenERC20ProjectPayer.sol} (95%) rename contracts/{JBETHERC20ProjectPayerDeployer.sol => JBGasTokenERC20ProjectPayerDeployer.sol} (83%) rename contracts/{JBETHERC20SplitsPayer.sol => JBGasTokenERC20SplitsPayer.sol} (95%) rename contracts/{JBETHERC20SplitsPayerDeployer.sol => JBGasTokenERC20SplitsPayerDeployer.sol} (92%) rename contracts/{JBETHPaymentTerminal.sol => JBGasTokenPaymentTerminal.sol} (89%) rename contracts/{JBETHPaymentTerminal3_1.sol => JBGasTokenPaymentTerminal3_1.sol} (89%) diff --git a/.solcover.js b/.solcover.js index fa16ebb83..15545dcb1 100644 --- a/.solcover.js +++ b/.solcover.js @@ -39,7 +39,7 @@ module.exports = { 'interfaces/IJBController.sol', 'interfaces/IJBControllerUtility.sol', 'interfaces/IJBDirectory.sol', - 'interfaces/IJBETHERC20ProjectPayerDeployer.sol', + 'interfaces/IJBGasTokenERC20ProjectPayerDeployer.sol', 'interfaces/IJBFeeGauge.sol', 'interfaces/IJBFundingCycleBallot.sol', 'interfaces/IJBFundingCycleDataSource.sol', diff --git a/contracts/JBETHERC20ProjectPayer.sol b/contracts/JBGasTokenERC20ProjectPayer.sol similarity index 95% rename from contracts/JBETHERC20ProjectPayer.sol rename to contracts/JBGasTokenERC20ProjectPayer.sol index f807d8a4d..40ff774c8 100644 --- a/contracts/JBETHERC20ProjectPayer.sol +++ b/contracts/JBGasTokenERC20ProjectPayer.sol @@ -24,7 +24,7 @@ import './libraries/JBTokens.sol'; Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions. ERC165: Introspection on interface adherance. */ -contract JBETHERC20ProjectPayer is Ownable, ERC165, IJBProjectPayer { +contract JBGasTokenERC20ProjectPayer is Ownable, ERC165, IJBProjectPayer { using SafeERC20 for IERC20; //*********************************************************************// @@ -104,13 +104,9 @@ contract JBETHERC20ProjectPayer is Ownable, ERC165, IJBProjectPayer { @param _interfaceId The ID of the interface to check for adherance to. */ - function supportsInterface(bytes4 _interfaceId) - public - view - virtual - override(ERC165, IERC165) - returns (bool) - { + function supportsInterface( + bytes4 _interfaceId + ) public view virtual override(ERC165, IERC165) returns (bool) { return _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId); } @@ -147,7 +143,7 @@ contract JBETHERC20ProjectPayer is Ownable, ERC165, IJBProjectPayer { bool _defaultPreferAddToBalance, address _owner ) public { - if(msg.sender != projectPayerDeployer) revert ALREADY_INITIALIZED(); + if (msg.sender != projectPayerDeployer) revert ALREADY_INITIALIZED(); defaultProjectId = _defaultProjectId; defaultBeneficiary = _defaultBeneficiary; @@ -176,7 +172,7 @@ contract JBETHERC20ProjectPayer is Ownable, ERC165, IJBProjectPayer { if (defaultPreferAddToBalance) _addToBalanceOf( defaultProjectId, - JBTokens.ETH, + JBTokens.GAS_TOKEN, address(this).balance, 18, // balance is a fixed point number with 18 decimals. defaultMemo, @@ -185,7 +181,7 @@ contract JBETHERC20ProjectPayer is Ownable, ERC165, IJBProjectPayer { else _pay( defaultProjectId, - JBTokens.ETH, + JBTokens.GAS_TOKEN, address(this).balance, 18, // balance is a fixed point number with 18 decimals. defaultBeneficiary == address(0) ? tx.origin : defaultBeneficiary, @@ -282,7 +278,7 @@ contract JBETHERC20ProjectPayer is Ownable, ERC165, IJBProjectPayer { bytes calldata _metadata ) public payable virtual override { // ETH shouldn't be sent if the token isn't ETH. - if (address(_token) != JBTokens.ETH) { + if (address(_token) != JBTokens.GAS_TOKEN) { if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED(); // Get a reference to the balance before receiving tokens. @@ -332,7 +328,7 @@ contract JBETHERC20ProjectPayer is Ownable, ERC165, IJBProjectPayer { bytes calldata _metadata ) public payable virtual override { // ETH shouldn't be sent if the token isn't ETH. - if (address(_token) != JBTokens.ETH) { + if (address(_token) != JBTokens.GAS_TOKEN) { if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED(); // Get a reference to the balance before receiving tokens. @@ -391,16 +387,16 @@ contract JBETHERC20ProjectPayer is Ownable, ERC165, IJBProjectPayer { if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT(); // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract. - if (_token != JBTokens.ETH) IERC20(_token).safeApprove(address(_terminal), _amount); + if (_token != JBTokens.GAS_TOKEN) IERC20(_token).safeApprove(address(_terminal), _amount); // If the token is ETH, send it in msg.value. - uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0; + uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0; // Send funds to the terminal. // If the token is ETH, send it in msg.value. _terminal.pay{value: _payableValue}( _projectId, - _amount, // ignored if the token is JBTokens.ETH. + _amount, // ignored if the token is JBTokens.GAS_TOKEN. _token, _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0) ? defaultBeneficiary @@ -441,10 +437,10 @@ contract JBETHERC20ProjectPayer is Ownable, ERC165, IJBProjectPayer { if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT(); // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract. - if (_token != JBTokens.ETH) IERC20(_token).safeApprove(address(_terminal), _amount); + if (_token != JBTokens.GAS_TOKEN) IERC20(_token).safeApprove(address(_terminal), _amount); // If the token is ETH, send it in msg.value. - uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0; + uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0; // Add to balance so tokens don't get issued. _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata); diff --git a/contracts/JBETHERC20ProjectPayerDeployer.sol b/contracts/JBGasTokenERC20ProjectPayerDeployer.sol similarity index 83% rename from contracts/JBETHERC20ProjectPayerDeployer.sol rename to contracts/JBGasTokenERC20ProjectPayerDeployer.sol index 5d49e2456..853bd0818 100644 --- a/contracts/JBETHERC20ProjectPayerDeployer.sol +++ b/contracts/JBGasTokenERC20ProjectPayerDeployer.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.16; -import { Clones } from '@openzeppelin/contracts/proxy/Clones.sol'; +import {Clones} from '@openzeppelin/contracts/proxy/Clones.sol'; -import './interfaces/IJBETHERC20ProjectPayerDeployer.sol'; -import './JBETHERC20ProjectPayer.sol'; +import './interfaces/IJBGasTokenERC20ProjectPayerDeployer.sol'; +import './JBGasTokenERC20ProjectPayer.sol'; /** @notice @@ -12,10 +12,9 @@ import './JBETHERC20ProjectPayer.sol'; @dev Adheres to - - IJBETHERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules. + IJBGasTokenERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules. */ -contract JBETHERC20ProjectPayerDeployer is IJBETHERC20ProjectPayerDeployer { - +contract JBGasTokenERC20ProjectPayerDeployer is IJBGasTokenERC20ProjectPayerDeployer { address immutable implementation; IJBDirectory immutable directory; @@ -24,7 +23,7 @@ contract JBETHERC20ProjectPayerDeployer is IJBETHERC20ProjectPayerDeployer { @param _directory A contract storing directories of terminals and controllers for each project. */ constructor(IJBDirectory _directory) { - implementation = address(new JBETHERC20ProjectPayer(_directory)); + implementation = address(new JBGasTokenERC20ProjectPayer(_directory)); directory = _directory; } diff --git a/contracts/JBETHERC20SplitsPayer.sol b/contracts/JBGasTokenERC20SplitsPayer.sol similarity index 95% rename from contracts/JBETHERC20SplitsPayer.sol rename to contracts/JBGasTokenERC20SplitsPayer.sol index dec2480de..7b46820bf 100644 --- a/contracts/JBETHERC20SplitsPayer.sol +++ b/contracts/JBGasTokenERC20SplitsPayer.sol @@ -8,7 +8,7 @@ import '@paulrberg/contracts/math/PRBMath.sol'; import './interfaces/IJBSplitsPayer.sol'; import './interfaces/IJBSplitsStore.sol'; import './libraries/JBConstants.sol'; -import './JBETHERC20ProjectPayer.sol'; +import './JBGasTokenERC20ProjectPayer.sol'; /** @notice @@ -23,10 +23,14 @@ import './JBETHERC20ProjectPayer.sol'; @dev Inherits from - - JBETHERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called. + JBGasTokenERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called. ReentrancyGuard: Contract module that helps prevent reentrant calls to a function. */ -contract JBETHERC20SplitsPayer is JBETHERC20ProjectPayer, ReentrancyGuard, IJBSplitsPayer { +contract JBGasTokenERC20SplitsPayer is + JBGasTokenERC20ProjectPayer, + ReentrancyGuard, + IJBSplitsPayer +{ using SafeERC20 for IERC20; //*********************************************************************// @@ -76,13 +80,9 @@ contract JBETHERC20SplitsPayer is JBETHERC20ProjectPayer, ReentrancyGuard, IJBSp @return A flag indicating if this contract adheres to the specified interface. */ - function supportsInterface(bytes4 _interfaceId) - public - view - virtual - override(JBETHERC20ProjectPayer, IERC165) - returns (bool) - { + function supportsInterface( + bytes4 _interfaceId + ) public view virtual override(JBGasTokenERC20ProjectPayer, IERC165) returns (bool) { return _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId); } @@ -90,18 +90,13 @@ contract JBETHERC20SplitsPayer is JBETHERC20ProjectPayer, ReentrancyGuard, IJBSp //*********************************************************************// // -------------------------- constructor ---------------------------- // //*********************************************************************// -/** + /** @param _splitsStore A contract that stores splits for each project. */ - constructor( - IJBSplitsStore _splitsStore - ) - JBETHERC20ProjectPayer( - _splitsStore.directory() - ) - { + constructor(IJBSplitsStore _splitsStore) JBGasTokenERC20ProjectPayer(_splitsStore.directory()) { splitsStore = _splitsStore; } + /** @dev The re-initialize check is done in the inherited paroject payer @@ -128,7 +123,6 @@ contract JBETHERC20SplitsPayer is JBETHERC20ProjectPayer, ReentrancyGuard, IJBSp bool _preferAddToBalance, address _owner ) external override { - super.initialize( _defaultProjectId, _defaultBeneficiary, @@ -144,8 +138,6 @@ contract JBETHERC20SplitsPayer is JBETHERC20ProjectPayer, ReentrancyGuard, IJBSp defaultSplitsGroup = _defaultSplitsGroup; } - - //*********************************************************************// // ------------------------- default receive ------------------------- // //*********************************************************************// @@ -163,7 +155,7 @@ contract JBETHERC20SplitsPayer is JBETHERC20ProjectPayer, ReentrancyGuard, IJBSp defaultSplitsProjectId, defaultSplitsDomain, defaultSplitsGroup, - JBTokens.ETH, + JBTokens.GAS_TOKEN, address(this).balance, 18, // decimals. defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin @@ -178,7 +170,7 @@ contract JBETHERC20SplitsPayer is JBETHERC20ProjectPayer, ReentrancyGuard, IJBSp // Pay the project by adding to its balance if prefered. _addToBalanceOf( defaultProjectId, - JBTokens.ETH, + JBTokens.GAS_TOKEN, _leftoverAmount, 18, // decimals. defaultMemo, @@ -188,7 +180,7 @@ contract JBETHERC20SplitsPayer is JBETHERC20ProjectPayer, ReentrancyGuard, IJBSp else _pay( defaultProjectId, - JBTokens.ETH, + JBTokens.GAS_TOKEN, _leftoverAmount, 18, // decimals. defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin, @@ -286,7 +278,7 @@ contract JBETHERC20SplitsPayer is JBETHERC20ProjectPayer, ReentrancyGuard, IJBSp bytes calldata _metadata ) public payable virtual override nonReentrant { // ETH shouldn't be sent if the token isn't ETH. - if (address(_token) != JBTokens.ETH) { + if (address(_token) != JBTokens.GAS_TOKEN) { if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED(); // Get a reference to the balance before receiving tokens. @@ -335,7 +327,7 @@ contract JBETHERC20SplitsPayer is JBETHERC20ProjectPayer, ReentrancyGuard, IJBSp // If no project was specified, send the funds directly to the beneficiary or the tx.origin. else { // Transfer the ETH. - if (_token == JBTokens.ETH) + if (_token == JBTokens.GAS_TOKEN) Address.sendValue( // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin. _beneficiary != address(0) ? payable(_beneficiary) : defaultBeneficiary != address(0) @@ -392,7 +384,7 @@ contract JBETHERC20SplitsPayer is JBETHERC20ProjectPayer, ReentrancyGuard, IJBSp bytes calldata _metadata ) public payable virtual override nonReentrant { // ETH shouldn't be sent if this terminal's token isn't ETH. - if (address(_token) != JBTokens.ETH) { + if (address(_token) != JBTokens.GAS_TOKEN) { if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED(); // Get a reference to the balance before receiving tokens. @@ -430,7 +422,7 @@ contract JBETHERC20SplitsPayer is JBETHERC20ProjectPayer, ReentrancyGuard, IJBSp // Otherwise, send a payment to the beneficiary. else { // Transfer the ETH. - if (_token == JBTokens.ETH) + if (_token == JBTokens.GAS_TOKEN) Address.sendValue( // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin. defaultBeneficiary != address(0) ? defaultBeneficiary : payable(tx.origin), @@ -546,11 +538,11 @@ contract JBETHERC20SplitsPayer is JBETHERC20ProjectPayer, ReentrancyGuard, IJBSp ); // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract. - if (_token != JBTokens.ETH) + if (_token != JBTokens.GAS_TOKEN) IERC20(_token).safeApprove(address(_split.allocator), _splitAmount); // If the token is ETH, send it in msg.value. - uint256 _payableValue = _token == JBTokens.ETH ? _splitAmount : 0; + uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _splitAmount : 0; // Trigger the allocator's `allocate` function. _split.allocator.allocate{value: _payableValue}(_data); @@ -580,7 +572,7 @@ contract JBETHERC20SplitsPayer is JBETHERC20ProjectPayer, ReentrancyGuard, IJBSp ); } else { // Transfer the ETH. - if (_token == JBTokens.ETH) + if (_token == JBTokens.GAS_TOKEN) Address.sendValue( // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary. _split.beneficiary != address(0) ? _split.beneficiary : payable(_defaultBeneficiary), diff --git a/contracts/JBETHERC20SplitsPayerDeployer.sol b/contracts/JBGasTokenERC20SplitsPayerDeployer.sol similarity index 92% rename from contracts/JBETHERC20SplitsPayerDeployer.sol rename to contracts/JBGasTokenERC20SplitsPayerDeployer.sol index f4f56f6db..fedd23f58 100644 --- a/contracts/JBETHERC20SplitsPayerDeployer.sol +++ b/contracts/JBGasTokenERC20SplitsPayerDeployer.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.16; -import { Clones } from '@openzeppelin/contracts/proxy/Clones.sol'; +import {Clones} from '@openzeppelin/contracts/proxy/Clones.sol'; -import './interfaces/IJBETHERC20SplitsPayerDeployer.sol'; +import './interfaces/IJBGasTokenERC20SplitsPayerDeployer.sol'; import './structs/JBSplit.sol'; import './structs/JBGroupedSplits.sol'; -import './JBETHERC20SplitsPayer.sol'; +import './JBGasTokenERC20SplitsPayer.sol'; /** @notice @@ -14,16 +14,15 @@ import './JBETHERC20SplitsPayer.sol'; @dev Adheres to - - IJBETHERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules. + IJBGasTokenERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules. */ -contract JBETHERC20SplitsPayerDeployer is IJBETHERC20SplitsPayerDeployer { - +contract JBGasTokenERC20SplitsPayerDeployer is IJBGasTokenERC20SplitsPayerDeployer { address immutable implementation; IJBSplitsStore immutable splitsStore; constructor(IJBSplitsStore _splitsStore) { - implementation = address(new JBETHERC20SplitsPayer(_splitsStore)); + implementation = address(new JBGasTokenERC20SplitsPayer(_splitsStore)); splitsStore = _splitsStore; } @@ -123,7 +122,6 @@ contract JBETHERC20SplitsPayerDeployer is IJBETHERC20SplitsPayerDeployer { bool _defaultPreferAddToBalance, address _owner ) public override returns (IJBSplitsPayer splitsPayer) { - // Deploy the splits payer. splitsPayer = IJBSplitsPayer(payable(Clones.clone(implementation))); diff --git a/contracts/JBETHPaymentTerminal.sol b/contracts/JBGasTokenPaymentTerminal.sol similarity index 89% rename from contracts/JBETHPaymentTerminal.sol rename to contracts/JBGasTokenPaymentTerminal.sol index d1db7a75e..617752c4c 100644 --- a/contracts/JBETHPaymentTerminal.sol +++ b/contracts/JBGasTokenPaymentTerminal.sol @@ -7,13 +7,13 @@ import './libraries/JBSplitsGroups.sol'; /** @notice - Manages all inflows and outflows of ETH funds into the protocol ecosystem. + Manages all inflows and outflows of GAS_TOKEN funds into the protocol ecosystem. @dev Inherits from - JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem. */ -contract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal { +contract JBGasTokenPaymentTerminal is JBPayoutRedemptionPaymentTerminal { //*********************************************************************// // -------------------------- internal views ------------------------- // //*********************************************************************// @@ -53,11 +53,11 @@ contract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal { address _owner ) JBPayoutRedemptionPaymentTerminal( - JBTokens.ETH, + JBTokens.GAS_TOKEN, 18, // 18 decimals. - JBCurrencies.ETH, + JBCurrencies.GAS_CURRENCY, _baseWeightCurrency, - JBSplitsGroups.ETH_PAYOUT, + JBSplitsGroups.GAS_TOKEN_PAYOUT, _operatorStore, _projects, _directory, @@ -83,11 +83,7 @@ contract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal { @param _to The address to which the transfer should go. @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal. */ - function _transferFrom( - address _from, - address payable _to, - uint256 _amount - ) internal override { + function _transferFrom(address _from, address payable _to, uint256 _amount) internal override { _from; // Prevents unused var compiler and natspec complaints. Address.sendValue(_to, _amount); diff --git a/contracts/JBETHPaymentTerminal3_1.sol b/contracts/JBGasTokenPaymentTerminal3_1.sol similarity index 89% rename from contracts/JBETHPaymentTerminal3_1.sol rename to contracts/JBGasTokenPaymentTerminal3_1.sol index 3a667bc69..a18fcdee4 100644 --- a/contracts/JBETHPaymentTerminal3_1.sol +++ b/contracts/JBGasTokenPaymentTerminal3_1.sol @@ -7,13 +7,13 @@ import './libraries/JBSplitsGroups.sol'; /** @notice - Manages all inflows and outflows of ETH funds into the protocol ecosystem. + Manages all inflows and outflows of GAS_TOKEN funds into the protocol ecosystem. @dev Inherits from - JBPayoutRedemptionPaymentTerminal3_1: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem. */ -contract JBETHPaymentTerminal3_1 is JBPayoutRedemptionPaymentTerminal3_1 { +contract JBGasTokenPaymentTerminal3_1 is JBPayoutRedemptionPaymentTerminal3_1 { //*********************************************************************// // -------------------------- internal views ------------------------- // //*********************************************************************// @@ -53,11 +53,11 @@ contract JBETHPaymentTerminal3_1 is JBPayoutRedemptionPaymentTerminal3_1 { address _owner ) JBPayoutRedemptionPaymentTerminal3_1( - JBTokens.ETH, + JBTokens.GAS_TOKEN, 18, // 18 decimals. - JBCurrencies.ETH, + JBCurrencies.GAS_CURRENCY, _baseWeightCurrency, - JBSplitsGroups.ETH_PAYOUT, + JBSplitsGroups.GAS_TOKEN_PAYOUT, _operatorStore, _projects, _directory, @@ -83,11 +83,7 @@ contract JBETHPaymentTerminal3_1 is JBPayoutRedemptionPaymentTerminal3_1 { @param _to The address to which the transfer should go. @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal. */ - function _transferFrom( - address _from, - address payable _to, - uint256 _amount - ) internal override { + function _transferFrom(address _from, address payable _to, uint256 _amount) internal override { _from; // Prevents unused var compiler and natspec complaints. Address.sendValue(_to, _amount); diff --git a/contracts/JBSingleTokenPaymentTerminalStore.sol b/contracts/JBSingleTokenPaymentTerminalStore.sol index dcfaf8290..822cb42c5 100644 --- a/contracts/JBSingleTokenPaymentTerminalStore.sol +++ b/contracts/JBSingleTokenPaymentTerminalStore.sol @@ -144,12 +144,10 @@ contract JBSingleTokenPaymentTerminalStore is ReentrancyGuard, IJBSingleTokenPay @return The current amount of overflow that project has in the specified terminal. */ - function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId) - external - view - override - returns (uint256) - { + function currentOverflowOf( + IJBSingleTokenPaymentTerminal _terminal, + uint256 _projectId + ) external view override returns (uint256) { // Return the overflow during the project's current funding cycle. return _overflowDuring( @@ -277,11 +275,7 @@ contract JBSingleTokenPaymentTerminalStore is ReentrancyGuard, IJBSingleTokenPay @param _fundingCycleStore A contract storing all funding cycle configurations. @param _prices A contract that exposes price feeds. */ - constructor( - IJBDirectory _directory, - IJBFundingCycleStore _fundingCycleStore, - IJBPrices _prices - ) { + constructor(IJBDirectory _directory, IJBFundingCycleStore _fundingCycleStore, IJBPrices _prices) { directory = _directory; fundingCycleStore = _fundingCycleStore; prices = _prices; @@ -414,7 +408,7 @@ contract JBSingleTokenPaymentTerminalStore is ReentrancyGuard, IJBSingleTokenPay // 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 + ? 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. @@ -643,7 +637,7 @@ contract JBSingleTokenPaymentTerminalStore is ReentrancyGuard, IJBSingleTokenPay ? _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. + 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) ); @@ -721,7 +715,7 @@ contract JBSingleTokenPaymentTerminalStore is ReentrancyGuard, IJBSingleTokenPay ? _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. + 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) ); @@ -775,12 +769,9 @@ contract JBSingleTokenPaymentTerminalStore is ReentrancyGuard, IJBSingleTokenPay @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) - { + 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); @@ -890,7 +881,7 @@ contract JBSingleTokenPaymentTerminalStore is ReentrancyGuard, IJBSingleTokenPay 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. + 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) ); @@ -934,9 +925,13 @@ contract JBSingleTokenPaymentTerminalStore is ReentrancyGuard, IJBSingleTokenPay } // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals. - uint256 _totalOverflow18Decimal = _currency == JBCurrencies.ETH + uint256 _totalOverflow18Decimal = _currency == JBCurrencies.GAS_CURRENCY ? _ethOverflow - : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.ETH, _currency, 18)); + : PRBMath.mulDiv( + _ethOverflow, + 10 ** 18, + prices.priceFor(JBCurrencies.GAS_CURRENCY, _currency, 18) + ); // Adjust the decimals of the fixed point number if needed to match the target decimals. return diff --git a/contracts/JBSingleTokenPaymentTerminalStore3_1.sol b/contracts/JBSingleTokenPaymentTerminalStore3_1.sol index a783f3b8c..fde44fe22 100644 --- a/contracts/JBSingleTokenPaymentTerminalStore3_1.sol +++ b/contracts/JBSingleTokenPaymentTerminalStore3_1.sol @@ -150,12 +150,10 @@ contract JBSingleTokenPaymentTerminalStore3_1 is @return The current amount of overflow that project has in the specified terminal. */ - function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId) - external - view - override - returns (uint256) - { + function currentOverflowOf( + IJBSingleTokenPaymentTerminal _terminal, + uint256 _projectId + ) external view override returns (uint256) { // Return the overflow during the project's current funding cycle. return _overflowDuring( @@ -283,11 +281,7 @@ contract JBSingleTokenPaymentTerminalStore3_1 is @param _fundingCycleStore A contract storing all funding cycle configurations. @param _prices A contract that exposes price feeds. */ - constructor( - IJBDirectory _directory, - IJBFundingCycleStore _fundingCycleStore, - IJBPrices _prices - ) { + constructor(IJBDirectory _directory, IJBFundingCycleStore _fundingCycleStore, IJBPrices _prices) { directory = _directory; fundingCycleStore = _fundingCycleStore; prices = _prices; @@ -420,7 +414,7 @@ contract JBSingleTokenPaymentTerminalStore3_1 is // 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 + ? 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. @@ -647,7 +641,7 @@ contract JBSingleTokenPaymentTerminalStore3_1 is ? _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. + 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) ); @@ -725,7 +719,7 @@ contract JBSingleTokenPaymentTerminalStore3_1 is ? _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. + 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) ); @@ -779,12 +773,9 @@ contract JBSingleTokenPaymentTerminalStore3_1 is @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) - { + 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); @@ -899,7 +890,7 @@ contract JBSingleTokenPaymentTerminalStore3_1 is 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. + 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) ); @@ -943,9 +934,13 @@ contract JBSingleTokenPaymentTerminalStore3_1 is } // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals. - uint256 _totalOverflow18Decimal = _currency == JBCurrencies.ETH + uint256 _totalOverflow18Decimal = _currency == JBCurrencies.GAS_CURRENCY ? _ethOverflow - : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.ETH, _currency, 18)); + : PRBMath.mulDiv( + _ethOverflow, + 10 ** 18, + prices.priceFor(JBCurrencies.GAS_CURRENCY, _currency, 18) + ); // Adjust the decimals of the fixed point number if needed to match the target decimals. return diff --git a/contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol b/contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol index a7b714f95..f0b16dbf4 100644 --- a/contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol +++ b/contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol @@ -194,13 +194,9 @@ abstract contract JBPayoutRedemptionPaymentTerminal is @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals. */ - function currentEthOverflowOf(uint256 _projectId) - external - view - virtual - override - returns (uint256) - { + function currentEthOverflowOf( + uint256 _projectId + ) external view virtual override returns (uint256) { // Get this terminal's current overflow. uint256 _overflow = store.currentOverflowOf(this, _projectId); @@ -211,12 +207,12 @@ abstract contract JBPayoutRedemptionPaymentTerminal is // Return the amount converted to ETH. return - (currency == JBCurrencies.ETH) + (currency == JBCurrencies.GAS_CURRENCY) ? _adjustedOverflow : PRBMath.mulDiv( _adjustedOverflow, - 10**decimals, - prices.priceFor(currency, JBCurrencies.ETH, decimals) + 10 ** decimals, + prices.priceFor(currency, JBCurrencies.GAS_CURRENCY, decimals) ); } @@ -245,13 +241,9 @@ abstract contract JBPayoutRedemptionPaymentTerminal is @param _interfaceId The ID of the interface to check for adherance to. */ - function supportsInterface(bytes4 _interfaceId) - public - view - virtual - override(JBSingleTokenPaymentTerminal, IERC165) - returns (bool) - { + function supportsInterface( + bytes4 _interfaceId + ) public view virtual override(JBSingleTokenPaymentTerminal, IERC165) returns (bool) { return _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId || _interfaceId == type(IJBPayoutTerminal).interfaceId || @@ -353,7 +345,7 @@ abstract contract JBPayoutRedemptionPaymentTerminal is _token; // Prevents unused var compiler and natspec complaints. // ETH shouldn't be sent if this terminal's token isn't ETH. - if (token != JBTokens.ETH) { + if (token != JBTokens.GAS_TOKEN) { if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED(); // Get a reference to the balance before receiving tokens. @@ -516,7 +508,10 @@ abstract contract JBPayoutRedemptionPaymentTerminal is @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal. */ - function migrate(uint256 _projectId, IJBPaymentTerminal _to) + function migrate( + uint256 _projectId, + IJBPaymentTerminal _to + ) external virtual override @@ -535,7 +530,7 @@ abstract contract JBPayoutRedemptionPaymentTerminal is _beforeTransferTo(address(_to), balance); // If this terminal's token is ETH, send it in msg.value. - uint256 _payableValue = token == JBTokens.ETH ? balance : 0; + uint256 _payableValue = token == JBTokens.GAS_TOKEN ? balance : 0; // Withdraw the balance to transfer to the new terminal; _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes('')); @@ -564,7 +559,7 @@ abstract contract JBPayoutRedemptionPaymentTerminal is _token; // Prevents unused var compiler and natspec complaints. // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender. - if (token != JBTokens.ETH) { + if (token != JBTokens.GAS_TOKEN) { // Amount must be greater than 0. if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED(); @@ -593,7 +588,9 @@ abstract contract JBPayoutRedemptionPaymentTerminal is @param _projectId The ID of the project whos held fees should be processed. */ - function processFees(uint256 _projectId) + function processFees( + uint256 _projectId + ) external virtual override @@ -697,11 +694,7 @@ abstract contract JBPayoutRedemptionPaymentTerminal is @param _to The address to which the transfer should go. @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal. */ - function _transferFrom( - address _from, - address payable _to, - uint256 _amount - ) internal virtual { + function _transferFrom(address _from, address payable _to, uint256 _amount) internal virtual { _from; // Prevents unused var compiler and natspec complaints. _to; // Prevents unused var compiler and natspec complaints. _amount; // Prevents unused var compiler and natspec complaints. @@ -808,7 +801,7 @@ abstract contract JBPayoutRedemptionPaymentTerminal is uint256 _payableValue; // If this terminal's token is ETH, send it in msg.value. - if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount; + if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount; // Pass the correct token forwardedAmount to the delegate _data.forwardedAmount.value = _delegateAllocation.amount; @@ -1117,7 +1110,9 @@ abstract contract JBPayoutRedemptionPaymentTerminal is // Trigger the allocator's `allocate` function. // If this terminal's token is ETH, send it in msg.value. - _split.allocator.allocate{value: token == JBTokens.ETH ? _netPayoutAmount : 0}(_data); + _split.allocator.allocate{value: token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0}( + _data + ); // Otherwise, if a project is specified, make a payment to it. } else if (_split.projectId != 0) { @@ -1169,7 +1164,7 @@ abstract contract JBPayoutRedemptionPaymentTerminal is _beforeTransferTo(address(_terminal), _netPayoutAmount); // If this terminal's token is ETH, send it in msg.value. - uint256 _payableValue = token == JBTokens.ETH ? _netPayoutAmount : 0; + uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0; // Send the projectId in the metadata. bytes memory _projectMetadata = new bytes(32); @@ -1302,7 +1297,7 @@ abstract contract JBPayoutRedemptionPaymentTerminal is _beforeTransferTo(address(_terminal), _amount); // If this terminal's token is ETH, send it in msg.value. - uint256 _payableValue = token == JBTokens.ETH ? _amount : 0; + uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _amount : 0; // Send the payment. _terminal.pay{value: _payableValue}( @@ -1416,7 +1411,7 @@ abstract contract JBPayoutRedemptionPaymentTerminal is uint256 _payableValue; // If this terminal's token is ETH, send it in msg.value. - if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount; + if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount; // Pass the correct token forwardedAmount to the delegate _data.forwardedAmount.value = _delegateAllocation.amount; @@ -1486,10 +1481,10 @@ abstract contract JBPayoutRedemptionPaymentTerminal is @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal */ - function _refundHeldFees(uint256 _projectId, uint256 _amount) - internal - returns (uint256 refundedFees) - { + function _refundHeldFees( + uint256 _projectId, + uint256 _amount + ) internal returns (uint256 refundedFees) { // Get a reference to the project's held fees. JBFee[] memory _heldFees = _heldFeesOf[_projectId]; diff --git a/contracts/abstract/JBPayoutRedemptionPaymentTerminal3_1.sol b/contracts/abstract/JBPayoutRedemptionPaymentTerminal3_1.sol index 59291d676..9ddd95b30 100644 --- a/contracts/abstract/JBPayoutRedemptionPaymentTerminal3_1.sol +++ b/contracts/abstract/JBPayoutRedemptionPaymentTerminal3_1.sol @@ -195,13 +195,9 @@ abstract contract JBPayoutRedemptionPaymentTerminal3_1 is @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals. */ - function currentEthOverflowOf(uint256 _projectId) - external - view - virtual - override - returns (uint256) - { + function currentEthOverflowOf( + uint256 _projectId + ) external view virtual override returns (uint256) { // Get this terminal's current overflow. uint256 _overflow = store.currentOverflowOf(this, _projectId); @@ -212,12 +208,12 @@ abstract contract JBPayoutRedemptionPaymentTerminal3_1 is // Return the amount converted to ETH. return - (currency == JBCurrencies.ETH) + (currency == JBCurrencies.GAS_CURRENCY) ? _adjustedOverflow : PRBMath.mulDiv( _adjustedOverflow, - 10**decimals, - prices.priceFor(currency, JBCurrencies.ETH, decimals) + 10 ** decimals, + prices.priceFor(currency, JBCurrencies.GAS_CURRENCY, decimals) ); } @@ -246,13 +242,9 @@ abstract contract JBPayoutRedemptionPaymentTerminal3_1 is @param _interfaceId The ID of the interface to check for adherance to. */ - function supportsInterface(bytes4 _interfaceId) - public - view - virtual - override(JBSingleTokenPaymentTerminal, IERC165) - returns (bool) - { + function supportsInterface( + bytes4 _interfaceId + ) public view virtual override(JBSingleTokenPaymentTerminal, IERC165) returns (bool) { return _interfaceId == type(IJBPayoutRedemptionPaymentTerminal3_1).interfaceId || _interfaceId == type(IJBPayoutTerminal3_1).interfaceId || @@ -354,7 +346,7 @@ abstract contract JBPayoutRedemptionPaymentTerminal3_1 is _token; // Prevents unused var compiler and natspec complaints. // ETH shouldn't be sent if this terminal's token isn't ETH. - if (token != JBTokens.ETH) { + if (token != JBTokens.GAS_TOKEN) { if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED(); // Get a reference to the balance before receiving tokens. @@ -528,7 +520,10 @@ abstract contract JBPayoutRedemptionPaymentTerminal3_1 is @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal. */ - function migrate(uint256 _projectId, IJBPaymentTerminal _to) + function migrate( + uint256 _projectId, + IJBPaymentTerminal _to + ) external virtual override @@ -547,7 +542,7 @@ abstract contract JBPayoutRedemptionPaymentTerminal3_1 is _beforeTransferTo(address(_to), balance); // If this terminal's token is ETH, send it in msg.value. - uint256 _payableValue = token == JBTokens.ETH ? balance : 0; + uint256 _payableValue = token == JBTokens.GAS_TOKEN ? balance : 0; // Withdraw the balance to transfer to the new terminal; _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes('')); @@ -586,7 +581,9 @@ abstract contract JBPayoutRedemptionPaymentTerminal3_1 is @param _projectId The ID of the project whos held fees should be processed. */ - function processFees(uint256 _projectId) + function processFees( + uint256 _projectId + ) external virtual override @@ -704,7 +701,7 @@ abstract contract JBPayoutRedemptionPaymentTerminal3_1 is _token; // Prevents unused var compiler and natspec complaints. // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender. - if (token != JBTokens.ETH) { + if (token != JBTokens.GAS_TOKEN) { // Amount must be greater than 0. if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED(); @@ -736,11 +733,7 @@ abstract contract JBPayoutRedemptionPaymentTerminal3_1 is @param _to The address to which the transfer should go. @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal. */ - function _transferFrom( - address _from, - address payable _to, - uint256 _amount - ) internal virtual { + function _transferFrom(address _from, address payable _to, uint256 _amount) internal virtual { _from; // Prevents unused var compiler and natspec complaints. _to; // Prevents unused var compiler and natspec complaints. _amount; // Prevents unused var compiler and natspec complaints. @@ -859,7 +852,7 @@ abstract contract JBPayoutRedemptionPaymentTerminal3_1 is uint256 _payableValue; // If this terminal's token is ETH, send it in msg.value. - if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount; + if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount; // Pass the correct token forwardedAmount to the delegate _data.forwardedAmount.value = _delegateAllocation.amount; @@ -1224,15 +1217,14 @@ abstract contract JBPayoutRedemptionPaymentTerminal3_1 is ) ) // If this terminal's token is ETH, send it in msg.value. - try _split.allocator.allocate{value: token == JBTokens.ETH ? netPayoutAmount : 0}(_data) { - - } catch (bytes memory reason) { + try + _split.allocator.allocate{value: token == JBTokens.GAS_TOKEN ? netPayoutAmount : 0}(_data) + {} catch (bytes memory reason) { _reason = reason; _error = 1; } else _error = 2; - if (_error != 0) { // Trigger any inhereted post-transfer cancelation logic. _cancelTransferTo(address(_split.allocator), netPayoutAmount); @@ -1243,7 +1235,13 @@ abstract contract JBPayoutRedemptionPaymentTerminal3_1 is // Add undistributed amount back to project's balance. store.recordAddedBalanceFor(_projectId, _amount); - emit PayoutReverted(_projectId, _split, _amount, _error == 1 ? _reason : abi.encode("IERC165 fail"), msg.sender); + emit PayoutReverted( + _projectId, + _split, + _amount, + _error == 1 ? _reason : abi.encode('IERC165 fail'), + msg.sender + ); } // Otherwise, if a project is specified, make a payment to it. @@ -1278,7 +1276,7 @@ abstract contract JBPayoutRedemptionPaymentTerminal3_1 is // Add to balance if prefered. if (_split.preferAddToBalance) try - _terminal.addToBalanceOf{value: token == JBTokens.ETH ? netPayoutAmount : 0}( + _terminal.addToBalanceOf{value: token == JBTokens.GAS_TOKEN ? netPayoutAmount : 0}( _split.projectId, netPayoutAmount, token, @@ -1299,7 +1297,7 @@ abstract contract JBPayoutRedemptionPaymentTerminal3_1 is } else try - _terminal.pay{value: token == JBTokens.ETH ? netPayoutAmount : 0}( + _terminal.pay{value: token == JBTokens.GAS_TOKEN ? netPayoutAmount : 0}( _split.projectId, netPayoutAmount, token, @@ -1385,16 +1383,12 @@ abstract contract JBPayoutRedemptionPaymentTerminal3_1 is @param _beneficiary The address to mint the platform's tokens for. @param _from The project ID the fee is being paid from. */ - function _processFee( - uint256 _amount, - address _beneficiary, - uint256 _from - ) internal { + function _processFee(uint256 _amount, address _beneficiary, uint256 _from) internal { // Get the terminal for the protocol project. IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token); // If this terminal's token is ETH, send it in msg.value. - uint256 _payableValue = token == JBTokens.ETH ? _amount : 0; + uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _amount : 0; // Send the projectId in the metadata. bytes memory _projectMetadata = new bytes(32); @@ -1422,7 +1416,7 @@ abstract contract JBPayoutRedemptionPaymentTerminal3_1 is // Add fee amount back to project's balance. store.recordAddedBalanceFor(_from, _amount); - emit FeeReverted(_from, _FEE_BENEFICIARY_PROJECT_ID, _amount, reason, msg.sender); + emit FeeReverted(_from, _FEE_BENEFICIARY_PROJECT_ID, _amount, reason, msg.sender); } } @@ -1524,7 +1518,7 @@ abstract contract JBPayoutRedemptionPaymentTerminal3_1 is uint256 _payableValue; // If this terminal's token is ETH, send it in msg.value. - if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount; + if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount; // Pass the correct token forwardedAmount to the delegate _data.forwardedAmount.value = _delegateAllocation.amount; @@ -1594,10 +1588,10 @@ abstract contract JBPayoutRedemptionPaymentTerminal3_1 is @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal */ - function _refundHeldFees(uint256 _projectId, uint256 _amount) - internal - returns (uint256 refundedFees) - { + function _refundHeldFees( + uint256 _projectId, + uint256 _amount + ) internal returns (uint256 refundedFees) { // Get a reference to the project's held fees. JBFee[] memory _heldFees = _heldFeesOf[_projectId]; diff --git a/contracts/interfaces/IJBETHERC20ProjectPayerDeployer.sol b/contracts/interfaces/IJBETHERC20ProjectPayerDeployer.sol index 803e2c893..89d66ef42 100644 --- a/contracts/interfaces/IJBETHERC20ProjectPayerDeployer.sol +++ b/contracts/interfaces/IJBETHERC20ProjectPayerDeployer.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.0; import './IJBDirectory.sol'; import './IJBProjectPayer.sol'; -interface IJBETHERC20ProjectPayerDeployer { +interface IJBGasTokenERC20ProjectPayerDeployer { event DeployProjectPayer( IJBProjectPayer indexed projectPayer, uint256 defaultProjectId, diff --git a/contracts/interfaces/IJBETHERC20SplitsPayerDeployer.sol b/contracts/interfaces/IJBETHERC20SplitsPayerDeployer.sol index c704d9675..f11f591c1 100644 --- a/contracts/interfaces/IJBETHERC20SplitsPayerDeployer.sol +++ b/contracts/interfaces/IJBETHERC20SplitsPayerDeployer.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.0; import './IJBSplitsPayer.sol'; import './IJBSplitsStore.sol'; -interface IJBETHERC20SplitsPayerDeployer { +interface IJBGasTokenERC20SplitsPayerDeployer { event DeploySplitsPayer( IJBSplitsPayer indexed splitsPayer, uint256 defaultSplitsProjectId, diff --git a/contracts/libraries/JBCurrencies.sol b/contracts/libraries/JBCurrencies.sol index 55e92803e..9d2424c8f 100644 --- a/contracts/libraries/JBCurrencies.sol +++ b/contracts/libraries/JBCurrencies.sol @@ -2,6 +2,6 @@ pragma solidity ^0.8.0; library JBCurrencies { - uint256 public constant ETH = 1; + uint256 public constant GAS_CURRENCY = 1; uint256 public constant USD = 2; } diff --git a/contracts/libraries/JBSplitsGroups.sol b/contracts/libraries/JBSplitsGroups.sol index a9468536a..6086577c1 100644 --- a/contracts/libraries/JBSplitsGroups.sol +++ b/contracts/libraries/JBSplitsGroups.sol @@ -2,6 +2,6 @@ pragma solidity ^0.8.0; library JBSplitsGroups { - uint256 public constant ETH_PAYOUT = 1; + uint256 public constant GAS_TOKEN_PAYOUT = 1; uint256 public constant RESERVED_TOKENS = 2; } diff --git a/contracts/libraries/JBTokens.sol b/contracts/libraries/JBTokens.sol index b2c1c9967..c9abd31c4 100644 --- a/contracts/libraries/JBTokens.sol +++ b/contracts/libraries/JBTokens.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.0; library JBTokens { /** @notice - The ETH token address in Juicebox is represented by 0x000000000000000000000000000000000000EEEe. + The GAS_CURRENCY token address in Juicebox is represented by 0x000000000000000000000000000000000000EEEe. */ - address public constant ETH = address(0x000000000000000000000000000000000000EEEe); + address public constant GAS_CURRENCY = address(0x000000000000000000000000000000000000EEEe); } diff --git a/deploy/1.js b/deploy/1.js index 75f0b9e1c..e9a0acd5b 100644 --- a/deploy/1.js +++ b/deploy/1.js @@ -163,16 +163,16 @@ module.exports = async ({ deployments, getChainId }) => { ], }); - // Deploy a JBETHERC20ProjectPayerDeployer contract. - await deploy('JBETHERC20ProjectPayerDeployer', { + // Deploy a JBGasTokenERC20ProjectPayerDeployer contract. + await deploy('JBGasTokenERC20ProjectPayerDeployer', { ...baseDeployArgs, args: [JBDirectory.address], }); - // Deploy a JBETHERC20SplitsPayerDeployer contract. - await deploy('JBETHERC20SplitsPayerDeployer', { + // Deploy a JBGasTokenERC20SplitsPayerDeployer contract. + await deploy('JBGasTokenERC20SplitsPayerDeployer', { ...baseDeployArgs, - contract: 'contracts/JBETHERC20SplitsPayerDeployer.sol:JBETHERC20SplitsPayerDeployer', + contract: 'contracts/JBGasTokenERC20SplitsPayerDeployer.sol:JBGasTokenERC20SplitsPayerDeployer', args: [JBSplitStore.address], }); @@ -344,11 +344,11 @@ module.exports = async ({ deployments, getChainId }) => { /*mustStartAtOrAfter*/ ethers.BigNumber.from(protocolProjectStartsAtOrAfter), - /*groupedSplits*/ [groupedSplits], + /*groupedSplits*/[groupedSplits], - /*fundAccessConstraints*/ [], + /*fundAccessConstraints*/[], - /*terminals*/ [JBETHPaymentTerminal.address], + /*terminals*/[JBETHPaymentTerminal.address], /*memo*/ '', ); diff --git a/deploy/splits_and_project_payer.js b/deploy/splits_and_project_payer.js index faab6fc14..d2028feee 100644 --- a/deploy/splits_and_project_payer.js +++ b/deploy/splits_and_project_payer.js @@ -46,21 +46,21 @@ module.exports = async ({ deployments, getChainId }) => { console.log({ multisigAddress, jbDirectory }); - // Deploy a JBETHERC20ProjectPayerDeployer contract. - let jbProjectPayer = await deploy('JBETHERC20ProjectPayerDeployer', { + // Deploy a JBGasTokenERC20ProjectPayerDeployer contract. + let jbProjectPayer = await deploy('JBGasTokenERC20ProjectPayerDeployer', { ...baseDeployArgs, args: [jbDirectory], }); - // Deploy a JBETHERC20SplitsPayerDeployer contract. - let jbSplitsPayer = await deploy('JBETHERC20SplitsPayerDeployer', { + // Deploy a JBGasTokenERC20SplitsPayerDeployer contract. + let jbSplitsPayer = await deploy('JBGasTokenERC20SplitsPayerDeployer', { ...baseDeployArgs, - contract: 'contracts/JBETHERC20SplitsPayerDeployer.sol:JBETHERC20SplitsPayerDeployer', + contract: 'contracts/JBGasTokenERC20SplitsPayerDeployer.sol:JBGasTokenERC20SplitsPayerDeployer', args: [jbSplitsStore], }); - console.log('JBETHERC20ProjectPayerDeployer address: ' + jbProjectPayer.address); - console.log('JBETHERC20SplitsPayerDeployer address: ' + jbSplitsPayer.address); + console.log('JBGasTokenERC20ProjectPayerDeployer address: ' + jbProjectPayer.address); + console.log('JBGasTokenERC20SplitsPayerDeployer address: ' + jbSplitsPayer.address); console.log('Done'); }; diff --git a/deploy/v3_1.js b/deploy/v3_1.js index c05f84403..f41239ae0 100644 --- a/deploy/v3_1.js +++ b/deploy/v3_1.js @@ -14,7 +14,7 @@ module.exports = async ({ deployments, getChainId }) => { const [deployer] = await ethers.getSigners(); let governanceAddress; - let chainlinkV2UsdEthPriceFeed; + let chainlinkV2UsdGasCurrencyPriceFeed; let chainId = await getChainId(); let baseDeployArgs = { from: deployer.address, @@ -29,15 +29,20 @@ module.exports = async ({ deployments, getChainId }) => { // mainnet case '1': governanceAddress = '0xAF28bcB48C40dBC86f52D459A6562F658fc94B1e'; - chainlinkV2UsdEthPriceFeed = '0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419'; + chainlinkV2UsdGasCurrencyPriceFeed = '0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419'; protocolProjectStartsAtOrAfter = 1664047173; break; // Goerli case '5': governanceAddress = '0x46D623731E179FAF971CdA04fF8c499C95461b3c'; - chainlinkV2UsdEthPriceFeed = '0xD4a33860578De61DBAbDc8BFdb98FD742fA7028e'; + chainlinkV2UsdGasCurrencyPriceFeed = '0xD4a33860578De61DBAbDc8BFdb98FD742fA7028e'; protocolProjectStartsAtOrAfter = 0; break; + // Polygon + case '137': + governanceAddress = '0x34d7b8E14bB7Aae027bd59B6A4aF671A2b48F86B'; + chainlinkV2UsdGasCurrencyPriceFeed = '0xab594600376ec9fd91f8e885dadf0ce036862de0'; + protocolProjectStartsAtOrAfter = 0; // hardhat / localhost case '31337': governanceAddress = deployer.address; @@ -158,16 +163,16 @@ module.exports = async ({ deployments, getChainId }) => { const jbProjectsContract = new ethers.Contract(JBProjects.address, JBProjects.abi); const jbCurrenciesLibrary = new ethers.Contract(JBCurrencies.address, JBCurrencies.abi); - // Get a reference to USD and ETH currency indexes. + // Get a reference to USD and GAS_TOKEN currency indexes. const USD = await jbCurrenciesLibrary.connect(deployer).USD(); - const ETH = await jbCurrenciesLibrary.connect(deployer).ETH(); + const GAS_CURRENCY = await jbCurrenciesLibrary.connect(deployer).GAS_CURRENCY(); - // Deploy a JBETHPaymentTerminal contract. - const JBETHPaymentTerminal = await deploy('JBETHPaymentTerminal3_1', { + // Deploy a JBGasTokenPaymentTerminal contract. + const JBGasTokenPaymentTerminal = await deploy('JBGasTokenPaymentTerminal3_1', { ...baseDeployArgs, - contract: 'contracts/JBETHPaymentTerminal3_1.sol:JBETHPaymentTerminal3_1', + contract: 'contracts/JBGasTokenPaymentTerminal3_1.sol:JBGasTokenPaymentTerminal3_1', args: [ - ETH, + GAS_CURRENCY, JBOperatorStore.address, JBProjects.address, JBDirectory.address, @@ -178,34 +183,34 @@ module.exports = async ({ deployments, getChainId }) => { ], }); - // Deploy a JBETHERC20ProjectPayerDeployer contract. - await deploy('JBETHERC20ProjectPayerDeployer', { + // Deploy a JBGasTokenERC20ProjectPayerDeployer contract. + await deploy('JBGasTokenERC20ProjectPayerDeployer', { ...baseDeployArgs, args: [JBDirectory.address], }); - // Deploy a JBETHERC20SplitsPayerDeployer contract. - await deploy('JBETHERC20SplitsPayerDeployer', { + // Deploy a JBGasTokenERC20SplitsPayerDeployer contract. + await deploy('JBGasTokenERC20SplitsPayerDeployer', { ...baseDeployArgs, - contract: 'contracts/JBETHERC20SplitsPayerDeployer.sol:JBETHERC20SplitsPayerDeployer', + contract: 'contracts/JBGasTokenERC20SplitsPayerDeployer.sol:JBGasTokenERC20SplitsPayerDeployer', args: [JBSplitStore.address], }); - // Get a reference to an existing ETH/USD feed. - const usdEthFeed = await jbPricesContract.connect(deployer).feedFor(USD, ETH); + // Get a reference to an existing GasCurrency/USD feed. + const usdGasCurrencyFeed = await jbPricesContract.connect(deployer).feedFor(USD, GAS_CURRENCY); - // If needed, deploy an ETH/USD price feed and add it to the store. - if (chainlinkV2UsdEthPriceFeed && usdEthFeed == ethers.constants.AddressZero) { - // Deploy a JBChainlinkV3PriceFeed contract for ETH/USD. - const JBChainlinkV3UsdEthPriceFeed = await deploy('JBChainlinkV3PriceFeed', { + // If needed, deploy an GasCurrency/USD price feed and add it to the store. + if (chainlinkV2UsdGasCurrencyPriceFeed && usdGasCurrencyFeed == ethers.constants.AddressZero) { + // Deploy a JBChainlinkV3PriceFeed contract for GAS_TOKEN/USD. + const JBChainlinkV3UsdGasCurrencyPriceFeed = await deploy('JBChainlinkV3PriceFeed', { ...baseDeployArgs, - args: [chainlinkV2UsdEthPriceFeed], + args: [chainlinkV2UsdGasCurrencyPriceFeed], }); - //The base currency is ETH since the feed returns the USD price of 1 ETH. + //The base currency is GAS_TOKEN since the feed returns the USD price of 1 GAS_TOKEN. await jbPricesContract .connect(deployer) - .addFeedFor(USD, ETH, JBChainlinkV3UsdEthPriceFeed.address); + .addFeedFor(USD, GAS_TOKEN, JBChainlinkV3UsdGasCurrencyPriceFeed.address); } // If needed, transfer the ownership of the JBPrices to to the multisig. @@ -257,6 +262,95 @@ module.exports = async ({ deployments, getChainId }) => { args: [604800], }); + // // If needed, deploy the protocol project + // if ((await jbProjects.connect(deployer).count()) == 0) { + // console.log('Adding reserved token splits with current beneficiaries (as of deployment)'); + + // const beneficiaries = []; + + // let splits = []; + + // beneficiaries.map((beneficiary) => { + // splits.push({ + // preferClaimed: false, + // preferAddToBalance: false, + // percent: (1000000000 - 300600000) / beneficiaries.length, // 30.06% for JBDao + // projectId: 0, + // beneficiary: beneficiary, + // lockedUntil: 0, + // allocator: ethers.constants.AddressZero, + // }); + // }); + + // splits.push({ + // preferClaimed: false, + // preferAddToBalance: false, + // percent: 300600000, // 30.06% for JBDao + // projectId: 0, + // beneficiary: '0xaf28bcb48c40dbc86f52d459a6562f658fc94b1e', + // lockedUntil: 0, + // allocator: ethers.constants.AddressZero, + // }); + + // let groupedSplits = { + // group: 2, + // splits: splits, + // }; + + // console.log('Deploying protocol project...'); + + // await jbControllerContract.connect(deployer).launchProjectFor( + // /*owner*/ governanceAddress, + + // /* projectMetadata */ + // [ + // /*content*/ 'QmQHGuXv7nDh1rxj48HnzFtwvVxwF1KU9AfB6HbfG8fmJF', + // /*domain*/ ethers.BigNumber.from(0), + // ], + + // /*fundingCycleData*/ + // [ + // /*duration*/ ethers.BigNumber.from(1209600), + // /*weight*/ ethers.BigNumber.from('62850518250000000000000'), + // /*discountRate*/ ethers.BigNumber.from(5000000), + // /*ballot*/ JB3DayReconfigurationBufferBallot.address, + // ], + + // /*fundingCycleMetadata*/ + // [ + // /*global*/ + // [/*allowSetTerminals*/ false, /*allowSetController*/ true, /*pauseTransfer*/ true], + // /*reservedRate*/ ethers.BigNumber.from(5000), + // /*redemptionRate*/ ethers.BigNumber.from(0), + // /*ballotRedemptionRate*/ ethers.BigNumber.from(0), + // /*pausePay*/ false, + // /*pauseDistributions*/ false, + // /*pauseRedeem*/ false, + // /*pauseBurn*/ false, + // /*allowMinting*/ false, + // /*allowTerminalMigration*/ false, + // /*allowControllerMigration*/ false, + // /*holdFees*/ false, + // /*preferClaimedTokenOverride*/ false, + // /*useTotalOverflowForRedemptions*/ false, + // /*useDataSourceForPay*/ false, + // /*useDataSourceForRedeem*/ false, + // /*dataSource*/ ethers.constants.AddressZero, + // /*metadata*/ 0, + // ], + + // /*mustStartAtOrAfter*/ ethers.BigNumber.from(protocolProjectStartsAtOrAfter), + + // /*groupedSplits*/[groupedSplits], + + // /*fundAccessConstraints*/[], + + // /*terminals*/[JBGasTokenPaymentTerminal.address], + + // /*memo*/ '', + // ); + // } + console.log('Done'); }; diff --git a/deployments/goerli/JBETHERC20ProjectPayerDeployer.json b/deployments/goerli/JBETHERC20ProjectPayerDeployer.json index 8557bce16..1b088638b 100644 --- a/deployments/goerli/JBETHERC20ProjectPayerDeployer.json +++ b/deployments/goerli/JBETHERC20ProjectPayerDeployer.json @@ -165,11 +165,11 @@ ], "numDeployments": 1, "solcInputHash": "e87fd161fb98793b8dd4dcaee81afb88", - "metadata": "{\"compiler\":{\"version\":\"0.8.16+commit.07a7930e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IJBDirectory\",\"name\":\"_directory\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IJBProjectPayer\",\"name\":\"projectPayer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"defaultProjectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"defaultBeneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"defaultPreferClaimedTokens\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"defaultMemo\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"defaultMetadata\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"preferAddToBalance\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"contract IJBDirectory\",\"name\":\"directory\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"DeployProjectPayer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_defaultProjectId\",\"type\":\"uint256\"},{\"internalType\":\"address payable\",\"name\":\"_defaultBeneficiary\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_defaultPreferClaimedTokens\",\"type\":\"bool\"},{\"internalType\":\"string\",\"name\":\"_defaultMemo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_defaultMetadata\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"_defaultPreferAddToBalance\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"deployProjectPayer\",\"outputs\":[{\"internalType\":\"contract IJBProjectPayer\",\"name\":\"projectPayer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Adheres to - IJBETHERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_directory\":\"A contract storing directories of terminals and controllers for each project.\"}},\"deployProjectPayer(uint256,address,bool,string,bytes,bool,address)\":{\"params\":{\"_defaultBeneficiary\":\"The address that'll receive the project's tokens when the project payer receives payments. \",\"_defaultMemo\":\"The memo that'll be forwarded with the project payer's received payments. \",\"_defaultMetadata\":\"The metadata that'll be forwarded with the project payer's received payments. \",\"_defaultPreferAddToBalance\":\"A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\",\"_defaultPreferClaimedTokens\":\"A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \",\"_defaultProjectId\":\"The ID of the project whose treasury should be forwarded the project payer contract's received payments.\",\"_owner\":\"The address that will own the project payer.\"},\"returns\":{\"projectPayer\":\"The project payer contract.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"deployProjectPayer(uint256,address,bool,string,bytes,bool,address)\":{\"notice\":\" Allows anyone to deploy a new project payer contract.\"}},\"notice\":\" Deploys project payer contracts.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/JBETHERC20ProjectPayerDeployer.sol\":\"JBETHERC20ProjectPayerDeployer\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0x24e0364e503a9bbde94c715d26573a76f14cd2a202d45f96f52134ab806b67b9\",\"license\":\"MIT\"},\"@openzeppelin/contracts/proxy/Clones.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/Clones.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for\\n * deploying minimal proxy contracts, also known as \\\"clones\\\".\\n *\\n * > To simply and cheaply clone contract functionality in an immutable way, this standard specifies\\n * > a minimal bytecode implementation that delegates all calls to a known, fixed address.\\n *\\n * The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2`\\n * (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the\\n * deterministic method.\\n *\\n * _Available since v3.4._\\n */\\nlibrary Clones {\\n /**\\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.\\n *\\n * This function uses the create opcode, which should never revert.\\n */\\n function clone(address implementation) internal returns (address instance) {\\n assembly {\\n let ptr := mload(0x40)\\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\\n mstore(add(ptr, 0x14), shl(0x60, implementation))\\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\\n instance := create(0, ptr, 0x37)\\n }\\n require(instance != address(0), \\\"ERC1167: create failed\\\");\\n }\\n\\n /**\\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.\\n *\\n * This function uses the create2 opcode and a `salt` to deterministically deploy\\n * the clone. Using the same `implementation` and `salt` multiple time will revert, since\\n * the clones cannot be deployed twice at the same address.\\n */\\n function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) {\\n assembly {\\n let ptr := mload(0x40)\\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\\n mstore(add(ptr, 0x14), shl(0x60, implementation))\\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\\n instance := create2(0, ptr, 0x37, salt)\\n }\\n require(instance != address(0), \\\"ERC1167: create2 failed\\\");\\n }\\n\\n /**\\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\\n */\\n function predictDeterministicAddress(\\n address implementation,\\n bytes32 salt,\\n address deployer\\n ) internal pure returns (address predicted) {\\n assembly {\\n let ptr := mload(0x40)\\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\\n mstore(add(ptr, 0x14), shl(0x60, implementation))\\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf3ff00000000000000000000000000000000)\\n mstore(add(ptr, 0x38), shl(0x60, deployer))\\n mstore(add(ptr, 0x4c), salt)\\n mstore(add(ptr, 0x6c), keccak256(ptr, 0x37))\\n predicted := keccak256(add(ptr, 0x37), 0x55)\\n }\\n }\\n\\n /**\\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\\n */\\n function predictDeterministicAddress(address implementation, bytes32 salt)\\n internal\\n view\\n returns (address predicted)\\n {\\n return predictDeterministicAddress(implementation, salt, address(this));\\n }\\n}\\n\",\"keccak256\":\"0x1cc0efb01cbf008b768fd7b334786a6e358809198bb7e67f1c530af4957c6a21\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address sender,\\n address recipient,\\n uint256 amount\\n ) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0x61437cb513a887a1bbad006e7b1c8b414478427d33de47c5600af3c748f108da\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(\\n IERC20 token,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(\\n IERC20 token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) {\\n // Return data is optional\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xc3d946432c0ddbb1f846a0d3985be71299df331b91d06732152117f62f0be2b5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool _approved) external;\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x516a22876c1fab47f49b1bc22b4614491cd05338af8bd2e7b382da090a079990\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3777e696b62134e6177440dbe6e6601c0c156a443f57167194b67e75527439de\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"contracts/JBETHERC20ProjectPayer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport '@openzeppelin/contracts/access/Ownable.sol';\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\\nimport './interfaces/IJBProjectPayer.sol';\\nimport './libraries/JBTokens.sol';\\n\\n/** \\n @notice \\n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\\n\\n @dev\\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\\n\\n @dev\\n Adheres to -\\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n\\n @dev\\n Inherits from -\\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\\n ERC165: Introspection on interface adherance. \\n*/\\ncontract JBETHERC20ProjectPayer is Ownable, ERC165, IJBProjectPayer {\\n using SafeERC20 for IERC20;\\n\\n //*********************************************************************//\\n // -------------------------- custom errors -------------------------- //\\n //*********************************************************************//\\n error INCORRECT_DECIMAL_AMOUNT();\\n error ALREADY_INITIALIZED();\\n error NO_MSG_VALUE_ALLOWED();\\n error TERMINAL_NOT_FOUND();\\n\\n //*********************************************************************//\\n // ------------------- public immutable properties ------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice \\n A contract storing directories of terminals and controllers for each project.\\n */\\n IJBDirectory public immutable override directory;\\n\\n /**\\n @notice \\n The deployer associated with this implementation. Used to rule out double initialization.\\n */\\n address public immutable override projectPayerDeployer;\\n\\n //*********************************************************************//\\n // --------------------- public stored properties -------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n The ID of the project that should be used to forward this contract's received payments.\\n */\\n uint256 public override defaultProjectId;\\n\\n /** \\n @notice \\n The beneficiary that should be used in the payment made when this contract receives payments.\\n */\\n address payable public override defaultBeneficiary;\\n\\n /** \\n @notice \\n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\\n */\\n bool public override defaultPreferClaimedTokens;\\n\\n /** \\n @notice \\n The memo that should be used in the payment made when this contract receives payments.\\n */\\n string public override defaultMemo;\\n\\n /** \\n @notice \\n The metadata that should be used in the payment made when this contract receives payments.\\n */\\n bytes public override defaultMetadata;\\n\\n /**\\n @notice \\n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\\n */\\n bool public override defaultPreferAddToBalance;\\n\\n //*********************************************************************//\\n // ------------------------- public views ---------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Indicates if this contract adheres to the specified interface.\\n\\n @dev \\n See {IERC165-supportsInterface}.\\n\\n @param _interfaceId The ID of the interface to check for adherance to.\\n */\\n function supportsInterface(bytes4 _interfaceId)\\n public\\n view\\n virtual\\n override(ERC165, IERC165)\\n returns (bool)\\n {\\n return\\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\\n }\\n\\n //*********************************************************************//\\n // -------------------------- constructors --------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @dev This is the constructor of the implementation. The directory is shared between project payers and is\\n immutable. If a new JBDirectory is needed, a new JBProjectPayerDeployer should be deployed.\\n @param _directory A contract storing directories of terminals and controllers for each project.\\n */\\n constructor(IJBDirectory _directory) {\\n directory = _directory;\\n projectPayerDeployer = msg.sender;\\n }\\n\\n /** \\n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\\n @param _defaultBeneficiary The address that'll receive the project's tokens. \\n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \\n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\\n @param _owner The address that will own the contract.\\n */\\n function initialize(\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string memory _defaultMemo,\\n bytes memory _defaultMetadata,\\n bool _defaultPreferAddToBalance,\\n address _owner\\n ) public {\\n if(msg.sender != projectPayerDeployer) revert ALREADY_INITIALIZED();\\n\\n defaultProjectId = _defaultProjectId;\\n defaultBeneficiary = _defaultBeneficiary;\\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\\n defaultMemo = _defaultMemo;\\n defaultMetadata = _defaultMetadata;\\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\\n _transferOwnership(_owner);\\n }\\n\\n //*********************************************************************//\\n // ------------------------- default receive ------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Received funds are paid to the default project ID using the stored default properties.\\n\\n @dev\\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\\n\\n @dev\\n This function is called automatically when the contract receives an ETH payment.\\n */\\n receive() external payable virtual override {\\n if (defaultPreferAddToBalance)\\n _addToBalanceOf(\\n defaultProjectId,\\n JBTokens.ETH,\\n address(this).balance,\\n 18, // balance is a fixed point number with 18 decimals.\\n defaultMemo,\\n defaultMetadata\\n );\\n else\\n _pay(\\n defaultProjectId,\\n JBTokens.ETH,\\n address(this).balance,\\n 18, // balance is a fixed point number with 18 decimals.\\n defaultBeneficiary == address(0) ? tx.origin : defaultBeneficiary,\\n 0, // Can't determine expectation of returned tokens ahead of time.\\n defaultPreferClaimedTokens,\\n defaultMemo,\\n defaultMetadata\\n );\\n }\\n\\n //*********************************************************************//\\n // ---------------------- external transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\\n\\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\\n @param _beneficiary The address that'll receive the project's tokens. \\n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \\n @param _memo The memo that'll be used. \\n @param _metadata The metadata that'll be sent. \\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\\n */\\n function setDefaultValues(\\n uint256 _projectId,\\n address payable _beneficiary,\\n bool _preferClaimedTokens,\\n string memory _memo,\\n bytes memory _metadata,\\n bool _defaultPreferAddToBalance\\n ) external virtual override onlyOwner {\\n // Set the default project ID if it has changed.\\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\\n\\n // Set the default beneficiary if it has changed.\\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\\n\\n // Set the default claimed token preference if it has changed.\\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\\n defaultPreferClaimedTokens = _preferClaimedTokens;\\n\\n // Set the default memo if it has changed.\\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\\n defaultMemo = _memo;\\n\\n // Set the default metadata if it has changed.\\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\\n defaultMetadata = _metadata;\\n\\n // Set the add to balance preference if it has changed.\\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\\n\\n emit SetDefaultValues(\\n _projectId,\\n _beneficiary,\\n _preferClaimedTokens,\\n _memo,\\n _metadata,\\n _defaultPreferAddToBalance,\\n msg.sender\\n );\\n }\\n\\n //*********************************************************************//\\n // ----------------------- public transactions ----------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n Make a payment to the specified project.\\n\\n @param _projectId The ID of the project that is being paid.\\n @param _token The token being paid in.\\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\\n @param _beneficiary The address who will receive tokens from the payment.\\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\\n */\\n function pay(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) public payable virtual override {\\n // ETH shouldn't be sent if the token isn't ETH.\\n if (address(_token) != JBTokens.ETH) {\\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\\n\\n // Get a reference to the balance before receiving tokens.\\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\\n\\n // Transfer tokens to this contract from the msg sender.\\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\\n\\n // The amount should reflect the change in balance.\\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\\n } else {\\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\\n _amount = msg.value;\\n _decimals = 18;\\n }\\n\\n _pay(\\n _projectId,\\n _token,\\n _amount,\\n _decimals,\\n _beneficiary,\\n _minReturnedTokens,\\n _preferClaimedTokens,\\n _memo,\\n _metadata\\n );\\n }\\n\\n /** \\n @notice \\n Add to the balance of the specified project.\\n\\n @param _projectId The ID of the project that is being paid.\\n @param _token The token being paid in.\\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Extra data to pass along to the terminal.\\n */\\n function addToBalanceOf(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) public payable virtual override {\\n // ETH shouldn't be sent if the token isn't ETH.\\n if (address(_token) != JBTokens.ETH) {\\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\\n\\n // Get a reference to the balance before receiving tokens.\\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\\n\\n // Transfer tokens to this contract from the msg sender.\\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\\n\\n // The amount should reflect the change in balance.\\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\\n } else {\\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\\n _amount = msg.value;\\n _decimals = 18;\\n }\\n\\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\\n }\\n\\n //*********************************************************************//\\n // ---------------------- internal transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n Make a payment to the specified project.\\n\\n @param _projectId The ID of the project that is being paid.\\n @param _token The token being paid in.\\n @param _amount The amount of tokens being paid, as a fixed point number. \\n @param _decimals The number of decimals in the `_amount` fixed point number. \\n @param _beneficiary The address who will receive tokens from the payment.\\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _metadata Bytes to send along to the data source and delegate, if provided.\\n */\\n function _pay(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string memory _memo,\\n bytes memory _metadata\\n ) internal virtual {\\n // Find the terminal for the specified project.\\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\\n\\n // There must be a terminal.\\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\\n\\n // The amount's decimals must match the terminal's expected decimals.\\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\\n\\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\\n if (_token != JBTokens.ETH) IERC20(_token).safeApprove(address(_terminal), _amount);\\n\\n // If the token is ETH, send it in msg.value.\\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\\n\\n // Send funds to the terminal.\\n // If the token is ETH, send it in msg.value.\\n _terminal.pay{value: _payableValue}(\\n _projectId,\\n _amount, // ignored if the token is JBTokens.ETH.\\n _token,\\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\\n ? defaultBeneficiary\\n : tx.origin,\\n _minReturnedTokens,\\n _preferClaimedTokens,\\n _memo,\\n _metadata\\n );\\n }\\n\\n /** \\n @notice \\n Add to the balance of the specified project.\\n\\n @param _projectId The ID of the project that is being paid.\\n @param _token The token being paid in.\\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Extra data to pass along to the terminal.\\n */\\n function _addToBalanceOf(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n string memory _memo,\\n bytes memory _metadata\\n ) internal virtual {\\n // Find the terminal for the specified project.\\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\\n\\n // There must be a terminal.\\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\\n\\n // The amount's decimals must match the terminal's expected decimals.\\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\\n\\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\\n if (_token != JBTokens.ETH) IERC20(_token).safeApprove(address(_terminal), _amount);\\n\\n // If the token is ETH, send it in msg.value.\\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\\n\\n // Add to balance so tokens don't get issued.\\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\\n }\\n}\\n\",\"keccak256\":\"0xcbadf8e217bb9c43d18161ce576235277834988ea7cb51d58b5a794914e9156c\",\"license\":\"MIT\"},\"contracts/JBETHERC20ProjectPayerDeployer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport { Clones } from '@openzeppelin/contracts/proxy/Clones.sol';\\n\\nimport './interfaces/IJBETHERC20ProjectPayerDeployer.sol';\\nimport './JBETHERC20ProjectPayer.sol';\\n\\n/** \\n @notice \\n Deploys project payer contracts.\\n\\n @dev\\n Adheres to -\\n IJBETHERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n*/\\ncontract JBETHERC20ProjectPayerDeployer is IJBETHERC20ProjectPayerDeployer {\\n\\n address immutable implementation;\\n\\n IJBDirectory immutable directory;\\n\\n /**\\n @param _directory A contract storing directories of terminals and controllers for each project.\\n */\\n constructor(IJBDirectory _directory) {\\n implementation = address(new JBETHERC20ProjectPayer(_directory));\\n directory = _directory;\\n }\\n\\n //*********************************************************************//\\n // ---------------------- external transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n Allows anyone to deploy a new project payer contract.\\n\\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the project payer contract's received payments.\\n @param _defaultBeneficiary The address that'll receive the project's tokens when the project payer receives payments. \\n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \\n @param _defaultMemo The memo that'll be forwarded with the project payer's received payments. \\n @param _defaultMetadata The metadata that'll be forwarded with the project payer's received payments. \\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\\n @param _owner The address that will own the project payer.\\n\\n @return projectPayer The project payer contract.\\n */\\n function deployProjectPayer(\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string memory _defaultMemo,\\n bytes memory _defaultMetadata,\\n bool _defaultPreferAddToBalance,\\n address _owner\\n ) external override returns (IJBProjectPayer projectPayer) {\\n // Deploy the project payer.\\n projectPayer = IJBProjectPayer(payable(Clones.clone(implementation)));\\n\\n // Initialize the project payer.\\n projectPayer.initialize(\\n _defaultProjectId,\\n _defaultBeneficiary,\\n _defaultPreferClaimedTokens,\\n _defaultMemo,\\n _defaultMetadata,\\n _defaultPreferAddToBalance,\\n _owner\\n );\\n\\n emit DeployProjectPayer(\\n projectPayer,\\n _defaultProjectId,\\n _defaultBeneficiary,\\n _defaultPreferClaimedTokens,\\n _defaultMemo,\\n _defaultMetadata,\\n _defaultPreferAddToBalance,\\n directory,\\n _owner,\\n msg.sender\\n );\\n }\\n}\\n\",\"keccak256\":\"0xe8aac15e115cad48d4a84437f4415e8e6852855bba9062a1d2eff6848b83c44f\",\"license\":\"MIT\"},\"contracts/enums/JBBallotState.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nenum JBBallotState {\\n Active,\\n Approved,\\n Failed\\n}\\n\",\"keccak256\":\"0x891fcac63470398b3a11239da7feba6b07d640809fcefd2404303b823d7378f8\",\"license\":\"MIT\"},\"contracts/interfaces/IJBDirectory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBProjects.sol';\\n\\ninterface IJBDirectory {\\n event SetController(uint256 indexed projectId, address indexed controller, address caller);\\n\\n event AddTerminal(uint256 indexed projectId, IJBPaymentTerminal indexed terminal, address caller);\\n\\n event SetTerminals(uint256 indexed projectId, IJBPaymentTerminal[] terminals, address caller);\\n\\n event SetPrimaryTerminal(\\n uint256 indexed projectId,\\n address indexed token,\\n IJBPaymentTerminal indexed terminal,\\n address caller\\n );\\n\\n event SetIsAllowedToSetFirstController(address indexed addr, bool indexed flag, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function controllerOf(uint256 _projectId) external view returns (address);\\n\\n function isAllowedToSetFirstController(address _address) external view returns (bool);\\n\\n function terminalsOf(uint256 _projectId) external view returns (IJBPaymentTerminal[] memory);\\n\\n function isTerminalOf(uint256 _projectId, IJBPaymentTerminal _terminal)\\n external\\n view\\n returns (bool);\\n\\n function primaryTerminalOf(uint256 _projectId, address _token)\\n external\\n view\\n returns (IJBPaymentTerminal);\\n\\n function setControllerOf(uint256 _projectId, address _controller) external;\\n\\n function setTerminalsOf(uint256 _projectId, IJBPaymentTerminal[] calldata _terminals) external;\\n\\n function setPrimaryTerminalOf(\\n uint256 _projectId,\\n address _token,\\n IJBPaymentTerminal _terminal\\n ) external;\\n\\n function setIsAllowedToSetFirstController(address _address, bool _flag) external;\\n}\\n\",\"keccak256\":\"0x715321646db00514d1355ed43c40cd3f01e94959552fd07797b315d9c49cdb1d\",\"license\":\"MIT\"},\"contracts/interfaces/IJBETHERC20ProjectPayerDeployer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBDirectory.sol';\\nimport './IJBProjectPayer.sol';\\n\\ninterface IJBETHERC20ProjectPayerDeployer {\\n event DeployProjectPayer(\\n IJBProjectPayer indexed projectPayer,\\n uint256 defaultProjectId,\\n address defaultBeneficiary,\\n bool defaultPreferClaimedTokens,\\n string defaultMemo,\\n bytes defaultMetadata,\\n bool preferAddToBalance,\\n IJBDirectory directory,\\n address owner,\\n address caller\\n );\\n\\n function deployProjectPayer(\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string memory _defaultMemo,\\n bytes memory _defaultMetadata,\\n bool _preferAddToBalance,\\n address _owner\\n ) external returns (IJBProjectPayer projectPayer);\\n}\\n\",\"keccak256\":\"0x69b364b5e637bc641d453d30aa66b8b8a8f024e0117c892246367344a1d12e64\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleBallot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../enums/JBBallotState.sol';\\n\\ninterface IJBFundingCycleBallot is IERC165 {\\n function duration() external view returns (uint256);\\n\\n function stateOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n uint256 _start\\n ) external view returns (JBBallotState);\\n}\\n\",\"keccak256\":\"0x49553a56209237846bc400cf27f260824a6bd06fd8094a7eb5abb9de75779598\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../enums/JBBallotState.sol';\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBFundingCycleData.sol';\\n\\ninterface IJBFundingCycleStore {\\n event Configure(\\n uint256 indexed configuration,\\n uint256 indexed projectId,\\n JBFundingCycleData data,\\n uint256 metadata,\\n uint256 mustStartAtOrAfter,\\n address caller\\n );\\n\\n event Init(uint256 indexed configuration, uint256 indexed projectId, uint256 indexed basedOn);\\n\\n function latestConfigurationOf(uint256 _projectId) external view returns (uint256);\\n\\n function get(uint256 _projectId, uint256 _configuration)\\n external\\n view\\n returns (JBFundingCycle memory);\\n\\n function latestConfiguredOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBBallotState ballotState);\\n\\n function queuedOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentBallotStateOf(uint256 _projectId) external view returns (JBBallotState);\\n\\n function configureFor(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n uint256 _metadata,\\n uint256 _mustStartAtOrAfter\\n ) external returns (JBFundingCycle memory fundingCycle);\\n}\\n\",\"keccak256\":\"0xaead823851433be0c2ddc8f8086813e6cd647de3a1bc0f7570a5d6b38c378b5a\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\n\\ninterface IJBPaymentTerminal is IERC165 {\\n function acceptsToken(address _token, uint256 _projectId) external view returns (bool);\\n\\n function currencyForToken(address _token) external view returns (uint256);\\n\\n function decimalsForToken(address _token) external view returns (uint256);\\n\\n // Return value must be a fixed point number with 18 decimals.\\n function currentEthOverflowOf(uint256 _projectId) external view returns (uint256);\\n\\n function pay(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable returns (uint256 beneficiaryTokenCount);\\n\\n function addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable;\\n}\\n\",\"keccak256\":\"0xb7826f5ed609359ce322c09e83236c47ba385df1c3cad3607e56fd0a2e00eee2\",\"license\":\"MIT\"},\"contracts/interfaces/IJBProjectPayer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './IJBDirectory.sol';\\n\\ninterface IJBProjectPayer is IERC165 {\\n event SetDefaultValues(\\n uint256 indexed projectId,\\n address indexed beneficiary,\\n bool preferClaimedTokens,\\n string memo,\\n bytes metadata,\\n bool preferAddToBalance,\\n address caller\\n );\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function projectPayerDeployer() external view returns (address);\\n\\n function defaultProjectId() external view returns (uint256);\\n\\n function defaultBeneficiary() external view returns (address payable);\\n\\n function defaultPreferClaimedTokens() external view returns (bool);\\n\\n function defaultMemo() external view returns (string memory);\\n\\n function defaultMetadata() external view returns (bytes memory);\\n\\n function defaultPreferAddToBalance() external view returns (bool);\\n\\n function initialize(\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string memory _defaultMemo,\\n bytes memory _defaultMetadata,\\n bool _defaultPreferAddToBalance,\\n address _owner\\n ) external;\\n\\n function setDefaultValues(\\n uint256 _projectId,\\n address payable _beneficiary,\\n bool _preferClaimedTokens,\\n string memory _memo,\\n bytes memory _metadata,\\n bool _defaultPreferAddToBalance\\n ) external;\\n\\n function pay(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string memory _memo,\\n bytes memory _metadata\\n ) external payable;\\n\\n function addToBalanceOf(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n string memory _memo,\\n bytes memory _metadata\\n ) external payable;\\n\\n receive() external payable;\\n}\\n\",\"keccak256\":\"0x85f4cbd5482e26618994f742c149a5bd3cb3dc39dbeba85b21c36b3215007df6\",\"license\":\"MIT\"},\"contracts/interfaces/IJBProjects.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBTokenUriResolver.sol';\\n\\ninterface IJBProjects is IERC721 {\\n event Create(\\n uint256 indexed projectId,\\n address indexed owner,\\n JBProjectMetadata metadata,\\n address caller\\n );\\n\\n event SetMetadata(uint256 indexed projectId, JBProjectMetadata metadata, address caller);\\n\\n event SetTokenUriResolver(IJBTokenUriResolver indexed resolver, address caller);\\n\\n function count() external view returns (uint256);\\n\\n function metadataContentOf(uint256 _projectId, uint256 _domain)\\n external\\n view\\n returns (string memory);\\n\\n function tokenUriResolver() external view returns (IJBTokenUriResolver);\\n\\n function createFor(address _owner, JBProjectMetadata calldata _metadata)\\n external\\n returns (uint256 projectId);\\n\\n function setMetadataOf(uint256 _projectId, JBProjectMetadata calldata _metadata) external;\\n\\n function setTokenUriResolver(IJBTokenUriResolver _newResolver) external;\\n}\\n\",\"keccak256\":\"0x7cfc021d0bd7e73b1ba8f4845d7d35e3419d6a14d3d25ca3a8010e7f91062fe4\",\"license\":\"MIT\"},\"contracts/interfaces/IJBTokenUriResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBTokenUriResolver {\\n function getUri(uint256 _projectId) external view returns (string memory tokenUri);\\n}\\n\",\"keccak256\":\"0xd267fd8ca7c21c2c71794acdb9a98314c33a35fc559e0bf0897a6686d196d174\",\"license\":\"MIT\"},\"contracts/libraries/JBTokens.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBTokens {\\n /** \\n @notice \\n The ETH token address in Juicebox is represented by 0x000000000000000000000000000000000000EEEe.\\n */\\n address public constant ETH = address(0x000000000000000000000000000000000000EEEe);\\n}\\n\",\"keccak256\":\"0xecf82992f7b827766aa55f16872517a646521eef414d8cc9786617ea377e5463\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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.\\n @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.\\n @member basedOn The `configuration` of the funding cycle that was active when this cycle was created.\\n @member start The timestamp marking the moment from which the funding cycle is considered active. It is a unix timestamp measured in seconds.\\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n @member metadata Extra data that can be associated with a funding cycle.\\n*/\\nstruct JBFundingCycle {\\n uint256 number;\\n uint256 configuration;\\n uint256 basedOn;\\n uint256 start;\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n uint256 metadata;\\n}\\n\",\"keccak256\":\"0xcdd3ac9b6fa67e62ada88d09b73bc35ade1cd77d43db712289266a788928b4c2\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycleData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n*/\\nstruct JBFundingCycleData {\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n}\\n\",\"keccak256\":\"0x2aa6368bf4dfc5797e8b02a978293de0c777fae2658de2c825a103587240f3b0\",\"license\":\"MIT\"},\"contracts/structs/JBProjectMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member content The metadata content.\\n @member domain The domain within which the metadata applies.\\n*/\\nstruct JBProjectMetadata {\\n string content;\\n uint256 domain;\\n}\\n\",\"keccak256\":\"0x90ad7b1014c0a9f945fe7a2efde9d5de41e40574fa27969070b1d2ff52033ea0\",\"license\":\"MIT\"}},\"version\":1}", + "metadata": "{\"compiler\":{\"version\":\"0.8.16+commit.07a7930e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IJBDirectory\",\"name\":\"_directory\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IJBProjectPayer\",\"name\":\"projectPayer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"defaultProjectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"defaultBeneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"defaultPreferClaimedTokens\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"defaultMemo\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"defaultMetadata\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"preferAddToBalance\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"contract IJBDirectory\",\"name\":\"directory\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"DeployProjectPayer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_defaultProjectId\",\"type\":\"uint256\"},{\"internalType\":\"address payable\",\"name\":\"_defaultBeneficiary\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_defaultPreferClaimedTokens\",\"type\":\"bool\"},{\"internalType\":\"string\",\"name\":\"_defaultMemo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_defaultMetadata\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"_defaultPreferAddToBalance\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"deployProjectPayer\",\"outputs\":[{\"internalType\":\"contract IJBProjectPayer\",\"name\":\"projectPayer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Adheres to - IJBGasTokenERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_directory\":\"A contract storing directories of terminals and controllers for each project.\"}},\"deployProjectPayer(uint256,address,bool,string,bytes,bool,address)\":{\"params\":{\"_defaultBeneficiary\":\"The address that'll receive the project's tokens when the project payer receives payments. \",\"_defaultMemo\":\"The memo that'll be forwarded with the project payer's received payments. \",\"_defaultMetadata\":\"The metadata that'll be forwarded with the project payer's received payments. \",\"_defaultPreferAddToBalance\":\"A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\",\"_defaultPreferClaimedTokens\":\"A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \",\"_defaultProjectId\":\"The ID of the project whose treasury should be forwarded the project payer contract's received payments.\",\"_owner\":\"The address that will own the project payer.\"},\"returns\":{\"projectPayer\":\"The project payer contract.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"deployProjectPayer(uint256,address,bool,string,bytes,bool,address)\":{\"notice\":\" Allows anyone to deploy a new project payer contract.\"}},\"notice\":\" Deploys project payer contracts.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/JBGasTokenERC20ProjectPayerDeployer.sol\":\"JBGasTokenERC20ProjectPayerDeployer\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0x24e0364e503a9bbde94c715d26573a76f14cd2a202d45f96f52134ab806b67b9\",\"license\":\"MIT\"},\"@openzeppelin/contracts/proxy/Clones.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/Clones.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for\\n * deploying minimal proxy contracts, also known as \\\"clones\\\".\\n *\\n * > To simply and cheaply clone contract functionality in an immutable way, this standard specifies\\n * > a minimal bytecode implementation that delegates all calls to a known, fixed address.\\n *\\n * The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2`\\n * (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the\\n * deterministic method.\\n *\\n * _Available since v3.4._\\n */\\nlibrary Clones {\\n /**\\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.\\n *\\n * This function uses the create opcode, which should never revert.\\n */\\n function clone(address implementation) internal returns (address instance) {\\n assembly {\\n let ptr := mload(0x40)\\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\\n mstore(add(ptr, 0x14), shl(0x60, implementation))\\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\\n instance := create(0, ptr, 0x37)\\n }\\n require(instance != address(0), \\\"ERC1167: create failed\\\");\\n }\\n\\n /**\\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.\\n *\\n * This function uses the create2 opcode and a `salt` to deterministically deploy\\n * the clone. Using the same `implementation` and `salt` multiple time will revert, since\\n * the clones cannot be deployed twice at the same address.\\n */\\n function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) {\\n assembly {\\n let ptr := mload(0x40)\\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\\n mstore(add(ptr, 0x14), shl(0x60, implementation))\\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\\n instance := create2(0, ptr, 0x37, salt)\\n }\\n require(instance != address(0), \\\"ERC1167: create2 failed\\\");\\n }\\n\\n /**\\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\\n */\\n function predictDeterministicAddress(\\n address implementation,\\n bytes32 salt,\\n address deployer\\n ) internal pure returns (address predicted) {\\n assembly {\\n let ptr := mload(0x40)\\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\\n mstore(add(ptr, 0x14), shl(0x60, implementation))\\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf3ff00000000000000000000000000000000)\\n mstore(add(ptr, 0x38), shl(0x60, deployer))\\n mstore(add(ptr, 0x4c), salt)\\n mstore(add(ptr, 0x6c), keccak256(ptr, 0x37))\\n predicted := keccak256(add(ptr, 0x37), 0x55)\\n }\\n }\\n\\n /**\\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\\n */\\n function predictDeterministicAddress(address implementation, bytes32 salt)\\n internal\\n view\\n returns (address predicted)\\n {\\n return predictDeterministicAddress(implementation, salt, address(this));\\n }\\n}\\n\",\"keccak256\":\"0x1cc0efb01cbf008b768fd7b334786a6e358809198bb7e67f1c530af4957c6a21\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address sender,\\n address recipient,\\n uint256 amount\\n ) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0x61437cb513a887a1bbad006e7b1c8b414478427d33de47c5600af3c748f108da\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(\\n IERC20 token,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(\\n IERC20 token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) {\\n // Return data is optional\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xc3d946432c0ddbb1f846a0d3985be71299df331b91d06732152117f62f0be2b5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool _approved) external;\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x516a22876c1fab47f49b1bc22b4614491cd05338af8bd2e7b382da090a079990\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3777e696b62134e6177440dbe6e6601c0c156a443f57167194b67e75527439de\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"contracts/JBGasTokenERC20ProjectPayer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport '@openzeppelin/contracts/access/Ownable.sol';\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\\nimport './interfaces/IJBProjectPayer.sol';\\nimport './libraries/JBTokens.sol';\\n\\n/** \\n @notice \\n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\\n\\n @dev\\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\\n\\n @dev\\n Adheres to -\\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n\\n @dev\\n Inherits from -\\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\\n ERC165: Introspection on interface adherance. \\n*/\\ncontract JBGasTokenERC20ProjectPayer is Ownable, ERC165, IJBProjectPayer {\\n using SafeERC20 for IERC20;\\n\\n //*********************************************************************//\\n // -------------------------- custom errors -------------------------- //\\n //*********************************************************************//\\n error INCORRECT_DECIMAL_AMOUNT();\\n error ALREADY_INITIALIZED();\\n error NO_MSG_VALUE_ALLOWED();\\n error TERMINAL_NOT_FOUND();\\n\\n //*********************************************************************//\\n // ------------------- public immutable properties ------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice \\n A contract storing directories of terminals and controllers for each project.\\n */\\n IJBDirectory public immutable override directory;\\n\\n /**\\n @notice \\n The deployer associated with this implementation. Used to rule out double initialization.\\n */\\n address public immutable override projectPayerDeployer;\\n\\n //*********************************************************************//\\n // --------------------- public stored properties -------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n The ID of the project that should be used to forward this contract's received payments.\\n */\\n uint256 public override defaultProjectId;\\n\\n /** \\n @notice \\n The beneficiary that should be used in the payment made when this contract receives payments.\\n */\\n address payable public override defaultBeneficiary;\\n\\n /** \\n @notice \\n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\\n */\\n bool public override defaultPreferClaimedTokens;\\n\\n /** \\n @notice \\n The memo that should be used in the payment made when this contract receives payments.\\n */\\n string public override defaultMemo;\\n\\n /** \\n @notice \\n The metadata that should be used in the payment made when this contract receives payments.\\n */\\n bytes public override defaultMetadata;\\n\\n /**\\n @notice \\n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\\n */\\n bool public override defaultPreferAddToBalance;\\n\\n //*********************************************************************//\\n // ------------------------- public views ---------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Indicates if this contract adheres to the specified interface.\\n\\n @dev \\n See {IERC165-supportsInterface}.\\n\\n @param _interfaceId The ID of the interface to check for adherance to.\\n */\\n function supportsInterface(bytes4 _interfaceId)\\n public\\n view\\n virtual\\n override(ERC165, IERC165)\\n returns (bool)\\n {\\n return\\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\\n }\\n\\n //*********************************************************************//\\n // -------------------------- constructors --------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @dev This is the constructor of the implementation. The directory is shared between project payers and is\\n immutable. If a new JBDirectory is needed, a new JBProjectPayerDeployer should be deployed.\\n @param _directory A contract storing directories of terminals and controllers for each project.\\n */\\n constructor(IJBDirectory _directory) {\\n directory = _directory;\\n projectPayerDeployer = msg.sender;\\n }\\n\\n /** \\n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\\n @param _defaultBeneficiary The address that'll receive the project's tokens. \\n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \\n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\\n @param _owner The address that will own the contract.\\n */\\n function initialize(\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string memory _defaultMemo,\\n bytes memory _defaultMetadata,\\n bool _defaultPreferAddToBalance,\\n address _owner\\n ) public {\\n if(msg.sender != projectPayerDeployer) revert ALREADY_INITIALIZED();\\n\\n defaultProjectId = _defaultProjectId;\\n defaultBeneficiary = _defaultBeneficiary;\\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\\n defaultMemo = _defaultMemo;\\n defaultMetadata = _defaultMetadata;\\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\\n _transferOwnership(_owner);\\n }\\n\\n //*********************************************************************//\\n // ------------------------- default receive ------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Received funds are paid to the default project ID using the stored default properties.\\n\\n @dev\\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\\n\\n @dev\\n This function is called automatically when the contract receives an ETH payment.\\n */\\n receive() external payable virtual override {\\n if (defaultPreferAddToBalance)\\n _addToBalanceOf(\\n defaultProjectId,\\n JBTokens.GAS_TOKEN,\\n address(this).balance,\\n 18, // balance is a fixed point number with 18 decimals.\\n defaultMemo,\\n defaultMetadata\\n );\\n else\\n _pay(\\n defaultProjectId,\\n JBTokens.GAS_TOKEN,\\n address(this).balance,\\n 18, // balance is a fixed point number with 18 decimals.\\n defaultBeneficiary == address(0) ? tx.origin : defaultBeneficiary,\\n 0, // Can't determine expectation of returned tokens ahead of time.\\n defaultPreferClaimedTokens,\\n defaultMemo,\\n defaultMetadata\\n );\\n }\\n\\n //*********************************************************************//\\n // ---------------------- external transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\\n\\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\\n @param _beneficiary The address that'll receive the project's tokens. \\n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \\n @param _memo The memo that'll be used. \\n @param _metadata The metadata that'll be sent. \\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\\n */\\n function setDefaultValues(\\n uint256 _projectId,\\n address payable _beneficiary,\\n bool _preferClaimedTokens,\\n string memory _memo,\\n bytes memory _metadata,\\n bool _defaultPreferAddToBalance\\n ) external virtual override onlyOwner {\\n // Set the default project ID if it has changed.\\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\\n\\n // Set the default beneficiary if it has changed.\\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\\n\\n // Set the default claimed token preference if it has changed.\\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\\n defaultPreferClaimedTokens = _preferClaimedTokens;\\n\\n // Set the default memo if it has changed.\\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\\n defaultMemo = _memo;\\n\\n // Set the default metadata if it has changed.\\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\\n defaultMetadata = _metadata;\\n\\n // Set the add to balance preference if it has changed.\\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\\n\\n emit SetDefaultValues(\\n _projectId,\\n _beneficiary,\\n _preferClaimedTokens,\\n _memo,\\n _metadata,\\n _defaultPreferAddToBalance,\\n msg.sender\\n );\\n }\\n\\n //*********************************************************************//\\n // ----------------------- public transactions ----------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n Make a payment to the specified project.\\n\\n @param _projectId The ID of the project that is being paid.\\n @param _token The token being paid in.\\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\\n @param _beneficiary The address who will receive tokens from the payment.\\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\\n */\\n function pay(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) public payable virtual override {\\n // ETH shouldn't be sent if the token isn't ETH.\\n if (address(_token) != JBTokens.GAS_TOKEN) {\\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\\n\\n // Get a reference to the balance before receiving tokens.\\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\\n\\n // Transfer tokens to this contract from the msg sender.\\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\\n\\n // The amount should reflect the change in balance.\\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\\n } else {\\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\\n _amount = msg.value;\\n _decimals = 18;\\n }\\n\\n _pay(\\n _projectId,\\n _token,\\n _amount,\\n _decimals,\\n _beneficiary,\\n _minReturnedTokens,\\n _preferClaimedTokens,\\n _memo,\\n _metadata\\n );\\n }\\n\\n /** \\n @notice \\n Add to the balance of the specified project.\\n\\n @param _projectId The ID of the project that is being paid.\\n @param _token The token being paid in.\\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Extra data to pass along to the terminal.\\n */\\n function addToBalanceOf(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) public payable virtual override {\\n // ETH shouldn't be sent if the token isn't ETH.\\n if (address(_token) != JBTokens.GAS_TOKEN) {\\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\\n\\n // Get a reference to the balance before receiving tokens.\\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\\n\\n // Transfer tokens to this contract from the msg sender.\\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\\n\\n // The amount should reflect the change in balance.\\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\\n } else {\\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\\n _amount = msg.value;\\n _decimals = 18;\\n }\\n\\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\\n }\\n\\n //*********************************************************************//\\n // ---------------------- internal transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n Make a payment to the specified project.\\n\\n @param _projectId The ID of the project that is being paid.\\n @param _token The token being paid in.\\n @param _amount The amount of tokens being paid, as a fixed point number. \\n @param _decimals The number of decimals in the `_amount` fixed point number. \\n @param _beneficiary The address who will receive tokens from the payment.\\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _metadata Bytes to send along to the data source and delegate, if provided.\\n */\\n function _pay(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string memory _memo,\\n bytes memory _metadata\\n ) internal virtual {\\n // Find the terminal for the specified project.\\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\\n\\n // There must be a terminal.\\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\\n\\n // The amount's decimals must match the terminal's expected decimals.\\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\\n\\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).safeApprove(address(_terminal), _amount);\\n\\n // If the token is ETH, send it in msg.value.\\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\\n\\n // Send funds to the terminal.\\n // If the token is ETH, send it in msg.value.\\n _terminal.pay{value: _payableValue}(\\n _projectId,\\n _amount, // ignored if the token is JBTokens.GAS_TOKEN.\\n _token,\\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\\n ? defaultBeneficiary\\n : tx.origin,\\n _minReturnedTokens,\\n _preferClaimedTokens,\\n _memo,\\n _metadata\\n );\\n }\\n\\n /** \\n @notice \\n Add to the balance of the specified project.\\n\\n @param _projectId The ID of the project that is being paid.\\n @param _token The token being paid in.\\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Extra data to pass along to the terminal.\\n */\\n function _addToBalanceOf(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n string memory _memo,\\n bytes memory _metadata\\n ) internal virtual {\\n // Find the terminal for the specified project.\\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\\n\\n // There must be a terminal.\\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\\n\\n // The amount's decimals must match the terminal's expected decimals.\\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\\n\\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).safeApprove(address(_terminal), _amount);\\n\\n // If the token is ETH, send it in msg.value.\\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\\n\\n // Add to balance so tokens don't get issued.\\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\\n }\\n}\\n\",\"keccak256\":\"0xcbadf8e217bb9c43d18161ce576235277834988ea7cb51d58b5a794914e9156c\",\"license\":\"MIT\"},\"contracts/JBGasTokenERC20ProjectPayerDeployer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport { Clones } from '@openzeppelin/contracts/proxy/Clones.sol';\\n\\nimport './interfaces/IJBGasTokenERC20ProjectPayerDeployer.sol';\\nimport './JBGasTokenERC20ProjectPayer.sol';\\n\\n/** \\n @notice \\n Deploys project payer contracts.\\n\\n @dev\\n Adheres to -\\n IJBGasTokenERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n*/\\ncontract JBGasTokenERC20ProjectPayerDeployer is IJBGasTokenERC20ProjectPayerDeployer {\\n\\n address immutable implementation;\\n\\n IJBDirectory immutable directory;\\n\\n /**\\n @param _directory A contract storing directories of terminals and controllers for each project.\\n */\\n constructor(IJBDirectory _directory) {\\n implementation = address(new JBGasTokenERC20ProjectPayer(_directory));\\n directory = _directory;\\n }\\n\\n //*********************************************************************//\\n // ---------------------- external transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n Allows anyone to deploy a new project payer contract.\\n\\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the project payer contract's received payments.\\n @param _defaultBeneficiary The address that'll receive the project's tokens when the project payer receives payments. \\n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \\n @param _defaultMemo The memo that'll be forwarded with the project payer's received payments. \\n @param _defaultMetadata The metadata that'll be forwarded with the project payer's received payments. \\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\\n @param _owner The address that will own the project payer.\\n\\n @return projectPayer The project payer contract.\\n */\\n function deployProjectPayer(\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string memory _defaultMemo,\\n bytes memory _defaultMetadata,\\n bool _defaultPreferAddToBalance,\\n address _owner\\n ) external override returns (IJBProjectPayer projectPayer) {\\n // Deploy the project payer.\\n projectPayer = IJBProjectPayer(payable(Clones.clone(implementation)));\\n\\n // Initialize the project payer.\\n projectPayer.initialize(\\n _defaultProjectId,\\n _defaultBeneficiary,\\n _defaultPreferClaimedTokens,\\n _defaultMemo,\\n _defaultMetadata,\\n _defaultPreferAddToBalance,\\n _owner\\n );\\n\\n emit DeployProjectPayer(\\n projectPayer,\\n _defaultProjectId,\\n _defaultBeneficiary,\\n _defaultPreferClaimedTokens,\\n _defaultMemo,\\n _defaultMetadata,\\n _defaultPreferAddToBalance,\\n directory,\\n _owner,\\n msg.sender\\n );\\n }\\n}\\n\",\"keccak256\":\"0xe8aac15e115cad48d4a84437f4415e8e6852855bba9062a1d2eff6848b83c44f\",\"license\":\"MIT\"},\"contracts/enums/JBBallotState.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nenum JBBallotState {\\n Active,\\n Approved,\\n Failed\\n}\\n\",\"keccak256\":\"0x891fcac63470398b3a11239da7feba6b07d640809fcefd2404303b823d7378f8\",\"license\":\"MIT\"},\"contracts/interfaces/IJBDirectory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBProjects.sol';\\n\\ninterface IJBDirectory {\\n event SetController(uint256 indexed projectId, address indexed controller, address caller);\\n\\n event AddTerminal(uint256 indexed projectId, IJBPaymentTerminal indexed terminal, address caller);\\n\\n event SetTerminals(uint256 indexed projectId, IJBPaymentTerminal[] terminals, address caller);\\n\\n event SetPrimaryTerminal(\\n uint256 indexed projectId,\\n address indexed token,\\n IJBPaymentTerminal indexed terminal,\\n address caller\\n );\\n\\n event SetIsAllowedToSetFirstController(address indexed addr, bool indexed flag, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function controllerOf(uint256 _projectId) external view returns (address);\\n\\n function isAllowedToSetFirstController(address _address) external view returns (bool);\\n\\n function terminalsOf(uint256 _projectId) external view returns (IJBPaymentTerminal[] memory);\\n\\n function isTerminalOf(uint256 _projectId, IJBPaymentTerminal _terminal)\\n external\\n view\\n returns (bool);\\n\\n function primaryTerminalOf(uint256 _projectId, address _token)\\n external\\n view\\n returns (IJBPaymentTerminal);\\n\\n function setControllerOf(uint256 _projectId, address _controller) external;\\n\\n function setTerminalsOf(uint256 _projectId, IJBPaymentTerminal[] calldata _terminals) external;\\n\\n function setPrimaryTerminalOf(\\n uint256 _projectId,\\n address _token,\\n IJBPaymentTerminal _terminal\\n ) external;\\n\\n function setIsAllowedToSetFirstController(address _address, bool _flag) external;\\n}\\n\",\"keccak256\":\"0x715321646db00514d1355ed43c40cd3f01e94959552fd07797b315d9c49cdb1d\",\"license\":\"MIT\"},\"contracts/interfaces/IJBGasTokenERC20ProjectPayerDeployer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBDirectory.sol';\\nimport './IJBProjectPayer.sol';\\n\\ninterface IJBGasTokenERC20ProjectPayerDeployer {\\n event DeployProjectPayer(\\n IJBProjectPayer indexed projectPayer,\\n uint256 defaultProjectId,\\n address defaultBeneficiary,\\n bool defaultPreferClaimedTokens,\\n string defaultMemo,\\n bytes defaultMetadata,\\n bool preferAddToBalance,\\n IJBDirectory directory,\\n address owner,\\n address caller\\n );\\n\\n function deployProjectPayer(\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string memory _defaultMemo,\\n bytes memory _defaultMetadata,\\n bool _preferAddToBalance,\\n address _owner\\n ) external returns (IJBProjectPayer projectPayer);\\n}\\n\",\"keccak256\":\"0x69b364b5e637bc641d453d30aa66b8b8a8f024e0117c892246367344a1d12e64\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleBallot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../enums/JBBallotState.sol';\\n\\ninterface IJBFundingCycleBallot is IERC165 {\\n function duration() external view returns (uint256);\\n\\n function stateOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n uint256 _start\\n ) external view returns (JBBallotState);\\n}\\n\",\"keccak256\":\"0x49553a56209237846bc400cf27f260824a6bd06fd8094a7eb5abb9de75779598\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../enums/JBBallotState.sol';\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBFundingCycleData.sol';\\n\\ninterface IJBFundingCycleStore {\\n event Configure(\\n uint256 indexed configuration,\\n uint256 indexed projectId,\\n JBFundingCycleData data,\\n uint256 metadata,\\n uint256 mustStartAtOrAfter,\\n address caller\\n );\\n\\n event Init(uint256 indexed configuration, uint256 indexed projectId, uint256 indexed basedOn);\\n\\n function latestConfigurationOf(uint256 _projectId) external view returns (uint256);\\n\\n function get(uint256 _projectId, uint256 _configuration)\\n external\\n view\\n returns (JBFundingCycle memory);\\n\\n function latestConfiguredOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBBallotState ballotState);\\n\\n function queuedOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentBallotStateOf(uint256 _projectId) external view returns (JBBallotState);\\n\\n function configureFor(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n uint256 _metadata,\\n uint256 _mustStartAtOrAfter\\n ) external returns (JBFundingCycle memory fundingCycle);\\n}\\n\",\"keccak256\":\"0xaead823851433be0c2ddc8f8086813e6cd647de3a1bc0f7570a5d6b38c378b5a\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\n\\ninterface IJBPaymentTerminal is IERC165 {\\n function acceptsToken(address _token, uint256 _projectId) external view returns (bool);\\n\\n function currencyForToken(address _token) external view returns (uint256);\\n\\n function decimalsForToken(address _token) external view returns (uint256);\\n\\n // Return value must be a fixed point number with 18 decimals.\\n function currentEthOverflowOf(uint256 _projectId) external view returns (uint256);\\n\\n function pay(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable returns (uint256 beneficiaryTokenCount);\\n\\n function addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable;\\n}\\n\",\"keccak256\":\"0xb7826f5ed609359ce322c09e83236c47ba385df1c3cad3607e56fd0a2e00eee2\",\"license\":\"MIT\"},\"contracts/interfaces/IJBProjectPayer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './IJBDirectory.sol';\\n\\ninterface IJBProjectPayer is IERC165 {\\n event SetDefaultValues(\\n uint256 indexed projectId,\\n address indexed beneficiary,\\n bool preferClaimedTokens,\\n string memo,\\n bytes metadata,\\n bool preferAddToBalance,\\n address caller\\n );\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function projectPayerDeployer() external view returns (address);\\n\\n function defaultProjectId() external view returns (uint256);\\n\\n function defaultBeneficiary() external view returns (address payable);\\n\\n function defaultPreferClaimedTokens() external view returns (bool);\\n\\n function defaultMemo() external view returns (string memory);\\n\\n function defaultMetadata() external view returns (bytes memory);\\n\\n function defaultPreferAddToBalance() external view returns (bool);\\n\\n function initialize(\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string memory _defaultMemo,\\n bytes memory _defaultMetadata,\\n bool _defaultPreferAddToBalance,\\n address _owner\\n ) external;\\n\\n function setDefaultValues(\\n uint256 _projectId,\\n address payable _beneficiary,\\n bool _preferClaimedTokens,\\n string memory _memo,\\n bytes memory _metadata,\\n bool _defaultPreferAddToBalance\\n ) external;\\n\\n function pay(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string memory _memo,\\n bytes memory _metadata\\n ) external payable;\\n\\n function addToBalanceOf(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n string memory _memo,\\n bytes memory _metadata\\n ) external payable;\\n\\n receive() external payable;\\n}\\n\",\"keccak256\":\"0x85f4cbd5482e26618994f742c149a5bd3cb3dc39dbeba85b21c36b3215007df6\",\"license\":\"MIT\"},\"contracts/interfaces/IJBProjects.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBTokenUriResolver.sol';\\n\\ninterface IJBProjects is IERC721 {\\n event Create(\\n uint256 indexed projectId,\\n address indexed owner,\\n JBProjectMetadata metadata,\\n address caller\\n );\\n\\n event SetMetadata(uint256 indexed projectId, JBProjectMetadata metadata, address caller);\\n\\n event SetTokenUriResolver(IJBTokenUriResolver indexed resolver, address caller);\\n\\n function count() external view returns (uint256);\\n\\n function metadataContentOf(uint256 _projectId, uint256 _domain)\\n external\\n view\\n returns (string memory);\\n\\n function tokenUriResolver() external view returns (IJBTokenUriResolver);\\n\\n function createFor(address _owner, JBProjectMetadata calldata _metadata)\\n external\\n returns (uint256 projectId);\\n\\n function setMetadataOf(uint256 _projectId, JBProjectMetadata calldata _metadata) external;\\n\\n function setTokenUriResolver(IJBTokenUriResolver _newResolver) external;\\n}\\n\",\"keccak256\":\"0x7cfc021d0bd7e73b1ba8f4845d7d35e3419d6a14d3d25ca3a8010e7f91062fe4\",\"license\":\"MIT\"},\"contracts/interfaces/IJBTokenUriResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBTokenUriResolver {\\n function getUri(uint256 _projectId) external view returns (string memory tokenUri);\\n}\\n\",\"keccak256\":\"0xd267fd8ca7c21c2c71794acdb9a98314c33a35fc559e0bf0897a6686d196d174\",\"license\":\"MIT\"},\"contracts/libraries/JBTokens.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBTokens {\\n /** \\n @notice \\n The ETH token address in Juicebox is represented by 0x000000000000000000000000000000000000EEEe.\\n */\\n address public constant ETH = address(0x000000000000000000000000000000000000EEEe);\\n}\\n\",\"keccak256\":\"0xecf82992f7b827766aa55f16872517a646521eef414d8cc9786617ea377e5463\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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.\\n @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.\\n @member basedOn The `configuration` of the funding cycle that was active when this cycle was created.\\n @member start The timestamp marking the moment from which the funding cycle is considered active. It is a unix timestamp measured in seconds.\\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n @member metadata Extra data that can be associated with a funding cycle.\\n*/\\nstruct JBFundingCycle {\\n uint256 number;\\n uint256 configuration;\\n uint256 basedOn;\\n uint256 start;\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n uint256 metadata;\\n}\\n\",\"keccak256\":\"0xcdd3ac9b6fa67e62ada88d09b73bc35ade1cd77d43db712289266a788928b4c2\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycleData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n*/\\nstruct JBFundingCycleData {\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n}\\n\",\"keccak256\":\"0x2aa6368bf4dfc5797e8b02a978293de0c777fae2658de2c825a103587240f3b0\",\"license\":\"MIT\"},\"contracts/structs/JBProjectMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member content The metadata content.\\n @member domain The domain within which the metadata applies.\\n*/\\nstruct JBProjectMetadata {\\n string content;\\n uint256 domain;\\n}\\n\",\"keccak256\":\"0x90ad7b1014c0a9f945fe7a2efde9d5de41e40574fa27969070b1d2ff52033ea0\",\"license\":\"MIT\"}},\"version\":1}", "bytecode": "0x60c060405234801561001057600080fd5b50604051612c0f380380612c0f83398101604081905261002f9161008d565b8060405161003c90610080565b6001600160a01b039091168152602001604051809103906000f080158015610068573d6000803e3d6000fd5b506001600160a01b039081166080521660a0526100bd565b612549806106c683390190565b60006020828403121561009f57600080fd5b81516001600160a01b03811681146100b657600080fd5b9392505050565b60805160a0516105e56100e1600039600061016a01526000607301526105e56000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c80635be94a6f14610030575b600080fd5b61004361003e3660046103a8565b61006c565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b60006100977f00000000000000000000000000000000000000000000000000000000000000006101b3565b6040517fc0048ca500000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff82169063c0048ca5906100f8908b908b908b908b908b908b908b906004016104c2565b600060405180830381600087803b15801561011257600080fd5b505af1158015610126573d6000803e3d6000fd5b505050508073ffffffffffffffffffffffffffffffffffffffff167f727d4d4c40bee220af4fdbae0c157cb7a5e5f2ce9c3e9676e8f615cd88bc85df8989898989897f00000000000000000000000000000000000000000000000000000000000000008a336040516101a09998979695949392919061052f565b60405180910390a2979650505050505050565b60006040517f3d602d80600a3d3981f3363d3d373d3d3d363d7300000000000000000000000081528260601b60148201527f5af43d82803e903d91602b57fd5bf3000000000000000000000000000000000060288201526037816000f091505073ffffffffffffffffffffffffffffffffffffffff8116610294576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f455243313136373a20637265617465206661696c656400000000000000000000604482015260640160405180910390fd5b919050565b73ffffffffffffffffffffffffffffffffffffffff811681146102bb57600080fd5b50565b8035801515811461029457600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261030e57600080fd5b813567ffffffffffffffff80821115610329576103296102ce565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561036f5761036f6102ce565b8160405283815286602085880101111561038857600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600080600080600060e0888a0312156103c357600080fd5b8735965060208801356103d581610299565b95506103e3604089016102be565b9450606088013567ffffffffffffffff8082111561040057600080fd5b61040c8b838c016102fd565b955060808a013591508082111561042257600080fd5b5061042f8a828b016102fd565b93505061043e60a089016102be565b915060c088013561044e81610299565b8091505092959891949750929550565b6000815180845260005b8181101561048457602081850181015186830182015201610468565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b878152600073ffffffffffffffffffffffffffffffffffffffff8089166020840152871515604084015260e0606084015261050060e084018861045e565b8381036080850152610512818861045e565b95151560a0850152509290921660c0909101525095945050505050565b60006101208b835273ffffffffffffffffffffffffffffffffffffffff808c1660208501528a1515604085015281606085015261056e8285018b61045e565b91508382036080850152610582828a61045e565b97151560a085015295861660c0840152505091831660e0830152909116610100909101529594505050505056fea2646970667358221220d9813aa7b2c826ebec43fdd21bc1f31e50caf91e73764e970cf07c573a4ea35f64736f6c6343000810003360c06040523480156200001157600080fd5b5060405162002549380380620025498339810160408190526200003491620000a5565b6200003f3362000055565b6001600160a01b03166080523360a052620000d7565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600060208284031215620000b857600080fd5b81516001600160a01b0381168114620000d057600080fd5b9392505050565b60805160a051612437620001126000396000818161046d015261133e01526000818161058a0152818161060e015261087201526124376000f3fe6080604052600436106100f75760003560e01c80638293fee61161008a578063b96053df11610059578063b96053df14610543578063c0048ca514610558578063c41c2f2414610578578063f2fde38b146105ac57600080fd5b80638293fee6146104c65780638da5cb5b146104d957806393b7f154146104f7578063a4919eb11461051157600080fd5b806354ab58af116100c657806354ab58af1461042357806364d3ed271461045b578063715018a61461048f5780637e646549146104a457600080fd5b806301ffc9a71461039757806309a6b7e5146103cc5780630e45f78e146103df5780633ce9830b146103ff57600080fd5b366103925760055460ff16156102305761022e60015461eeee4760126003805461012090611ae9565b80601f016020809104026020016040519081016040528092919081815260200182805461014c90611ae9565b80156101995780601f1061016e57610100808354040283529160200191610199565b820191906000526020600020905b81548152906001019060200180831161017c57829003601f168201915b5050505050600480546101ab90611ae9565b80601f01602080910402602001604051908101604052809291908181526020018280546101d790611ae9565b80156102245780601f106101f957610100808354040283529160200191610224565b820191906000526020600020905b81548152906001019060200180831161020757829003601f168201915b50505050506105cc565b005b60015460025461022e919061eeee9047906012906001600160a01b031615610263576002546001600160a01b0316610265565b325b6000600260149054906101000a900460ff166003805461028490611ae9565b80601f01602080910402602001604051908101604052809291908181526020018280546102b090611ae9565b80156102fd5780601f106102d2576101008083540402835291602001916102fd565b820191906000526020600020905b8154815290600101906020018083116102e057829003601f168201915b50505050506004805461030f90611ae9565b80601f016020809104026020016040519081016040528092919081815260200182805461033b90611ae9565b80156103885780601f1061035d57610100808354040283529160200191610388565b820191906000526020600020905b81548152906001019060200180831161036b57829003601f168201915b5050505050610830565b600080fd5b3480156103a357600080fd5b506103b76103b2366004611b3c565b610af1565b60405190151581526020015b60405180910390f35b61022e6103da366004611bdc565b610b8a565b3480156103eb57600080fd5b5061022e6103fa366004611d73565b610d8d565b34801561040b57600080fd5b5061041560015481565b6040519081526020016103c3565b34801561042f57600080fd5b50600254610443906001600160a01b031681565b6040516001600160a01b0390911681526020016103c3565b34801561046757600080fd5b506104437f000000000000000000000000000000000000000000000000000000000000000081565b34801561049b57600080fd5b5061022e61100f565b3480156104b057600080fd5b506104b961108f565b6040516103c39190611e87565b61022e6104d4366004611e9a565b61111d565b3480156104e557600080fd5b506000546001600160a01b0316610443565b34801561050357600080fd5b506005546103b79060ff1681565b34801561051d57600080fd5b506002546103b79074010000000000000000000000000000000000000000900460ff1681565b34801561054f57600080fd5b506104b9611326565b34801561056457600080fd5b5061022e610573366004611f76565b611333565b34801561058457600080fd5b506104437f000000000000000000000000000000000000000000000000000000000000000081565b3480156105b857600080fd5b5061022e6105c7366004612030565b611442565b6040517f86202650000000000000000000000000000000000000000000000000000000008152600481018790526001600160a01b0386811660248301526000917f000000000000000000000000000000000000000000000000000000000000000090911690638620265090604401602060405180830381865afa158015610657573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061067b919061204d565b90506001600160a01b0381166106bd576040517ffba10dd600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fb7bad1b10000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015285919083169063b7bad1b190602401602060405180830381865afa15801561071f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610743919061206a565b1461077a576040517fb972592400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03861661eeee146107a0576107a06001600160a01b0387168287611558565b60006001600160a01b03871661eeee146107bb5760006107bd565b855b9050816001600160a01b0316630cf8e858828a898b89896040518763ffffffff1660e01b81526004016107f4959493929190612083565b6000604051808303818588803b15801561080d57600080fd5b505af1158015610821573d6000803e3d6000fd5b50505050505050505050505050565b6040517f86202650000000000000000000000000000000000000000000000000000000008152600481018a90526001600160a01b0389811660248301526000917f000000000000000000000000000000000000000000000000000000000000000090911690638620265090604401602060405180830381865afa1580156108bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108df919061204d565b90506001600160a01b038116610921576040517ffba10dd600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fb7bad1b10000000000000000000000000000000000000000000000000000000081526001600160a01b038a8116600483015288919083169063b7bad1b190602401602060405180830381865afa158015610983573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109a7919061206a565b146109de576040517fb972592400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03891661eeee14610a0457610a046001600160a01b038a16828a611558565b60006001600160a01b038a1661eeee14610a1f576000610a21565b885b9050816001600160a01b0316631ebc263f828d8c8e60006001600160a01b03168d6001600160a01b031603610a77576002546001600160a01b0316610a665732610a79565b6002546001600160a01b0316610a79565b8c5b8c8c8c8c6040518a63ffffffff1660e01b8152600401610aa09897969594939291906120cf565b60206040518083038185885af1158015610abe573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610ae3919061206a565b505050505050505050505050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7ddb72fc000000000000000000000000000000000000000000000000000000001480610b8457507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b6001600160a01b03871661eeee14610d04573415610bd4576040517fbcfd35be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038916906370a0823190602401602060405180830381865afa158015610c34573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c58919061206a565b9050610c6f6001600160a01b03891633308a611743565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015281906001600160a01b038a16906370a0823190602401602060405180830381865afa158015610cce573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cf2919061206a565b610cfc9190612139565b965050610d0c565b349550601294505b610d838888888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8c018190048102820181019092528a815292508a91508990819084018382808284376000920191909152506105cc92505050565b5050505050505050565b6000546001600160a01b03163314610e06576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b6001548614610e155760018690555b6002546001600160a01b03868116911614610e5e57600280547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0387161790555b600260149054906101000a900460ff16151584151514610ebc57600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000861515021790555b6003604051602001610ece9190612204565b6040516020818303038152906040528051906020012083604051602001610ef59190612210565b6040516020818303038152906040528051906020012014610f1e576003610f1c848261227a565b505b6004604051602001610f309190612204565b6040516020818303038152906040528051906020012082604051602001610f579190612210565b6040516020818303038152906040528051906020012014610f80576004610f7e838261227a565b505b60055460ff16151581151514610fbd57600580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168215151790555b846001600160a01b0316867f36b1c5cef608e320317b9ee5155756634c65fe7055b424ce57e2f6c59eec79478686868633604051610fff959493929190612394565b60405180910390a3505050505050565b6000546001600160a01b03163314611083576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610dfd565b61108d600061179a565b565b6004805461109c90611ae9565b80601f01602080910402602001604051908101604052809291908181526020018280546110c890611ae9565b80156111155780601f106110ea57610100808354040283529160200191611115565b820191906000526020600020905b8154815290600101906020018083116110f857829003601f168201915b505050505081565b6001600160a01b038a1661eeee14611297573415611167576040517fbcfd35be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038c16906370a0823190602401602060405180830381865afa1580156111c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111eb919061206a565b90506112026001600160a01b038c1633308d611743565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015281906001600160a01b038d16906370a0823190602401602060405180830381865afa158015611261573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611285919061206a565b61128f9190612139565b99505061129f565b349850601297505b6113198b8b8b8b8b8b8b8b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8f018190048102820181019092528d815292508d91508c908190840183828082843760009201919091525061083092505050565b5050505050505050505050565b6003805461109c90611ae9565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611395576040517f439a74c900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018790556002805486151574010000000000000000000000000000000000000000027fffffffffffffffffffffff0000000000000000000000000000000000000000009091166001600160a01b0389161717905560036113f6858261227a565b506004611403848261227a565b50600580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168315151790556114398161179a565b50505050505050565b6000546001600160a01b031633146114b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610dfd565b6001600160a01b03811661154c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610dfd565b6115558161179a565b50565b8015806115eb57506040517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa1580156115c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115e9919061206a565b155b611677576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e6365000000000000000000006064820152608401610dfd565b6040516001600160a01b03831660248201526044810182905261173e9084907f095ea7b300000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611802565b505050565b6040516001600160a01b03808516602483015283166044820152606481018290526117949085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016116bc565b50505050565b600080546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000611857826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166119019092919063ffffffff16565b80519091501561173e578080602001905181019061187591906123e4565b61173e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610dfd565b6060611910848460008561191a565b90505b9392505050565b6060824710156119ac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610dfd565b6001600160a01b0385163b611a1d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610dfd565b600080866001600160a01b03168587604051611a399190612210565b60006040518083038185875af1925050503d8060008114611a76576040519150601f19603f3d011682016040523d82523d6000602084013e611a7b565b606091505b5091509150611a8b828286611a96565b979650505050505050565b60608315611aa5575081611913565b825115611ab55782518084602001fd5b816040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dfd9190611e87565b600181811c90821680611afd57607f821691505b602082108103611b36577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600060208284031215611b4e57600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461191357600080fd5b6001600160a01b038116811461155557600080fd5b60008083601f840112611ba557600080fd5b50813567ffffffffffffffff811115611bbd57600080fd5b602083019150836020828501011115611bd557600080fd5b9250929050565b60008060008060008060008060c0898b031215611bf857600080fd5b883597506020890135611c0a81611b7e565b96506040890135955060608901359450608089013567ffffffffffffffff80821115611c3557600080fd5b611c418c838d01611b93565b909650945060a08b0135915080821115611c5a57600080fd5b50611c678b828c01611b93565b999c989b5096995094979396929594505050565b801515811461155557600080fd5b8035611c9481611c7b565b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f830112611cd957600080fd5b813567ffffffffffffffff80821115611cf457611cf4611c99565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715611d3a57611d3a611c99565b81604052838152866020858801011115611d5357600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c08789031215611d8c57600080fd5b863595506020870135611d9e81611b7e565b94506040870135611dae81611c7b565b9350606087013567ffffffffffffffff80821115611dcb57600080fd5b611dd78a838b01611cc8565b94506080890135915080821115611ded57600080fd5b50611dfa89828a01611cc8565b92505060a0870135611e0b81611c7b565b809150509295509295509295565b60005b83811015611e34578181015183820152602001611e1c565b50506000910152565b60008151808452611e55816020860160208601611e19565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006119136020830184611e3d565b60008060008060008060008060008060006101208c8e031215611ebc57600080fd5b8b359a50611ecd60208d0135611b7e565b60208c0135995060408c0135985060608c01359750611eef60808d0135611b7e565b60808c0135965060a08c01359550611f0960c08d01611c89565b945067ffffffffffffffff8060e08e01351115611f2557600080fd5b611f358e60e08f01358f01611b93565b90955093506101008d0135811015611f4c57600080fd5b50611f5e8d6101008e01358e01611b93565b81935080925050509295989b509295989b9093969950565b600080600080600080600060e0888a031215611f9157600080fd5b873596506020880135611fa381611b7e565b95506040880135611fb381611c7b565b9450606088013567ffffffffffffffff80821115611fd057600080fd5b611fdc8b838c01611cc8565b955060808a0135915080821115611ff257600080fd5b50611fff8a828b01611cc8565b93505060a088013561201081611c7b565b915060c088013561202081611b7e565b8091505092959891949750929550565b60006020828403121561204257600080fd5b813561191381611b7e565b60006020828403121561205f57600080fd5b815161191381611b7e565b60006020828403121561207c57600080fd5b5051919050565b8581528460208201526001600160a01b038416604082015260a0606082015260006120b160a0830185611e3d565b82810360808401526120c38185611e3d565b98975050505050505050565b60006101008a83528960208401526001600160a01b03808a16604085015280891660608501525086608084015285151560a08401528060c084015261211681840186611e3d565b905082810360e084015261212a8185611e3d565b9b9a5050505050505050505050565b81810381811115610b84577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000815461218081611ae9565b6001828116801561219857600181146121cb576121fa565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00841687528215158302870194506121fa565b8560005260208060002060005b858110156121f15781548a8201529084019082016121d8565b50505082870194505b5050505092915050565b60006119138284612173565b60008251612222818460208701611e19565b9190910192915050565b601f82111561173e57600081815260208120601f850160051c810160208610156122535750805b601f850160051c820191505b818110156122725782815560010161225f565b505050505050565b815167ffffffffffffffff81111561229457612294611c99565b6122a8816122a28454611ae9565b8461222c565b602080601f8311600181146122fb57600084156122c55750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555612272565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561234857888601518255948401946001909101908401612329565b508582101561238457878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b851515815260a0602082015260006123af60a0830187611e3d565b82810360408401526123c18187611e3d565b941515606084015250506001600160a01b03919091166080909101529392505050565b6000602082840312156123f657600080fd5b815161191381611c7b56fea2646970667358221220d8fef8595bb92757a75cfecd11a51f739d7c43b0f78c357375608404c1047b7064736f6c63430008100033", "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c80635be94a6f14610030575b600080fd5b61004361003e3660046103a8565b61006c565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b60006100977f00000000000000000000000000000000000000000000000000000000000000006101b3565b6040517fc0048ca500000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff82169063c0048ca5906100f8908b908b908b908b908b908b908b906004016104c2565b600060405180830381600087803b15801561011257600080fd5b505af1158015610126573d6000803e3d6000fd5b505050508073ffffffffffffffffffffffffffffffffffffffff167f727d4d4c40bee220af4fdbae0c157cb7a5e5f2ce9c3e9676e8f615cd88bc85df8989898989897f00000000000000000000000000000000000000000000000000000000000000008a336040516101a09998979695949392919061052f565b60405180910390a2979650505050505050565b60006040517f3d602d80600a3d3981f3363d3d373d3d3d363d7300000000000000000000000081528260601b60148201527f5af43d82803e903d91602b57fd5bf3000000000000000000000000000000000060288201526037816000f091505073ffffffffffffffffffffffffffffffffffffffff8116610294576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f455243313136373a20637265617465206661696c656400000000000000000000604482015260640160405180910390fd5b919050565b73ffffffffffffffffffffffffffffffffffffffff811681146102bb57600080fd5b50565b8035801515811461029457600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261030e57600080fd5b813567ffffffffffffffff80821115610329576103296102ce565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561036f5761036f6102ce565b8160405283815286602085880101111561038857600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600080600080600060e0888a0312156103c357600080fd5b8735965060208801356103d581610299565b95506103e3604089016102be565b9450606088013567ffffffffffffffff8082111561040057600080fd5b61040c8b838c016102fd565b955060808a013591508082111561042257600080fd5b5061042f8a828b016102fd565b93505061043e60a089016102be565b915060c088013561044e81610299565b8091505092959891949750929550565b6000815180845260005b8181101561048457602081850181015186830182015201610468565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b878152600073ffffffffffffffffffffffffffffffffffffffff8089166020840152871515604084015260e0606084015261050060e084018861045e565b8381036080850152610512818861045e565b95151560a0850152509290921660c0909101525095945050505050565b60006101208b835273ffffffffffffffffffffffffffffffffffffffff808c1660208501528a1515604085015281606085015261056e8285018b61045e565b91508382036080850152610582828a61045e565b97151560a085015295861660c0840152505091831660e0830152909116610100909101529594505050505056fea2646970667358221220d9813aa7b2c826ebec43fdd21bc1f31e50caf91e73764e970cf07c573a4ea35f64736f6c63430008100033", "devdoc": { - "details": "Adheres to - IJBETHERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.", + "details": "Adheres to - IJBGasTokenERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.", "kind": "dev", "methods": { "constructor": { diff --git a/deployments/goerli/JBETHERC20SplitsPayerDeployer.json b/deployments/goerli/JBETHERC20SplitsPayerDeployer.json index 2f42a5f4d..f7e2ef3fd 100644 --- a/deployments/goerli/JBETHERC20SplitsPayerDeployer.json +++ b/deployments/goerli/JBETHERC20SplitsPayerDeployer.json @@ -299,11 +299,11 @@ ], "numDeployments": 1, "solcInputHash": "e87fd161fb98793b8dd4dcaee81afb88", - "metadata": "{\"compiler\":{\"version\":\"0.8.16+commit.07a7930e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IJBSplitsStore\",\"name\":\"_splitsStore\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IJBSplitsPayer\",\"name\":\"splitsPayer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"defaultSplitsProjectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"defaultSplitsDomain\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"defaultSplitsGroup\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"contract IJBSplitsStore\",\"name\":\"splitsStore\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"defaultProjectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"defaultBeneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"defaultPreferClaimedTokens\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"defaultMemo\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"defaultMetadata\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"preferAddToBalance\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"DeploySplitsPayer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_defaultSplitsProjectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_defaultSplitsDomain\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_defaultSplitsGroup\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_defaultProjectId\",\"type\":\"uint256\"},{\"internalType\":\"address payable\",\"name\":\"_defaultBeneficiary\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_defaultPreferClaimedTokens\",\"type\":\"bool\"},{\"internalType\":\"string\",\"name\":\"_defaultMemo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_defaultMetadata\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"_defaultPreferAddToBalance\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"deploySplitsPayer\",\"outputs\":[{\"internalType\":\"contract IJBSplitsPayer\",\"name\":\"splitsPayer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_defaultSplitsProjectId\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"preferClaimed\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"preferAddToBalance\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"percent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"lockedUntil\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBSplitAllocator\",\"name\":\"allocator\",\"type\":\"address\"}],\"internalType\":\"struct JBSplit[]\",\"name\":\"_defaultSplits\",\"type\":\"tuple[]\"},{\"internalType\":\"contract IJBSplitsStore\",\"name\":\"_splitsStore\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_defaultProjectId\",\"type\":\"uint256\"},{\"internalType\":\"address payable\",\"name\":\"_defaultBeneficiary\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_defaultPreferClaimedTokens\",\"type\":\"bool\"},{\"internalType\":\"string\",\"name\":\"_defaultMemo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_defaultMetadata\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"_defaultPreferAddToBalance\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"deploySplitsPayerWithSplits\",\"outputs\":[{\"internalType\":\"contract IJBSplitsPayer\",\"name\":\"splitsPayer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Adheres to - IJBETHERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\",\"kind\":\"dev\",\"methods\":{\"deploySplitsPayer(uint256,uint256,uint256,uint256,address,bool,string,bytes,bool,address)\":{\"params\":{\"_defaultBeneficiary\":\"The address that'll receive the project's tokens when the splits payer receives payments. \",\"_defaultMemo\":\"The memo that'll be forwarded with the splits payer's received payments. \",\"_defaultMetadata\":\"The metadata that'll be forwarded with the splits payer's received payments. \",\"_defaultPreferAddToBalance\":\"A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\",\"_defaultPreferClaimedTokens\":\"A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \",\"_defaultProjectId\":\"The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\",\"_defaultSplitsDomain\":\"The splits domain to payout when this contract receives direct payments.\",\"_defaultSplitsGroup\":\"The splits group to payout when this contract receives direct payments.\",\"_defaultSplitsProjectId\":\"The ID of project for which the default splits are stored.\",\"_owner\":\"The address that will own the splits payer.\"},\"returns\":{\"splitsPayer\":\"The splits payer contract.\"}},\"deploySplitsPayerWithSplits(uint256,(bool,bool,uint256,uint256,address,uint256,address)[],address,uint256,address,bool,string,bytes,bool,address)\":{\"details\":\"This contract must have Operator permissions over the SET_SPLITS permission of the specified `_defaultSplitsProjectId`.\",\"params\":{\"_defaultBeneficiary\":\"The address that'll receive the project's tokens when the splits payer receives payments. \",\"_defaultMemo\":\"The memo that'll be forwarded with the splits payer's received payments. \",\"_defaultMetadata\":\"The metadata that'll be forwarded with the splits payer's received payments. \",\"_defaultPreferAddToBalance\":\"A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\",\"_defaultPreferClaimedTokens\":\"A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \",\"_defaultProjectId\":\"The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\",\"_defaultSplits\":\"The splits to payout when this contract receives direct payments.\",\"_defaultSplitsProjectId\":\"The ID of project for which the default splits are stored.\",\"_owner\":\"The address that will own the splits payer.\",\"_splitsStore\":\"A contract that stores splits for each project.\"},\"returns\":{\"splitsPayer\":\"The splits payer contract.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"deploySplitsPayer(uint256,uint256,uint256,uint256,address,bool,string,bytes,bool,address)\":{\"notice\":\" Allows anyone to deploy a new splits payer contract.\"},\"deploySplitsPayerWithSplits(uint256,(bool,bool,uint256,uint256,address,uint256,address)[],address,uint256,address,bool,string,bytes,bool,address)\":{\"notice\":\" Allows anyone to deploy a new splits payer contract.\"}},\"notice\":\" Deploys splits payer contracts.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/JBETHERC20SplitsPayerDeployer.sol\":\"JBETHERC20SplitsPayerDeployer\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0x24e0364e503a9bbde94c715d26573a76f14cd2a202d45f96f52134ab806b67b9\",\"license\":\"MIT\"},\"@openzeppelin/contracts/proxy/Clones.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/Clones.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for\\n * deploying minimal proxy contracts, also known as \\\"clones\\\".\\n *\\n * > To simply and cheaply clone contract functionality in an immutable way, this standard specifies\\n * > a minimal bytecode implementation that delegates all calls to a known, fixed address.\\n *\\n * The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2`\\n * (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the\\n * deterministic method.\\n *\\n * _Available since v3.4._\\n */\\nlibrary Clones {\\n /**\\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.\\n *\\n * This function uses the create opcode, which should never revert.\\n */\\n function clone(address implementation) internal returns (address instance) {\\n assembly {\\n let ptr := mload(0x40)\\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\\n mstore(add(ptr, 0x14), shl(0x60, implementation))\\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\\n instance := create(0, ptr, 0x37)\\n }\\n require(instance != address(0), \\\"ERC1167: create failed\\\");\\n }\\n\\n /**\\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.\\n *\\n * This function uses the create2 opcode and a `salt` to deterministically deploy\\n * the clone. Using the same `implementation` and `salt` multiple time will revert, since\\n * the clones cannot be deployed twice at the same address.\\n */\\n function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) {\\n assembly {\\n let ptr := mload(0x40)\\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\\n mstore(add(ptr, 0x14), shl(0x60, implementation))\\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\\n instance := create2(0, ptr, 0x37, salt)\\n }\\n require(instance != address(0), \\\"ERC1167: create2 failed\\\");\\n }\\n\\n /**\\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\\n */\\n function predictDeterministicAddress(\\n address implementation,\\n bytes32 salt,\\n address deployer\\n ) internal pure returns (address predicted) {\\n assembly {\\n let ptr := mload(0x40)\\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\\n mstore(add(ptr, 0x14), shl(0x60, implementation))\\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf3ff00000000000000000000000000000000)\\n mstore(add(ptr, 0x38), shl(0x60, deployer))\\n mstore(add(ptr, 0x4c), salt)\\n mstore(add(ptr, 0x6c), keccak256(ptr, 0x37))\\n predicted := keccak256(add(ptr, 0x37), 0x55)\\n }\\n }\\n\\n /**\\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\\n */\\n function predictDeterministicAddress(address implementation, bytes32 salt)\\n internal\\n view\\n returns (address predicted)\\n {\\n return predictDeterministicAddress(implementation, salt, address(this));\\n }\\n}\\n\",\"keccak256\":\"0x1cc0efb01cbf008b768fd7b334786a6e358809198bb7e67f1c530af4957c6a21\",\"license\":\"MIT\"},\"@openzeppelin/contracts/security/ReentrancyGuard.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuard {\\n // Booleans are more expensive than uint256 or any type that takes up a full\\n // word because each write operation emits an extra SLOAD to first read the\\n // slot's contents, replace the bits taken up by the boolean, and then write\\n // back. This is the compiler's defense against contract upgrades and\\n // pointer aliasing, and it cannot be disabled.\\n\\n // The values being non-zero value makes deployment a bit more expensive,\\n // but in exchange the refund on every call to nonReentrant will be lower in\\n // amount. Since refunds are capped to a percentage of the total\\n // transaction's gas, it is best to keep them low in cases like this one, to\\n // increase the likelihood of the full refund coming into effect.\\n uint256 private constant _NOT_ENTERED = 1;\\n uint256 private constant _ENTERED = 2;\\n\\n uint256 private _status;\\n\\n constructor() {\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and making it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n // On the first call to nonReentrant, _notEntered will be true\\n require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n _status = _ENTERED;\\n\\n _;\\n\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n _status = _NOT_ENTERED;\\n }\\n}\\n\",\"keccak256\":\"0x0e9621f60b2faabe65549f7ed0f24e8853a45c1b7990d47e8160e523683f3935\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address sender,\\n address recipient,\\n uint256 amount\\n ) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0x61437cb513a887a1bbad006e7b1c8b414478427d33de47c5600af3c748f108da\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(\\n IERC20 token,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(\\n IERC20 token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) {\\n // Return data is optional\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xc3d946432c0ddbb1f846a0d3985be71299df331b91d06732152117f62f0be2b5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool _approved) external;\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x516a22876c1fab47f49b1bc22b4614491cd05338af8bd2e7b382da090a079990\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3777e696b62134e6177440dbe6e6601c0c156a443f57167194b67e75527439de\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"@paulrberg/contracts/math/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\nimport \\\"prb-math/contracts/PRBMath.sol\\\";\\n\",\"keccak256\":\"0x42821345981bc0434a90ba2268a2f5278dfe9e38166981d72fc7f3b776a29495\",\"license\":\"Unlicense\"},\"contracts/JBETHERC20ProjectPayer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport '@openzeppelin/contracts/access/Ownable.sol';\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\\nimport './interfaces/IJBProjectPayer.sol';\\nimport './libraries/JBTokens.sol';\\n\\n/** \\n @notice \\n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\\n\\n @dev\\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\\n\\n @dev\\n Adheres to -\\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n\\n @dev\\n Inherits from -\\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\\n ERC165: Introspection on interface adherance. \\n*/\\ncontract JBETHERC20ProjectPayer is Ownable, ERC165, IJBProjectPayer {\\n using SafeERC20 for IERC20;\\n\\n //*********************************************************************//\\n // -------------------------- custom errors -------------------------- //\\n //*********************************************************************//\\n error INCORRECT_DECIMAL_AMOUNT();\\n error ALREADY_INITIALIZED();\\n error NO_MSG_VALUE_ALLOWED();\\n error TERMINAL_NOT_FOUND();\\n\\n //*********************************************************************//\\n // ------------------- public immutable properties ------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice \\n A contract storing directories of terminals and controllers for each project.\\n */\\n IJBDirectory public immutable override directory;\\n\\n /**\\n @notice \\n The deployer associated with this implementation. Used to rule out double initialization.\\n */\\n address public immutable override projectPayerDeployer;\\n\\n //*********************************************************************//\\n // --------------------- public stored properties -------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n The ID of the project that should be used to forward this contract's received payments.\\n */\\n uint256 public override defaultProjectId;\\n\\n /** \\n @notice \\n The beneficiary that should be used in the payment made when this contract receives payments.\\n */\\n address payable public override defaultBeneficiary;\\n\\n /** \\n @notice \\n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\\n */\\n bool public override defaultPreferClaimedTokens;\\n\\n /** \\n @notice \\n The memo that should be used in the payment made when this contract receives payments.\\n */\\n string public override defaultMemo;\\n\\n /** \\n @notice \\n The metadata that should be used in the payment made when this contract receives payments.\\n */\\n bytes public override defaultMetadata;\\n\\n /**\\n @notice \\n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\\n */\\n bool public override defaultPreferAddToBalance;\\n\\n //*********************************************************************//\\n // ------------------------- public views ---------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Indicates if this contract adheres to the specified interface.\\n\\n @dev \\n See {IERC165-supportsInterface}.\\n\\n @param _interfaceId The ID of the interface to check for adherance to.\\n */\\n function supportsInterface(bytes4 _interfaceId)\\n public\\n view\\n virtual\\n override(ERC165, IERC165)\\n returns (bool)\\n {\\n return\\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\\n }\\n\\n //*********************************************************************//\\n // -------------------------- constructors --------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @dev This is the constructor of the implementation. The directory is shared between project payers and is\\n immutable. If a new JBDirectory is needed, a new JBProjectPayerDeployer should be deployed.\\n @param _directory A contract storing directories of terminals and controllers for each project.\\n */\\n constructor(IJBDirectory _directory) {\\n directory = _directory;\\n projectPayerDeployer = msg.sender;\\n }\\n\\n /** \\n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\\n @param _defaultBeneficiary The address that'll receive the project's tokens. \\n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \\n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\\n @param _owner The address that will own the contract.\\n */\\n function initialize(\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string memory _defaultMemo,\\n bytes memory _defaultMetadata,\\n bool _defaultPreferAddToBalance,\\n address _owner\\n ) public {\\n if(msg.sender != projectPayerDeployer) revert ALREADY_INITIALIZED();\\n\\n defaultProjectId = _defaultProjectId;\\n defaultBeneficiary = _defaultBeneficiary;\\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\\n defaultMemo = _defaultMemo;\\n defaultMetadata = _defaultMetadata;\\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\\n _transferOwnership(_owner);\\n }\\n\\n //*********************************************************************//\\n // ------------------------- default receive ------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Received funds are paid to the default project ID using the stored default properties.\\n\\n @dev\\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\\n\\n @dev\\n This function is called automatically when the contract receives an ETH payment.\\n */\\n receive() external payable virtual override {\\n if (defaultPreferAddToBalance)\\n _addToBalanceOf(\\n defaultProjectId,\\n JBTokens.ETH,\\n address(this).balance,\\n 18, // balance is a fixed point number with 18 decimals.\\n defaultMemo,\\n defaultMetadata\\n );\\n else\\n _pay(\\n defaultProjectId,\\n JBTokens.ETH,\\n address(this).balance,\\n 18, // balance is a fixed point number with 18 decimals.\\n defaultBeneficiary == address(0) ? tx.origin : defaultBeneficiary,\\n 0, // Can't determine expectation of returned tokens ahead of time.\\n defaultPreferClaimedTokens,\\n defaultMemo,\\n defaultMetadata\\n );\\n }\\n\\n //*********************************************************************//\\n // ---------------------- external transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\\n\\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\\n @param _beneficiary The address that'll receive the project's tokens. \\n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \\n @param _memo The memo that'll be used. \\n @param _metadata The metadata that'll be sent. \\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\\n */\\n function setDefaultValues(\\n uint256 _projectId,\\n address payable _beneficiary,\\n bool _preferClaimedTokens,\\n string memory _memo,\\n bytes memory _metadata,\\n bool _defaultPreferAddToBalance\\n ) external virtual override onlyOwner {\\n // Set the default project ID if it has changed.\\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\\n\\n // Set the default beneficiary if it has changed.\\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\\n\\n // Set the default claimed token preference if it has changed.\\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\\n defaultPreferClaimedTokens = _preferClaimedTokens;\\n\\n // Set the default memo if it has changed.\\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\\n defaultMemo = _memo;\\n\\n // Set the default metadata if it has changed.\\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\\n defaultMetadata = _metadata;\\n\\n // Set the add to balance preference if it has changed.\\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\\n\\n emit SetDefaultValues(\\n _projectId,\\n _beneficiary,\\n _preferClaimedTokens,\\n _memo,\\n _metadata,\\n _defaultPreferAddToBalance,\\n msg.sender\\n );\\n }\\n\\n //*********************************************************************//\\n // ----------------------- public transactions ----------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n Make a payment to the specified project.\\n\\n @param _projectId The ID of the project that is being paid.\\n @param _token The token being paid in.\\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\\n @param _beneficiary The address who will receive tokens from the payment.\\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\\n */\\n function pay(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) public payable virtual override {\\n // ETH shouldn't be sent if the token isn't ETH.\\n if (address(_token) != JBTokens.ETH) {\\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\\n\\n // Get a reference to the balance before receiving tokens.\\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\\n\\n // Transfer tokens to this contract from the msg sender.\\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\\n\\n // The amount should reflect the change in balance.\\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\\n } else {\\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\\n _amount = msg.value;\\n _decimals = 18;\\n }\\n\\n _pay(\\n _projectId,\\n _token,\\n _amount,\\n _decimals,\\n _beneficiary,\\n _minReturnedTokens,\\n _preferClaimedTokens,\\n _memo,\\n _metadata\\n );\\n }\\n\\n /** \\n @notice \\n Add to the balance of the specified project.\\n\\n @param _projectId The ID of the project that is being paid.\\n @param _token The token being paid in.\\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Extra data to pass along to the terminal.\\n */\\n function addToBalanceOf(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) public payable virtual override {\\n // ETH shouldn't be sent if the token isn't ETH.\\n if (address(_token) != JBTokens.ETH) {\\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\\n\\n // Get a reference to the balance before receiving tokens.\\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\\n\\n // Transfer tokens to this contract from the msg sender.\\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\\n\\n // The amount should reflect the change in balance.\\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\\n } else {\\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\\n _amount = msg.value;\\n _decimals = 18;\\n }\\n\\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\\n }\\n\\n //*********************************************************************//\\n // ---------------------- internal transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n Make a payment to the specified project.\\n\\n @param _projectId The ID of the project that is being paid.\\n @param _token The token being paid in.\\n @param _amount The amount of tokens being paid, as a fixed point number. \\n @param _decimals The number of decimals in the `_amount` fixed point number. \\n @param _beneficiary The address who will receive tokens from the payment.\\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _metadata Bytes to send along to the data source and delegate, if provided.\\n */\\n function _pay(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string memory _memo,\\n bytes memory _metadata\\n ) internal virtual {\\n // Find the terminal for the specified project.\\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\\n\\n // There must be a terminal.\\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\\n\\n // The amount's decimals must match the terminal's expected decimals.\\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\\n\\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\\n if (_token != JBTokens.ETH) IERC20(_token).safeApprove(address(_terminal), _amount);\\n\\n // If the token is ETH, send it in msg.value.\\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\\n\\n // Send funds to the terminal.\\n // If the token is ETH, send it in msg.value.\\n _terminal.pay{value: _payableValue}(\\n _projectId,\\n _amount, // ignored if the token is JBTokens.ETH.\\n _token,\\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\\n ? defaultBeneficiary\\n : tx.origin,\\n _minReturnedTokens,\\n _preferClaimedTokens,\\n _memo,\\n _metadata\\n );\\n }\\n\\n /** \\n @notice \\n Add to the balance of the specified project.\\n\\n @param _projectId The ID of the project that is being paid.\\n @param _token The token being paid in.\\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Extra data to pass along to the terminal.\\n */\\n function _addToBalanceOf(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n string memory _memo,\\n bytes memory _metadata\\n ) internal virtual {\\n // Find the terminal for the specified project.\\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\\n\\n // There must be a terminal.\\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\\n\\n // The amount's decimals must match the terminal's expected decimals.\\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\\n\\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\\n if (_token != JBTokens.ETH) IERC20(_token).safeApprove(address(_terminal), _amount);\\n\\n // If the token is ETH, send it in msg.value.\\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\\n\\n // Add to balance so tokens don't get issued.\\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\\n }\\n}\\n\",\"keccak256\":\"0xcbadf8e217bb9c43d18161ce576235277834988ea7cb51d58b5a794914e9156c\",\"license\":\"MIT\"},\"contracts/JBETHERC20SplitsPayer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport '@openzeppelin/contracts/utils/Address.sol';\\nimport '@paulrberg/contracts/math/PRBMath.sol';\\nimport './interfaces/IJBSplitsPayer.sol';\\nimport './interfaces/IJBSplitsStore.sol';\\nimport './libraries/JBConstants.sol';\\nimport './JBETHERC20ProjectPayer.sol';\\n\\n/** \\n @notice \\n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\\n\\n @dev\\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\\n\\n @dev\\n Adheres to -\\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n\\n @dev\\n Inherits from -\\n JBETHERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\\n*/\\ncontract JBETHERC20SplitsPayer is JBETHERC20ProjectPayer, ReentrancyGuard, IJBSplitsPayer {\\n using SafeERC20 for IERC20;\\n\\n //*********************************************************************//\\n // ---------------- public immutable stored properties --------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The contract that stores splits for each project.\\n */\\n IJBSplitsStore public immutable override splitsStore;\\n\\n //*********************************************************************//\\n // --------------------- public stored properties -------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The ID of project for which the default splits are stored. \\n */\\n uint256 public override defaultSplitsProjectId;\\n\\n /**\\n @notice\\n The domain within which the default splits are stored. \\n */\\n uint256 public override defaultSplitsDomain;\\n\\n /**\\n @notice\\n The group within which the default splits are stored. \\n */\\n uint256 public override defaultSplitsGroup;\\n\\n //*********************************************************************//\\n // -------------------------- public views --------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Indicates if this contract adheres to the specified interface.\\n\\n @dev \\n See {IERC165-supportsInterface}.\\n\\n @param _interfaceId The ID of the interface to check for adherance to.\\n\\n @return A flag indicating if this contract adheres to the specified interface.\\n */\\n function supportsInterface(bytes4 _interfaceId)\\n public\\n view\\n virtual\\n override(JBETHERC20ProjectPayer, IERC165)\\n returns (bool)\\n {\\n return\\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\\n }\\n\\n //*********************************************************************//\\n // -------------------------- constructor ---------------------------- //\\n //*********************************************************************//\\n/**\\n @param _splitsStore A contract that stores splits for each project.\\n*/\\n constructor(\\n IJBSplitsStore _splitsStore\\n )\\n JBETHERC20ProjectPayer(\\n _splitsStore.directory()\\n )\\n {\\n splitsStore = _splitsStore;\\n }\\n /**\\n @dev The re-initialize check is done in the inherited paroject payer\\n \\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\\n @param _defaultBeneficiary The address that'll receive the project's tokens. \\n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \\n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\\n @param _owner The address that will own the contract.\\n */\\n function initialize(\\n uint256 _defaultSplitsProjectId,\\n uint256 _defaultSplitsDomain,\\n uint256 _defaultSplitsGroup,\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string memory _defaultMemo,\\n bytes memory _defaultMetadata,\\n bool _preferAddToBalance,\\n address _owner\\n ) external override {\\n\\n super.initialize(\\n _defaultProjectId,\\n _defaultBeneficiary,\\n _defaultPreferClaimedTokens,\\n _defaultMemo,\\n _defaultMetadata,\\n _preferAddToBalance,\\n _owner\\n );\\n\\n defaultSplitsProjectId = _defaultSplitsProjectId;\\n defaultSplitsDomain = _defaultSplitsDomain;\\n defaultSplitsGroup = _defaultSplitsGroup;\\n }\\n\\n\\n\\n //*********************************************************************//\\n // ------------------------- default receive ------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Received funds are paid to the default split group using the stored default properties.\\n\\n @dev\\n This function is called automatically when the contract receives an ETH payment.\\n */\\n receive() external payable virtual override nonReentrant {\\n // Pay the splits and get a reference to the amount leftover.\\n uint256 _leftoverAmount = _payToSplits(\\n defaultSplitsProjectId,\\n defaultSplitsDomain,\\n defaultSplitsGroup,\\n JBTokens.ETH,\\n address(this).balance,\\n 18, // decimals.\\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\\n );\\n\\n // If there is no leftover amount, nothing left to pay.\\n if (_leftoverAmount == 0) return;\\n\\n // If there's a default project ID, try to pay it.\\n if (defaultProjectId != 0)\\n if (defaultPreferAddToBalance)\\n // Pay the project by adding to its balance if prefered.\\n _addToBalanceOf(\\n defaultProjectId,\\n JBTokens.ETH,\\n _leftoverAmount,\\n 18, // decimals.\\n defaultMemo,\\n defaultMetadata\\n );\\n // Otherwise, issue a payment to the project.\\n else\\n _pay(\\n defaultProjectId,\\n JBTokens.ETH,\\n _leftoverAmount,\\n 18, // decimals.\\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\\n 0, // min returned tokens.\\n defaultPreferClaimedTokens,\\n defaultMemo,\\n defaultMetadata\\n );\\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\\n else\\n Address.sendValue(\\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(tx.origin),\\n _leftoverAmount\\n );\\n }\\n\\n //*********************************************************************//\\n // ---------------------- external transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Sets the splits in the splits store that payments this contract receives will be split between.\\n\\n @param _projectId The ID of project for which the default splits are stored. \\n @param _domain The domain within which the default splits are stored. \\n @param _group The group within which the default splits are stored. \\n @param _groupedSplits The split groups to set.\\n */\\n function setDefaultSplits(\\n uint256 _projectId,\\n uint256 _domain,\\n uint256 _group,\\n JBGroupedSplits[] memory _groupedSplits\\n ) external virtual override onlyOwner {\\n // Set the splits in the store.\\n splitsStore.set(_projectId, _domain, _groupedSplits);\\n\\n // Set the splits reference.\\n setDefaultSplitsReference(_projectId, _domain, _group);\\n }\\n\\n //*********************************************************************//\\n // ----------------------- public transactions ----------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Sets the location of the splits that payments this contract receives will be split between.\\n\\n @param _projectId The ID of project for which the default splits are stored. \\n @param _domain The domain within which the default splits are stored. \\n @param _group The group within which the default splits are stored. \\n */\\n function setDefaultSplitsReference(\\n uint256 _projectId,\\n uint256 _domain,\\n uint256 _group\\n ) public virtual override onlyOwner {\\n // Set the default splits project ID if it's changing.\\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\\n\\n // Set the default splits domain if it's changing.\\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\\n\\n // Set the default splits group if it's changing.\\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\\n\\n emit SetDefaultSplitsReference(_projectId, _domain, _group, msg.sender);\\n }\\n\\n /** \\n @notice \\n Make a payment to the specified project after first splitting the amount among the stored default splits.\\n\\n @param _projectId The ID of the project that is being paid after.\\n @param _token The token being paid in.\\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\\n */\\n function pay(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) public payable virtual override nonReentrant {\\n // ETH shouldn't be sent if the token isn't ETH.\\n if (address(_token) != JBTokens.ETH) {\\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\\n\\n // Get a reference to the balance before receiving tokens.\\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\\n\\n // Transfer tokens to this contract from the msg sender.\\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\\n\\n // The amount should reflect the change in balance.\\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\\n } else {\\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\\n _amount = msg.value;\\n _decimals = 18;\\n }\\n\\n // Pay the splits and get a reference to the amount leftover.\\n uint256 _leftoverAmount = _payToSplits(\\n defaultSplitsProjectId,\\n defaultSplitsDomain,\\n defaultSplitsGroup,\\n _token,\\n _amount,\\n _decimals,\\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\\n );\\n\\n // Pay any leftover amount.\\n if (_leftoverAmount > 0) {\\n // If there's a default project ID, try to pay it.\\n if (_projectId != 0) {\\n _pay(\\n _projectId,\\n _token,\\n _leftoverAmount,\\n _decimals,\\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\\n ? defaultBeneficiary\\n : tx.origin,\\n _minReturnedTokens,\\n _preferClaimedTokens,\\n _memo,\\n _metadata\\n );\\n }\\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\\n else {\\n // Transfer the ETH.\\n if (_token == JBTokens.ETH)\\n Address.sendValue(\\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\\n _beneficiary != address(0) ? payable(_beneficiary) : defaultBeneficiary != address(0)\\n ? defaultBeneficiary\\n : payable(tx.origin),\\n _leftoverAmount\\n );\\n // Or, transfer the ERC20.\\n else\\n IERC20(_token).safeTransfer(\\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\\n ? defaultBeneficiary\\n : tx.origin,\\n _leftoverAmount\\n );\\n }\\n }\\n\\n emit Pay(\\n _projectId,\\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\\n ? defaultBeneficiary\\n : tx.origin,\\n _token,\\n _amount,\\n _decimals,\\n _leftoverAmount,\\n _minReturnedTokens,\\n _preferClaimedTokens,\\n _memo,\\n _metadata,\\n msg.sender\\n );\\n }\\n\\n /** \\n @notice \\n Add to the balance of the specified project after first splitting the amount among the stored default splits.\\n\\n @param _projectId The ID of the project that is being paid after.\\n @param _token The token being paid in.\\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\\n @param _memo A memo to pass along to the emitted event. \\n @param _metadata Extra data to pass along to the terminal.\\n */\\n function addToBalanceOf(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) public payable virtual override nonReentrant {\\n // ETH shouldn't be sent if this terminal's token isn't ETH.\\n if (address(_token) != JBTokens.ETH) {\\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\\n\\n // Get a reference to the balance before receiving tokens.\\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\\n\\n // Transfer tokens to this contract from the msg sender.\\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\\n\\n // The amount should reflect the change in balance.\\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\\n } else {\\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\\n _amount = msg.value;\\n _decimals = 18;\\n }\\n\\n // Pay the splits and get a reference to the amount leftover.\\n uint256 _leftoverAmount = _payToSplits(\\n defaultSplitsProjectId,\\n defaultSplitsDomain,\\n defaultSplitsGroup,\\n _token,\\n _amount,\\n _decimals,\\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\\n );\\n\\n // Distribute any leftover amount.\\n if (_leftoverAmount > 0) {\\n // If there's a default project ID, try to add to its balance.\\n if (_projectId != 0)\\n // Add to the project's balance.\\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\\n\\n // Otherwise, send a payment to the beneficiary.\\n else {\\n // Transfer the ETH.\\n if (_token == JBTokens.ETH)\\n Address.sendValue(\\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(tx.origin),\\n _leftoverAmount\\n );\\n // Or, transfer the ERC20.\\n else\\n IERC20(_token).safeTransfer(\\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\\n _leftoverAmount\\n );\\n }\\n }\\n\\n emit AddToBalance(\\n _projectId,\\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\\n _token,\\n _amount,\\n _decimals,\\n _leftoverAmount,\\n _memo,\\n _metadata,\\n msg.sender\\n );\\n }\\n\\n //*********************************************************************//\\n // ---------------------- internal transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n Split an amount between all splits.\\n\\n @param _splitsProjectId The ID of the project to which the splits belong.\\n @param _splitsDomain The splits domain to which the group belongs.\\n @param _splitsGroup The splits group to pay.\\n @param _token The token the amonut being split is in.\\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\\n @param _decimals The number of decimals in the `_amount` fixed point number. \\n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\\n\\n @return leftoverAmount The amount leftover after all splits were paid.\\n */\\n function _payToSplits(\\n uint256 _splitsProjectId,\\n uint256 _splitsDomain,\\n uint256 _splitsGroup,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n address _defaultBeneficiary\\n ) internal virtual returns (uint256 leftoverAmount) {\\n // Pay the splits.\\n leftoverAmount = _payTo(\\n splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup),\\n _token,\\n _amount,\\n _decimals,\\n _defaultBeneficiary\\n );\\n emit DistributeToSplitGroup(_splitsProjectId, _splitsDomain, _splitsGroup, msg.sender);\\n }\\n\\n /** \\n @notice \\n Split an amount between all splits.\\n\\n @param _splits The splits.\\n @param _token The token the amonut being split is in.\\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\\n @param _decimals The number of decimals in the `_amount` fixed point number. \\n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\\n\\n @return leftoverAmount The amount leftover after all splits were paid.\\n */\\n function _payTo(\\n JBSplit[] memory _splits,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n address _defaultBeneficiary\\n ) internal virtual returns (uint256 leftoverAmount) {\\n // Set the leftover amount to the initial balance.\\n leftoverAmount = _amount;\\n\\n // Settle between all splits.\\n for (uint256 i; i < _splits.length; ) {\\n // Get a reference to the split being iterated on.\\n JBSplit memory _split = _splits[i];\\n\\n // The amount to send towards the split.\\n uint256 _splitAmount = PRBMath.mulDiv(\\n _amount,\\n _split.percent,\\n JBConstants.SPLITS_TOTAL_PERCENT\\n );\\n\\n if (_splitAmount > 0) {\\n // Transfer tokens to the split.\\n // If there's an allocator set, transfer to its `allocate` function.\\n if (_split.allocator != IJBSplitAllocator(address(0))) {\\n // Create the data to send to the allocator.\\n JBSplitAllocationData memory _data = JBSplitAllocationData(\\n _token,\\n _splitAmount,\\n _decimals,\\n defaultProjectId,\\n 0,\\n _split\\n );\\n\\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\\n if (_token != JBTokens.ETH)\\n IERC20(_token).safeApprove(address(_split.allocator), _splitAmount);\\n\\n // If the token is ETH, send it in msg.value.\\n uint256 _payableValue = _token == JBTokens.ETH ? _splitAmount : 0;\\n\\n // Trigger the allocator's `allocate` function.\\n _split.allocator.allocate{value: _payableValue}(_data);\\n\\n // Otherwise, if a project is specified, make a payment to it.\\n } else if (_split.projectId != 0) {\\n if (_split.preferAddToBalance)\\n _addToBalanceOf(\\n _split.projectId,\\n _token,\\n _splitAmount,\\n _decimals,\\n defaultMemo,\\n defaultMetadata\\n );\\n else\\n _pay(\\n _split.projectId,\\n _token,\\n _splitAmount,\\n _decimals,\\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\\n 0,\\n _split.preferClaimed,\\n defaultMemo,\\n defaultMetadata\\n );\\n } else {\\n // Transfer the ETH.\\n if (_token == JBTokens.ETH)\\n Address.sendValue(\\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\\n _split.beneficiary != address(0) ? _split.beneficiary : payable(_defaultBeneficiary),\\n _splitAmount\\n );\\n // Or, transfer the ERC20.\\n else {\\n IERC20(_token).safeTransfer(\\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\\n _splitAmount\\n );\\n }\\n }\\n\\n // Subtract from the amount to be sent to the beneficiary.\\n leftoverAmount = leftoverAmount - _splitAmount;\\n }\\n\\n emit DistributeToSplit(_split, _splitAmount, _defaultBeneficiary, msg.sender);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x19b81077f19b544d6ad5c6b945584fd9187c774f0f85e2965475ade2da15ae42\",\"license\":\"MIT\"},\"contracts/JBETHERC20SplitsPayerDeployer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport { Clones } from '@openzeppelin/contracts/proxy/Clones.sol';\\n\\nimport './interfaces/IJBETHERC20SplitsPayerDeployer.sol';\\nimport './structs/JBSplit.sol';\\nimport './structs/JBGroupedSplits.sol';\\nimport './JBETHERC20SplitsPayer.sol';\\n\\n/** \\n @notice \\n Deploys splits payer contracts.\\n\\n @dev\\n Adheres to -\\n IJBETHERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n*/\\ncontract JBETHERC20SplitsPayerDeployer is IJBETHERC20SplitsPayerDeployer {\\n\\n address immutable implementation;\\n\\n IJBSplitsStore immutable splitsStore;\\n\\n constructor(IJBSplitsStore _splitsStore) {\\n implementation = address(new JBETHERC20SplitsPayer(_splitsStore));\\n splitsStore = _splitsStore;\\n }\\n\\n //*********************************************************************//\\n // ---------------------- external transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n Allows anyone to deploy a new splits payer contract.\\n\\n @dev\\n This contract must have Operator permissions over the SET_SPLITS permission of the specified `_defaultSplitsProjectId`.\\n\\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\\n @param _defaultSplits The splits to payout when this contract receives direct payments.\\n @param _splitsStore A contract that stores splits for each project.\\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \\n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \\n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \\n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\\n @param _owner The address that will own the splits payer.\\n\\n @return splitsPayer The splits payer contract.\\n */\\n function deploySplitsPayerWithSplits(\\n uint256 _defaultSplitsProjectId,\\n JBSplit[] memory _defaultSplits,\\n IJBSplitsStore _splitsStore,\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string memory _defaultMemo,\\n bytes memory _defaultMetadata,\\n bool _defaultPreferAddToBalance,\\n address _owner\\n ) external override returns (IJBSplitsPayer splitsPayer) {\\n // Use this contract's address as the domain.\\n uint256 _domain = uint256(uint160(address(this)));\\n\\n // Create the random hash using data unique to this instance that'll be used as the storage domain.\\n uint256 _group = uint256(keccak256(abi.encodePacked(msg.sender, block.number)));\\n\\n // Set the splits in the store.\\n JBGroupedSplits[] memory _groupedSplits;\\n _groupedSplits = new JBGroupedSplits[](1);\\n _groupedSplits[0] = JBGroupedSplits(_group, _defaultSplits);\\n _splitsStore.set(_defaultSplitsProjectId, _domain, _groupedSplits);\\n\\n return\\n deploySplitsPayer(\\n _defaultSplitsProjectId,\\n _domain,\\n _group,\\n _defaultProjectId,\\n _defaultBeneficiary,\\n _defaultPreferClaimedTokens,\\n _defaultMemo,\\n _defaultMetadata,\\n _defaultPreferAddToBalance,\\n _owner\\n );\\n }\\n\\n //*********************************************************************//\\n // ---------------------- public transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n Allows anyone to deploy a new splits payer contract.\\n\\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \\n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \\n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \\n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\\n @param _owner The address that will own the splits payer.\\n\\n @return splitsPayer The splits payer contract.\\n */\\n function deploySplitsPayer(\\n uint256 _defaultSplitsProjectId,\\n uint256 _defaultSplitsDomain,\\n uint256 _defaultSplitsGroup,\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string memory _defaultMemo,\\n bytes memory _defaultMetadata,\\n bool _defaultPreferAddToBalance,\\n address _owner\\n ) public override returns (IJBSplitsPayer splitsPayer) {\\n\\n // Deploy the splits payer.\\n splitsPayer = IJBSplitsPayer(payable(Clones.clone(implementation)));\\n\\n splitsPayer.initialize(\\n _defaultSplitsProjectId,\\n _defaultSplitsDomain,\\n _defaultSplitsGroup,\\n _defaultProjectId,\\n _defaultBeneficiary,\\n _defaultPreferClaimedTokens,\\n _defaultMemo,\\n _defaultMetadata,\\n _defaultPreferAddToBalance,\\n _owner\\n );\\n\\n emit DeploySplitsPayer(\\n splitsPayer,\\n _defaultSplitsProjectId,\\n _defaultSplitsDomain,\\n _defaultSplitsGroup,\\n splitsStore,\\n _defaultProjectId,\\n _defaultBeneficiary,\\n _defaultPreferClaimedTokens,\\n _defaultMemo,\\n _defaultMetadata,\\n _defaultPreferAddToBalance,\\n _owner,\\n msg.sender\\n );\\n }\\n}\\n\",\"keccak256\":\"0x1d772589f0079d573ea80929092e23a4b2bc9a41f0e930dc1efb10d7fc731d81\",\"license\":\"MIT\"},\"contracts/enums/JBBallotState.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nenum JBBallotState {\\n Active,\\n Approved,\\n Failed\\n}\\n\",\"keccak256\":\"0x891fcac63470398b3a11239da7feba6b07d640809fcefd2404303b823d7378f8\",\"license\":\"MIT\"},\"contracts/interfaces/IJBDirectory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBProjects.sol';\\n\\ninterface IJBDirectory {\\n event SetController(uint256 indexed projectId, address indexed controller, address caller);\\n\\n event AddTerminal(uint256 indexed projectId, IJBPaymentTerminal indexed terminal, address caller);\\n\\n event SetTerminals(uint256 indexed projectId, IJBPaymentTerminal[] terminals, address caller);\\n\\n event SetPrimaryTerminal(\\n uint256 indexed projectId,\\n address indexed token,\\n IJBPaymentTerminal indexed terminal,\\n address caller\\n );\\n\\n event SetIsAllowedToSetFirstController(address indexed addr, bool indexed flag, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function controllerOf(uint256 _projectId) external view returns (address);\\n\\n function isAllowedToSetFirstController(address _address) external view returns (bool);\\n\\n function terminalsOf(uint256 _projectId) external view returns (IJBPaymentTerminal[] memory);\\n\\n function isTerminalOf(uint256 _projectId, IJBPaymentTerminal _terminal)\\n external\\n view\\n returns (bool);\\n\\n function primaryTerminalOf(uint256 _projectId, address _token)\\n external\\n view\\n returns (IJBPaymentTerminal);\\n\\n function setControllerOf(uint256 _projectId, address _controller) external;\\n\\n function setTerminalsOf(uint256 _projectId, IJBPaymentTerminal[] calldata _terminals) external;\\n\\n function setPrimaryTerminalOf(\\n uint256 _projectId,\\n address _token,\\n IJBPaymentTerminal _terminal\\n ) external;\\n\\n function setIsAllowedToSetFirstController(address _address, bool _flag) external;\\n}\\n\",\"keccak256\":\"0x715321646db00514d1355ed43c40cd3f01e94959552fd07797b315d9c49cdb1d\",\"license\":\"MIT\"},\"contracts/interfaces/IJBETHERC20SplitsPayerDeployer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBSplitsPayer.sol';\\nimport './IJBSplitsStore.sol';\\n\\ninterface IJBETHERC20SplitsPayerDeployer {\\n event DeploySplitsPayer(\\n IJBSplitsPayer indexed splitsPayer,\\n uint256 defaultSplitsProjectId,\\n uint256 defaultSplitsDomain,\\n uint256 defaultSplitsGroup,\\n IJBSplitsStore splitsStore,\\n uint256 defaultProjectId,\\n address defaultBeneficiary,\\n bool defaultPreferClaimedTokens,\\n string defaultMemo,\\n bytes defaultMetadata,\\n bool preferAddToBalance,\\n address owner,\\n address caller\\n );\\n\\n function deploySplitsPayer(\\n uint256 _defaultSplitsProjectId,\\n uint256 _defaultSplitsDomain,\\n uint256 _defaultSplitsGroup,\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string calldata _defaultMemo,\\n bytes calldata _defaultMetadata,\\n bool _preferAddToBalance,\\n address _owner\\n ) external returns (IJBSplitsPayer splitsPayer);\\n\\n function deploySplitsPayerWithSplits(\\n uint256 _defaultSplitsProjectId,\\n JBSplit[] memory _defaultSplits,\\n IJBSplitsStore _splitsStore,\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string memory _defaultMemo,\\n bytes memory _defaultMetadata,\\n bool _defaultPreferAddToBalance,\\n address _owner\\n ) external returns (IJBSplitsPayer splitsPayer);\\n}\\n\",\"keccak256\":\"0xc476797aa84a54530cdbaff6a9e8c2fc8bf90a051dd51a17a00c51345db2798c\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleBallot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../enums/JBBallotState.sol';\\n\\ninterface IJBFundingCycleBallot is IERC165 {\\n function duration() external view returns (uint256);\\n\\n function stateOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n uint256 _start\\n ) external view returns (JBBallotState);\\n}\\n\",\"keccak256\":\"0x49553a56209237846bc400cf27f260824a6bd06fd8094a7eb5abb9de75779598\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../enums/JBBallotState.sol';\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBFundingCycleData.sol';\\n\\ninterface IJBFundingCycleStore {\\n event Configure(\\n uint256 indexed configuration,\\n uint256 indexed projectId,\\n JBFundingCycleData data,\\n uint256 metadata,\\n uint256 mustStartAtOrAfter,\\n address caller\\n );\\n\\n event Init(uint256 indexed configuration, uint256 indexed projectId, uint256 indexed basedOn);\\n\\n function latestConfigurationOf(uint256 _projectId) external view returns (uint256);\\n\\n function get(uint256 _projectId, uint256 _configuration)\\n external\\n view\\n returns (JBFundingCycle memory);\\n\\n function latestConfiguredOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBBallotState ballotState);\\n\\n function queuedOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentBallotStateOf(uint256 _projectId) external view returns (JBBallotState);\\n\\n function configureFor(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n uint256 _metadata,\\n uint256 _mustStartAtOrAfter\\n ) external returns (JBFundingCycle memory fundingCycle);\\n}\\n\",\"keccak256\":\"0xaead823851433be0c2ddc8f8086813e6cd647de3a1bc0f7570a5d6b38c378b5a\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\n\\ninterface IJBPaymentTerminal is IERC165 {\\n function acceptsToken(address _token, uint256 _projectId) external view returns (bool);\\n\\n function currencyForToken(address _token) external view returns (uint256);\\n\\n function decimalsForToken(address _token) external view returns (uint256);\\n\\n // Return value must be a fixed point number with 18 decimals.\\n function currentEthOverflowOf(uint256 _projectId) external view returns (uint256);\\n\\n function pay(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable returns (uint256 beneficiaryTokenCount);\\n\\n function addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable;\\n}\\n\",\"keccak256\":\"0xb7826f5ed609359ce322c09e83236c47ba385df1c3cad3607e56fd0a2e00eee2\",\"license\":\"MIT\"},\"contracts/interfaces/IJBProjectPayer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './IJBDirectory.sol';\\n\\ninterface IJBProjectPayer is IERC165 {\\n event SetDefaultValues(\\n uint256 indexed projectId,\\n address indexed beneficiary,\\n bool preferClaimedTokens,\\n string memo,\\n bytes metadata,\\n bool preferAddToBalance,\\n address caller\\n );\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function projectPayerDeployer() external view returns (address);\\n\\n function defaultProjectId() external view returns (uint256);\\n\\n function defaultBeneficiary() external view returns (address payable);\\n\\n function defaultPreferClaimedTokens() external view returns (bool);\\n\\n function defaultMemo() external view returns (string memory);\\n\\n function defaultMetadata() external view returns (bytes memory);\\n\\n function defaultPreferAddToBalance() external view returns (bool);\\n\\n function initialize(\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string memory _defaultMemo,\\n bytes memory _defaultMetadata,\\n bool _defaultPreferAddToBalance,\\n address _owner\\n ) external;\\n\\n function setDefaultValues(\\n uint256 _projectId,\\n address payable _beneficiary,\\n bool _preferClaimedTokens,\\n string memory _memo,\\n bytes memory _metadata,\\n bool _defaultPreferAddToBalance\\n ) external;\\n\\n function pay(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string memory _memo,\\n bytes memory _metadata\\n ) external payable;\\n\\n function addToBalanceOf(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n string memory _memo,\\n bytes memory _metadata\\n ) external payable;\\n\\n receive() external payable;\\n}\\n\",\"keccak256\":\"0x85f4cbd5482e26618994f742c149a5bd3cb3dc39dbeba85b21c36b3215007df6\",\"license\":\"MIT\"},\"contracts/interfaces/IJBProjects.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBTokenUriResolver.sol';\\n\\ninterface IJBProjects is IERC721 {\\n event Create(\\n uint256 indexed projectId,\\n address indexed owner,\\n JBProjectMetadata metadata,\\n address caller\\n );\\n\\n event SetMetadata(uint256 indexed projectId, JBProjectMetadata metadata, address caller);\\n\\n event SetTokenUriResolver(IJBTokenUriResolver indexed resolver, address caller);\\n\\n function count() external view returns (uint256);\\n\\n function metadataContentOf(uint256 _projectId, uint256 _domain)\\n external\\n view\\n returns (string memory);\\n\\n function tokenUriResolver() external view returns (IJBTokenUriResolver);\\n\\n function createFor(address _owner, JBProjectMetadata calldata _metadata)\\n external\\n returns (uint256 projectId);\\n\\n function setMetadataOf(uint256 _projectId, JBProjectMetadata calldata _metadata) external;\\n\\n function setTokenUriResolver(IJBTokenUriResolver _newResolver) external;\\n}\\n\",\"keccak256\":\"0x7cfc021d0bd7e73b1ba8f4845d7d35e3419d6a14d3d25ca3a8010e7f91062fe4\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSplitAllocator.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport '../structs/JBSplitAllocationData.sol';\\n\\n/**\\n @title\\n Split allocator\\n\\n @notice\\n Provide a way to process a single split with extra logic\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n\\n @dev\\n The contract address should be set as an allocator in the adequate split\\n*/\\ninterface IJBSplitAllocator is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.distributePayoutOf(..), during the processing of the split including it\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control. The token and/or eth are optimistically transfered\\n to the allocator for its logic.\\n \\n @param _data the data passed by the terminal, as a JBSplitAllocationData struct:\\n address token;\\n uint256 amount;\\n uint256 decimals;\\n uint256 projectId;\\n uint256 group;\\n JBSplit split;\\n */\\n function allocate(JBSplitAllocationData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0x5efb6f51fc161f42ff58989386ad99028e4039a0ba897d66f358c3dfcf686105\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSplitsPayer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBSplit.sol';\\nimport './../structs/JBGroupedSplits.sol';\\nimport './IJBSplitsStore.sol';\\n\\ninterface IJBSplitsPayer is IERC165 {\\n event SetDefaultSplitsReference(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n address caller\\n );\\n event Pay(\\n uint256 indexed projectId,\\n address beneficiary,\\n address token,\\n uint256 amount,\\n uint256 decimals,\\n uint256 leftoverAmount,\\n uint256 minReturnedTokens,\\n bool preferClaimedTokens,\\n string memo,\\n bytes metadata,\\n address caller\\n );\\n\\n event AddToBalance(\\n uint256 indexed projectId,\\n address beneficiary,\\n address token,\\n uint256 amount,\\n uint256 decimals,\\n uint256 leftoverAmount,\\n string memo,\\n bytes metadata,\\n address caller\\n );\\n\\n event DistributeToSplitGroup(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n address caller\\n );\\n\\n event DistributeToSplit(\\n JBSplit split,\\n uint256 amount,\\n address defaultBeneficiary,\\n address caller\\n );\\n\\n function defaultSplitsProjectId() external view returns (uint256);\\n\\n function defaultSplitsDomain() external view returns (uint256);\\n\\n function defaultSplitsGroup() external view returns (uint256);\\n\\n function splitsStore() external view returns (IJBSplitsStore);\\n\\n function initialize(\\n uint256 _defaultSplitsProjectId,\\n uint256 _defaultSplitsDomain,\\n uint256 _defaultSplitsGroup,\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string memory _defaultMemo,\\n bytes memory _defaultMetadata,\\n bool _preferAddToBalance,\\n address _owner\\n ) external;\\n\\n function setDefaultSplitsReference(\\n uint256 _projectId,\\n uint256 _domain,\\n uint256 _group\\n ) external;\\n\\n function setDefaultSplits(\\n uint256 _projectId,\\n uint256 _domain,\\n uint256 _group,\\n JBGroupedSplits[] memory _splitsGroup\\n ) external;\\n}\\n\",\"keccak256\":\"0xb37aebcf7b3db4d026d635212ff27fca7467e5d6c0084d8331819f41555d4f20\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSplitsStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBGroupedSplits.sol';\\nimport './../structs/JBSplit.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBProjects.sol';\\n\\ninterface IJBSplitsStore {\\n event SetSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n address caller\\n );\\n\\n function projects() external view returns (IJBProjects);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function splitsOf(\\n uint256 _projectId,\\n uint256 _domain,\\n uint256 _group\\n ) external view returns (JBSplit[] memory);\\n\\n function set(\\n uint256 _projectId,\\n uint256 _domain,\\n JBGroupedSplits[] memory _groupedSplits\\n ) external;\\n}\\n\",\"keccak256\":\"0x66dab3dd394e318b850401ca92c2963b906cc0ad5562fa5d4f6f850175d1c77a\",\"license\":\"MIT\"},\"contracts/interfaces/IJBTokenUriResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBTokenUriResolver {\\n function getUri(uint256 _projectId) external view returns (string memory tokenUri);\\n}\\n\",\"keccak256\":\"0xd267fd8ca7c21c2c71794acdb9a98314c33a35fc559e0bf0897a6686d196d174\",\"license\":\"MIT\"},\"contracts/libraries/JBConstants.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/**\\n @notice\\n Global constants used across Juicebox contracts.\\n*/\\nlibrary JBConstants {\\n uint256 public constant MAX_RESERVED_RATE = 10_000;\\n uint256 public constant MAX_REDEMPTION_RATE = 10_000;\\n uint256 public constant MAX_DISCOUNT_RATE = 1_000_000_000;\\n uint256 public constant SPLITS_TOTAL_PERCENT = 1_000_000_000;\\n uint256 public constant MAX_FEE = 1_000_000_000;\\n uint256 public constant MAX_FEE_DISCOUNT = 1_000_000_000;\\n}\\n\",\"keccak256\":\"0x34362846a1cd428a8bdedf4ab6857e11402f345cb87b994b2e7fb6d2474b808d\",\"license\":\"MIT\"},\"contracts/libraries/JBTokens.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBTokens {\\n /** \\n @notice \\n The ETH token address in Juicebox is represented by 0x000000000000000000000000000000000000EEEe.\\n */\\n address public constant ETH = address(0x000000000000000000000000000000000000EEEe);\\n}\\n\",\"keccak256\":\"0xecf82992f7b827766aa55f16872517a646521eef414d8cc9786617ea377e5463\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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.\\n @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.\\n @member basedOn The `configuration` of the funding cycle that was active when this cycle was created.\\n @member start The timestamp marking the moment from which the funding cycle is considered active. It is a unix timestamp measured in seconds.\\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n @member metadata Extra data that can be associated with a funding cycle.\\n*/\\nstruct JBFundingCycle {\\n uint256 number;\\n uint256 configuration;\\n uint256 basedOn;\\n uint256 start;\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n uint256 metadata;\\n}\\n\",\"keccak256\":\"0xcdd3ac9b6fa67e62ada88d09b73bc35ade1cd77d43db712289266a788928b4c2\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycleData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n*/\\nstruct JBFundingCycleData {\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n}\\n\",\"keccak256\":\"0x2aa6368bf4dfc5797e8b02a978293de0c777fae2658de2c825a103587240f3b0\",\"license\":\"MIT\"},\"contracts/structs/JBGroupedSplits.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBSplit.sol';\\n\\n/** \\n @member group The group indentifier.\\n @member splits The splits to associate with the group.\\n*/\\nstruct JBGroupedSplits {\\n uint256 group;\\n JBSplit[] splits;\\n}\\n\",\"keccak256\":\"0x80be1b220da4ac04851ea540ebb94c1ec2b0442ec5bd1e88fdf78a56becd8b5a\",\"license\":\"MIT\"},\"contracts/structs/JBProjectMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member content The metadata content.\\n @member domain The domain within which the metadata applies.\\n*/\\nstruct JBProjectMetadata {\\n string content;\\n uint256 domain;\\n}\\n\",\"keccak256\":\"0x90ad7b1014c0a9f945fe7a2efde9d5de41e40574fa27969070b1d2ff52033ea0\",\"license\":\"MIT\"},\"contracts/structs/JBSplit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBSplitAllocator.sol';\\n\\n/** \\n @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.\\n @member preferAddToBalance A flag indicating if a distribution to a project should prefer triggering it's addToBalance function instead of its pay function.\\n @member percent The percent of the whole group that this split occupies. This number is out of `JBConstants.SPLITS_TOTAL_PERCENT`.\\n @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.\\n @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.\\n @member lockedUntil Specifies if the split should be unchangeable until the specified time, with the exception of extending the locked period.\\n @member allocator If an allocator is specified, funds will be sent to the allocator contract along with all properties of this split.\\n*/\\nstruct JBSplit {\\n bool preferClaimed;\\n bool preferAddToBalance;\\n uint256 percent;\\n uint256 projectId;\\n address payable beneficiary;\\n uint256 lockedUntil;\\n IJBSplitAllocator allocator;\\n}\\n\",\"keccak256\":\"0xc80a16606da8abf76d0f73abc38aee041e24f29342c1939018f70c286e89f105\",\"license\":\"MIT\"},\"contracts/structs/JBSplitAllocationData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBSplit.sol';\\n\\n/** \\n @member token The token being sent to the split allocator.\\n @member amount The amount being sent to the split allocator, as a fixed point number.\\n @member decimals The number of decimals in the amount.\\n @member projectId The project to which the split belongs.\\n @member group The group to which the split belongs.\\n @member split The split that caused the allocation.\\n*/\\nstruct JBSplitAllocationData {\\n address token;\\n uint256 amount;\\n uint256 decimals;\\n uint256 projectId;\\n uint256 group;\\n JBSplit split;\\n}\\n\",\"keccak256\":\"0x39f5c41bd31d36774744698ac94484b6cab62d7038df2f29d947668959782e63\",\"license\":\"MIT\"},\"prb-math/contracts/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivFixedPointOverflow(uint256 prod1);\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivOverflow(uint256 prod1, uint256 denominator);\\n\\n/// @notice Emitted when one of the inputs is type(int256).min.\\nerror PRBMath__MulDivSignedInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows int256.\\nerror PRBMath__MulDivSignedOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is MIN_SD59x18.\\nerror PRBMathSD59x18__AbsInputTooSmall();\\n\\n/// @notice Emitted when ceiling a number overflows SD59x18.\\nerror PRBMathSD59x18__CeilOverflow(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__DivInputTooSmall();\\n\\n/// @notice Emitted when one of the intermediary unsigned results overflows SD59x18.\\nerror PRBMathSD59x18__DivOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathSD59x18__ExpInputTooBig(int256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathSD59x18__Exp2InputTooBig(int256 x);\\n\\n/// @notice Emitted when flooring a number underflows SD59x18.\\nerror PRBMathSD59x18__FloorUnderflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format overflows SD59x18.\\nerror PRBMathSD59x18__FromIntOverflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format underflows SD59x18.\\nerror PRBMathSD59x18__FromIntUnderflow(int256 x);\\n\\n/// @notice Emitted when the product of the inputs is negative.\\nerror PRBMathSD59x18__GmNegativeProduct(int256 x, int256 y);\\n\\n/// @notice Emitted when multiplying the inputs overflows SD59x18.\\nerror PRBMathSD59x18__GmOverflow(int256 x, int256 y);\\n\\n/// @notice Emitted when the input is less than or equal to zero.\\nerror PRBMathSD59x18__LogInputTooSmall(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__MulInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__MulOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__PowuOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is negative.\\nerror PRBMathSD59x18__SqrtNegativeInput(int256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows SD59x18.\\nerror PRBMathSD59x18__SqrtOverflow(int256 x);\\n\\n/// @notice Emitted when addition overflows UD60x18.\\nerror PRBMathUD60x18__AddOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when ceiling a number overflows UD60x18.\\nerror PRBMathUD60x18__CeilOverflow(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathUD60x18__ExpInputTooBig(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathUD60x18__Exp2InputTooBig(uint256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format format overflows UD60x18.\\nerror PRBMathUD60x18__FromUintOverflow(uint256 x);\\n\\n/// @notice Emitted when multiplying the inputs overflows UD60x18.\\nerror PRBMathUD60x18__GmOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when the input is less than 1.\\nerror PRBMathUD60x18__LogInputTooSmall(uint256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows UD60x18.\\nerror PRBMathUD60x18__SqrtOverflow(uint256 x);\\n\\n/// @notice Emitted when subtraction underflows UD60x18.\\nerror PRBMathUD60x18__SubUnderflow(uint256 x, uint256 y);\\n\\n/// @dev Common mathematical functions used in both PRBMathSD59x18 and PRBMathUD60x18. Note that this shared library\\n/// does not always assume the signed 59.18-decimal fixed-point or the unsigned 60.18-decimal fixed-point\\n/// representation. When it does not, it is explicitly mentioned in the NatSpec documentation.\\nlibrary PRBMath {\\n /// STRUCTS ///\\n\\n struct SD59x18 {\\n int256 value;\\n }\\n\\n struct UD60x18 {\\n uint256 value;\\n }\\n\\n /// STORAGE ///\\n\\n /// @dev How many trailing decimals can be represented.\\n uint256 internal constant SCALE = 1e18;\\n\\n /// @dev Largest power of two divisor of SCALE.\\n uint256 internal constant SCALE_LPOTD = 262144;\\n\\n /// @dev SCALE inverted mod 2^256.\\n uint256 internal constant SCALE_INVERSE =\\n 78156646155174841979727994598816262306175212592076161876661_508869554232690281;\\n\\n /// FUNCTIONS ///\\n\\n /// @notice Calculates the binary exponent of x using the binary fraction method.\\n /// @dev Has to use 192.64-bit fixed-point numbers.\\n /// See https://ethereum.stackexchange.com/a/96594/24693.\\n /// @param x The exponent as an unsigned 192.64-bit fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp2(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n // Start from 0.5 in the 192.64-bit fixed-point format.\\n result = 0x800000000000000000000000000000000000000000000000;\\n\\n // Multiply the result by root(2, 2^-i) when the bit at position i is 1. None of the intermediary results overflows\\n // because the initial result is 2^191 and all magic factors are less than 2^65.\\n if (x & 0x8000000000000000 > 0) {\\n result = (result * 0x16A09E667F3BCC909) >> 64;\\n }\\n if (x & 0x4000000000000000 > 0) {\\n result = (result * 0x1306FE0A31B7152DF) >> 64;\\n }\\n if (x & 0x2000000000000000 > 0) {\\n result = (result * 0x1172B83C7D517ADCE) >> 64;\\n }\\n if (x & 0x1000000000000000 > 0) {\\n result = (result * 0x10B5586CF9890F62A) >> 64;\\n }\\n if (x & 0x800000000000000 > 0) {\\n result = (result * 0x1059B0D31585743AE) >> 64;\\n }\\n if (x & 0x400000000000000 > 0) {\\n result = (result * 0x102C9A3E778060EE7) >> 64;\\n }\\n if (x & 0x200000000000000 > 0) {\\n result = (result * 0x10163DA9FB33356D8) >> 64;\\n }\\n if (x & 0x100000000000000 > 0) {\\n result = (result * 0x100B1AFA5ABCBED61) >> 64;\\n }\\n if (x & 0x80000000000000 > 0) {\\n result = (result * 0x10058C86DA1C09EA2) >> 64;\\n }\\n if (x & 0x40000000000000 > 0) {\\n result = (result * 0x1002C605E2E8CEC50) >> 64;\\n }\\n if (x & 0x20000000000000 > 0) {\\n result = (result * 0x100162F3904051FA1) >> 64;\\n }\\n if (x & 0x10000000000000 > 0) {\\n result = (result * 0x1000B175EFFDC76BA) >> 64;\\n }\\n if (x & 0x8000000000000 > 0) {\\n result = (result * 0x100058BA01FB9F96D) >> 64;\\n }\\n if (x & 0x4000000000000 > 0) {\\n result = (result * 0x10002C5CC37DA9492) >> 64;\\n }\\n if (x & 0x2000000000000 > 0) {\\n result = (result * 0x1000162E525EE0547) >> 64;\\n }\\n if (x & 0x1000000000000 > 0) {\\n result = (result * 0x10000B17255775C04) >> 64;\\n }\\n if (x & 0x800000000000 > 0) {\\n result = (result * 0x1000058B91B5BC9AE) >> 64;\\n }\\n if (x & 0x400000000000 > 0) {\\n result = (result * 0x100002C5C89D5EC6D) >> 64;\\n }\\n if (x & 0x200000000000 > 0) {\\n result = (result * 0x10000162E43F4F831) >> 64;\\n }\\n if (x & 0x100000000000 > 0) {\\n result = (result * 0x100000B1721BCFC9A) >> 64;\\n }\\n if (x & 0x80000000000 > 0) {\\n result = (result * 0x10000058B90CF1E6E) >> 64;\\n }\\n if (x & 0x40000000000 > 0) {\\n result = (result * 0x1000002C5C863B73F) >> 64;\\n }\\n if (x & 0x20000000000 > 0) {\\n result = (result * 0x100000162E430E5A2) >> 64;\\n }\\n if (x & 0x10000000000 > 0) {\\n result = (result * 0x1000000B172183551) >> 64;\\n }\\n if (x & 0x8000000000 > 0) {\\n result = (result * 0x100000058B90C0B49) >> 64;\\n }\\n if (x & 0x4000000000 > 0) {\\n result = (result * 0x10000002C5C8601CC) >> 64;\\n }\\n if (x & 0x2000000000 > 0) {\\n result = (result * 0x1000000162E42FFF0) >> 64;\\n }\\n if (x & 0x1000000000 > 0) {\\n result = (result * 0x10000000B17217FBB) >> 64;\\n }\\n if (x & 0x800000000 > 0) {\\n result = (result * 0x1000000058B90BFCE) >> 64;\\n }\\n if (x & 0x400000000 > 0) {\\n result = (result * 0x100000002C5C85FE3) >> 64;\\n }\\n if (x & 0x200000000 > 0) {\\n result = (result * 0x10000000162E42FF1) >> 64;\\n }\\n if (x & 0x100000000 > 0) {\\n result = (result * 0x100000000B17217F8) >> 64;\\n }\\n if (x & 0x80000000 > 0) {\\n result = (result * 0x10000000058B90BFC) >> 64;\\n }\\n if (x & 0x40000000 > 0) {\\n result = (result * 0x1000000002C5C85FE) >> 64;\\n }\\n if (x & 0x20000000 > 0) {\\n result = (result * 0x100000000162E42FF) >> 64;\\n }\\n if (x & 0x10000000 > 0) {\\n result = (result * 0x1000000000B17217F) >> 64;\\n }\\n if (x & 0x8000000 > 0) {\\n result = (result * 0x100000000058B90C0) >> 64;\\n }\\n if (x & 0x4000000 > 0) {\\n result = (result * 0x10000000002C5C860) >> 64;\\n }\\n if (x & 0x2000000 > 0) {\\n result = (result * 0x1000000000162E430) >> 64;\\n }\\n if (x & 0x1000000 > 0) {\\n result = (result * 0x10000000000B17218) >> 64;\\n }\\n if (x & 0x800000 > 0) {\\n result = (result * 0x1000000000058B90C) >> 64;\\n }\\n if (x & 0x400000 > 0) {\\n result = (result * 0x100000000002C5C86) >> 64;\\n }\\n if (x & 0x200000 > 0) {\\n result = (result * 0x10000000000162E43) >> 64;\\n }\\n if (x & 0x100000 > 0) {\\n result = (result * 0x100000000000B1721) >> 64;\\n }\\n if (x & 0x80000 > 0) {\\n result = (result * 0x10000000000058B91) >> 64;\\n }\\n if (x & 0x40000 > 0) {\\n result = (result * 0x1000000000002C5C8) >> 64;\\n }\\n if (x & 0x20000 > 0) {\\n result = (result * 0x100000000000162E4) >> 64;\\n }\\n if (x & 0x10000 > 0) {\\n result = (result * 0x1000000000000B172) >> 64;\\n }\\n if (x & 0x8000 > 0) {\\n result = (result * 0x100000000000058B9) >> 64;\\n }\\n if (x & 0x4000 > 0) {\\n result = (result * 0x10000000000002C5D) >> 64;\\n }\\n if (x & 0x2000 > 0) {\\n result = (result * 0x1000000000000162E) >> 64;\\n }\\n if (x & 0x1000 > 0) {\\n result = (result * 0x10000000000000B17) >> 64;\\n }\\n if (x & 0x800 > 0) {\\n result = (result * 0x1000000000000058C) >> 64;\\n }\\n if (x & 0x400 > 0) {\\n result = (result * 0x100000000000002C6) >> 64;\\n }\\n if (x & 0x200 > 0) {\\n result = (result * 0x10000000000000163) >> 64;\\n }\\n if (x & 0x100 > 0) {\\n result = (result * 0x100000000000000B1) >> 64;\\n }\\n if (x & 0x80 > 0) {\\n result = (result * 0x10000000000000059) >> 64;\\n }\\n if (x & 0x40 > 0) {\\n result = (result * 0x1000000000000002C) >> 64;\\n }\\n if (x & 0x20 > 0) {\\n result = (result * 0x10000000000000016) >> 64;\\n }\\n if (x & 0x10 > 0) {\\n result = (result * 0x1000000000000000B) >> 64;\\n }\\n if (x & 0x8 > 0) {\\n result = (result * 0x10000000000000006) >> 64;\\n }\\n if (x & 0x4 > 0) {\\n result = (result * 0x10000000000000003) >> 64;\\n }\\n if (x & 0x2 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n if (x & 0x1 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n\\n // We're doing two things at the same time:\\n //\\n // 1. Multiply the result by 2^n + 1, where \\\"2^n\\\" is the integer part and the one is added to account for\\n // the fact that we initially set the result to 0.5. This is accomplished by subtracting from 191\\n // rather than 192.\\n // 2. Convert the result to the unsigned 60.18-decimal fixed-point format.\\n //\\n // This works because 2^(191-ip) = 2^ip / 2^191, where \\\"ip\\\" is the integer part \\\"2^n\\\".\\n result *= SCALE;\\n result >>= (191 - (x >> 64));\\n }\\n }\\n\\n /// @notice Finds the zero-based index of the first one in the binary representation of x.\\n /// @dev See the note on msb in the \\\"Find First Set\\\" Wikipedia article https://en.wikipedia.org/wiki/Find_first_set\\n /// @param x The uint256 number for which to find the index of the most significant bit.\\n /// @return msb The index of the most significant bit as an uint256.\\n function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\\n if (x >= 2**128) {\\n x >>= 128;\\n msb += 128;\\n }\\n if (x >= 2**64) {\\n x >>= 64;\\n msb += 64;\\n }\\n if (x >= 2**32) {\\n x >>= 32;\\n msb += 32;\\n }\\n if (x >= 2**16) {\\n x >>= 16;\\n msb += 16;\\n }\\n if (x >= 2**8) {\\n x >>= 8;\\n msb += 8;\\n }\\n if (x >= 2**4) {\\n x >>= 4;\\n msb += 4;\\n }\\n if (x >= 2**2) {\\n x >>= 2;\\n msb += 2;\\n }\\n if (x >= 2**1) {\\n // No need to shift x any more.\\n msb += 1;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.\\n ///\\n /// Requirements:\\n /// - The denominator cannot be zero.\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The multiplicand as an uint256.\\n /// @param y The multiplier as an uint256.\\n /// @param denominator The divisor as an uint256.\\n /// @return result The result as an uint256.\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n unchecked {\\n result = prod0 / denominator;\\n }\\n return result;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n if (prod1 >= denominator) {\\n revert PRBMath__MulDivOverflow(prod1, denominator);\\n }\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n unchecked {\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 lpotdod = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by lpotdod.\\n denominator := div(denominator, lpotdod)\\n\\n // Divide [prod1 prod0] by lpotdod.\\n prod0 := div(prod0, lpotdod)\\n\\n // Flip lpotdod such that it is 2^256 / lpotdod. If lpotdod is zero, then it becomes one.\\n lpotdod := add(div(sub(0, lpotdod), lpotdod), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * lpotdod;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f71e18) with full precision.\\n ///\\n /// @dev Variant of \\\"mulDiv\\\" with constant folding, i.e. in which the denominator is always 1e18. Before returning the\\n /// final result, we add 1 if (x * y) % SCALE >= HALF_SCALE. Without this, 6.6e-19 would be truncated to 0 instead of\\n /// being rounded to 1e-18. See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717.\\n ///\\n /// Requirements:\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - The body is purposely left uncommented; see the NatSpec comments in \\\"PRBMath.mulDiv\\\" to understand how this works.\\n /// - It is assumed that the result can never be type(uint256).max when x and y solve the following two equations:\\n /// 1. x * y = type(uint256).max * SCALE\\n /// 2. (x * y) % SCALE >= SCALE / 2\\n ///\\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function mulDivFixedPoint(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n uint256 prod0;\\n uint256 prod1;\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n if (prod1 >= SCALE) {\\n revert PRBMath__MulDivFixedPointOverflow(prod1);\\n }\\n\\n uint256 remainder;\\n uint256 roundUpUnit;\\n assembly {\\n remainder := mulmod(x, y, SCALE)\\n roundUpUnit := gt(remainder, 499999999999999999)\\n }\\n\\n if (prod1 == 0) {\\n unchecked {\\n result = (prod0 / SCALE) + roundUpUnit;\\n return result;\\n }\\n }\\n\\n assembly {\\n result := add(\\n mul(\\n or(\\n div(sub(prod0, remainder), SCALE_LPOTD),\\n mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, SCALE_LPOTD), SCALE_LPOTD), 1))\\n ),\\n SCALE_INVERSE\\n ),\\n roundUpUnit\\n )\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev An extension of \\\"mulDiv\\\" for signed numbers. Works by computing the signs and the absolute values separately.\\n ///\\n /// Requirements:\\n /// - None of the inputs can be type(int256).min.\\n /// - The result must fit within int256.\\n ///\\n /// @param x The multiplicand as an int256.\\n /// @param y The multiplier as an int256.\\n /// @param denominator The divisor as an int256.\\n /// @return result The result as an int256.\\n function mulDivSigned(\\n int256 x,\\n int256 y,\\n int256 denominator\\n ) internal pure returns (int256 result) {\\n if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {\\n revert PRBMath__MulDivSignedInputTooSmall();\\n }\\n\\n // Get hold of the absolute values of x, y and the denominator.\\n uint256 ax;\\n uint256 ay;\\n uint256 ad;\\n unchecked {\\n ax = x < 0 ? uint256(-x) : uint256(x);\\n ay = y < 0 ? uint256(-y) : uint256(y);\\n ad = denominator < 0 ? uint256(-denominator) : uint256(denominator);\\n }\\n\\n // Compute the absolute value of (x*y)\\u00f7denominator. The result must fit within int256.\\n uint256 rAbs = mulDiv(ax, ay, ad);\\n if (rAbs > uint256(type(int256).max)) {\\n revert PRBMath__MulDivSignedOverflow(rAbs);\\n }\\n\\n // Get the signs of x, y and the denominator.\\n uint256 sx;\\n uint256 sy;\\n uint256 sd;\\n assembly {\\n sx := sgt(x, sub(0, 1))\\n sy := sgt(y, sub(0, 1))\\n sd := sgt(denominator, sub(0, 1))\\n }\\n\\n // XOR over sx, sy and sd. This is checking whether there are one or three negative signs in the inputs.\\n // If yes, the result should be negative.\\n result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs);\\n }\\n\\n /// @notice Calculates the square root of x, rounding down.\\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The uint256 number for which to calculate the square root.\\n /// @return result The result as an uint256.\\n function sqrt(uint256 x) internal pure returns (uint256 result) {\\n if (x == 0) {\\n return 0;\\n }\\n\\n // Set the initial guess to the closest power of two that is higher than x.\\n uint256 xAux = uint256(x);\\n result = 1;\\n if (xAux >= 0x100000000000000000000000000000000) {\\n xAux >>= 128;\\n result <<= 64;\\n }\\n if (xAux >= 0x10000000000000000) {\\n xAux >>= 64;\\n result <<= 32;\\n }\\n if (xAux >= 0x100000000) {\\n xAux >>= 32;\\n result <<= 16;\\n }\\n if (xAux >= 0x10000) {\\n xAux >>= 16;\\n result <<= 8;\\n }\\n if (xAux >= 0x100) {\\n xAux >>= 8;\\n result <<= 4;\\n }\\n if (xAux >= 0x10) {\\n xAux >>= 4;\\n result <<= 2;\\n }\\n if (xAux >= 0x8) {\\n result <<= 1;\\n }\\n\\n // The operations can never overflow because the result is max 2^127 when it enters this block.\\n unchecked {\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1; // Seven iterations should be enough\\n uint256 roundedDownResult = x / result;\\n return result >= roundedDownResult ? roundedDownResult : result;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x62cbabae4910e168e99b9c2c3e3b5c9c7ad5e7abd961dcc63b7ea3d83d8ea87e\",\"license\":\"Unlicense\"}},\"version\":1}", + "metadata": "{\"compiler\":{\"version\":\"0.8.16+commit.07a7930e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IJBSplitsStore\",\"name\":\"_splitsStore\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IJBSplitsPayer\",\"name\":\"splitsPayer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"defaultSplitsProjectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"defaultSplitsDomain\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"defaultSplitsGroup\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"contract IJBSplitsStore\",\"name\":\"splitsStore\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"defaultProjectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"defaultBeneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"defaultPreferClaimedTokens\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"defaultMemo\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"defaultMetadata\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"preferAddToBalance\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"DeploySplitsPayer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_defaultSplitsProjectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_defaultSplitsDomain\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_defaultSplitsGroup\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_defaultProjectId\",\"type\":\"uint256\"},{\"internalType\":\"address payable\",\"name\":\"_defaultBeneficiary\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_defaultPreferClaimedTokens\",\"type\":\"bool\"},{\"internalType\":\"string\",\"name\":\"_defaultMemo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_defaultMetadata\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"_defaultPreferAddToBalance\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"deploySplitsPayer\",\"outputs\":[{\"internalType\":\"contract IJBSplitsPayer\",\"name\":\"splitsPayer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_defaultSplitsProjectId\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"preferClaimed\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"preferAddToBalance\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"percent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"lockedUntil\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBSplitAllocator\",\"name\":\"allocator\",\"type\":\"address\"}],\"internalType\":\"struct JBSplit[]\",\"name\":\"_defaultSplits\",\"type\":\"tuple[]\"},{\"internalType\":\"contract IJBSplitsStore\",\"name\":\"_splitsStore\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_defaultProjectId\",\"type\":\"uint256\"},{\"internalType\":\"address payable\",\"name\":\"_defaultBeneficiary\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_defaultPreferClaimedTokens\",\"type\":\"bool\"},{\"internalType\":\"string\",\"name\":\"_defaultMemo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_defaultMetadata\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"_defaultPreferAddToBalance\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"deploySplitsPayerWithSplits\",\"outputs\":[{\"internalType\":\"contract IJBSplitsPayer\",\"name\":\"splitsPayer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Adheres to - IJBGasTokenERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\",\"kind\":\"dev\",\"methods\":{\"deploySplitsPayer(uint256,uint256,uint256,uint256,address,bool,string,bytes,bool,address)\":{\"params\":{\"_defaultBeneficiary\":\"The address that'll receive the project's tokens when the splits payer receives payments. \",\"_defaultMemo\":\"The memo that'll be forwarded with the splits payer's received payments. \",\"_defaultMetadata\":\"The metadata that'll be forwarded with the splits payer's received payments. \",\"_defaultPreferAddToBalance\":\"A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\",\"_defaultPreferClaimedTokens\":\"A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \",\"_defaultProjectId\":\"The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\",\"_defaultSplitsDomain\":\"The splits domain to payout when this contract receives direct payments.\",\"_defaultSplitsGroup\":\"The splits group to payout when this contract receives direct payments.\",\"_defaultSplitsProjectId\":\"The ID of project for which the default splits are stored.\",\"_owner\":\"The address that will own the splits payer.\"},\"returns\":{\"splitsPayer\":\"The splits payer contract.\"}},\"deploySplitsPayerWithSplits(uint256,(bool,bool,uint256,uint256,address,uint256,address)[],address,uint256,address,bool,string,bytes,bool,address)\":{\"details\":\"This contract must have Operator permissions over the SET_SPLITS permission of the specified `_defaultSplitsProjectId`.\",\"params\":{\"_defaultBeneficiary\":\"The address that'll receive the project's tokens when the splits payer receives payments. \",\"_defaultMemo\":\"The memo that'll be forwarded with the splits payer's received payments. \",\"_defaultMetadata\":\"The metadata that'll be forwarded with the splits payer's received payments. \",\"_defaultPreferAddToBalance\":\"A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\",\"_defaultPreferClaimedTokens\":\"A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \",\"_defaultProjectId\":\"The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\",\"_defaultSplits\":\"The splits to payout when this contract receives direct payments.\",\"_defaultSplitsProjectId\":\"The ID of project for which the default splits are stored.\",\"_owner\":\"The address that will own the splits payer.\",\"_splitsStore\":\"A contract that stores splits for each project.\"},\"returns\":{\"splitsPayer\":\"The splits payer contract.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"deploySplitsPayer(uint256,uint256,uint256,uint256,address,bool,string,bytes,bool,address)\":{\"notice\":\" Allows anyone to deploy a new splits payer contract.\"},\"deploySplitsPayerWithSplits(uint256,(bool,bool,uint256,uint256,address,uint256,address)[],address,uint256,address,bool,string,bytes,bool,address)\":{\"notice\":\" Allows anyone to deploy a new splits payer contract.\"}},\"notice\":\" Deploys splits payer contracts.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/JBGasTokenERC20SplitsPayerDeployer.sol\":\"JBGasTokenERC20SplitsPayerDeployer\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0x24e0364e503a9bbde94c715d26573a76f14cd2a202d45f96f52134ab806b67b9\",\"license\":\"MIT\"},\"@openzeppelin/contracts/proxy/Clones.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/Clones.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for\\n * deploying minimal proxy contracts, also known as \\\"clones\\\".\\n *\\n * > To simply and cheaply clone contract functionality in an immutable way, this standard specifies\\n * > a minimal bytecode implementation that delegates all calls to a known, fixed address.\\n *\\n * The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2`\\n * (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the\\n * deterministic method.\\n *\\n * _Available since v3.4._\\n */\\nlibrary Clones {\\n /**\\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.\\n *\\n * This function uses the create opcode, which should never revert.\\n */\\n function clone(address implementation) internal returns (address instance) {\\n assembly {\\n let ptr := mload(0x40)\\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\\n mstore(add(ptr, 0x14), shl(0x60, implementation))\\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\\n instance := create(0, ptr, 0x37)\\n }\\n require(instance != address(0), \\\"ERC1167: create failed\\\");\\n }\\n\\n /**\\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.\\n *\\n * This function uses the create2 opcode and a `salt` to deterministically deploy\\n * the clone. Using the same `implementation` and `salt` multiple time will revert, since\\n * the clones cannot be deployed twice at the same address.\\n */\\n function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) {\\n assembly {\\n let ptr := mload(0x40)\\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\\n mstore(add(ptr, 0x14), shl(0x60, implementation))\\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\\n instance := create2(0, ptr, 0x37, salt)\\n }\\n require(instance != address(0), \\\"ERC1167: create2 failed\\\");\\n }\\n\\n /**\\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\\n */\\n function predictDeterministicAddress(\\n address implementation,\\n bytes32 salt,\\n address deployer\\n ) internal pure returns (address predicted) {\\n assembly {\\n let ptr := mload(0x40)\\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\\n mstore(add(ptr, 0x14), shl(0x60, implementation))\\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf3ff00000000000000000000000000000000)\\n mstore(add(ptr, 0x38), shl(0x60, deployer))\\n mstore(add(ptr, 0x4c), salt)\\n mstore(add(ptr, 0x6c), keccak256(ptr, 0x37))\\n predicted := keccak256(add(ptr, 0x37), 0x55)\\n }\\n }\\n\\n /**\\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\\n */\\n function predictDeterministicAddress(address implementation, bytes32 salt)\\n internal\\n view\\n returns (address predicted)\\n {\\n return predictDeterministicAddress(implementation, salt, address(this));\\n }\\n}\\n\",\"keccak256\":\"0x1cc0efb01cbf008b768fd7b334786a6e358809198bb7e67f1c530af4957c6a21\",\"license\":\"MIT\"},\"@openzeppelin/contracts/security/ReentrancyGuard.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuard {\\n // Booleans are more expensive than uint256 or any type that takes up a full\\n // word because each write operation emits an extra SLOAD to first read the\\n // slot's contents, replace the bits taken up by the boolean, and then write\\n // back. This is the compiler's defense against contract upgrades and\\n // pointer aliasing, and it cannot be disabled.\\n\\n // The values being non-zero value makes deployment a bit more expensive,\\n // but in exchange the refund on every call to nonReentrant will be lower in\\n // amount. Since refunds are capped to a percentage of the total\\n // transaction's gas, it is best to keep them low in cases like this one, to\\n // increase the likelihood of the full refund coming into effect.\\n uint256 private constant _NOT_ENTERED = 1;\\n uint256 private constant _ENTERED = 2;\\n\\n uint256 private _status;\\n\\n constructor() {\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and making it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n // On the first call to nonReentrant, _notEntered will be true\\n require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n _status = _ENTERED;\\n\\n _;\\n\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n _status = _NOT_ENTERED;\\n }\\n}\\n\",\"keccak256\":\"0x0e9621f60b2faabe65549f7ed0f24e8853a45c1b7990d47e8160e523683f3935\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address sender,\\n address recipient,\\n uint256 amount\\n ) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0x61437cb513a887a1bbad006e7b1c8b414478427d33de47c5600af3c748f108da\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(\\n IERC20 token,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(\\n IERC20 token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) {\\n // Return data is optional\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xc3d946432c0ddbb1f846a0d3985be71299df331b91d06732152117f62f0be2b5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool _approved) external;\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x516a22876c1fab47f49b1bc22b4614491cd05338af8bd2e7b382da090a079990\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3777e696b62134e6177440dbe6e6601c0c156a443f57167194b67e75527439de\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"@paulrberg/contracts/math/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\nimport \\\"prb-math/contracts/PRBMath.sol\\\";\\n\",\"keccak256\":\"0x42821345981bc0434a90ba2268a2f5278dfe9e38166981d72fc7f3b776a29495\",\"license\":\"Unlicense\"},\"contracts/JBGasTokenERC20ProjectPayer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport '@openzeppelin/contracts/access/Ownable.sol';\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\\nimport './interfaces/IJBProjectPayer.sol';\\nimport './libraries/JBTokens.sol';\\n\\n/** \\n @notice \\n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\\n\\n @dev\\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\\n\\n @dev\\n Adheres to -\\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n\\n @dev\\n Inherits from -\\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\\n ERC165: Introspection on interface adherance. \\n*/\\ncontract JBGasTokenERC20ProjectPayer is Ownable, ERC165, IJBProjectPayer {\\n using SafeERC20 for IERC20;\\n\\n //*********************************************************************//\\n // -------------------------- custom errors -------------------------- //\\n //*********************************************************************//\\n error INCORRECT_DECIMAL_AMOUNT();\\n error ALREADY_INITIALIZED();\\n error NO_MSG_VALUE_ALLOWED();\\n error TERMINAL_NOT_FOUND();\\n\\n //*********************************************************************//\\n // ------------------- public immutable properties ------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice \\n A contract storing directories of terminals and controllers for each project.\\n */\\n IJBDirectory public immutable override directory;\\n\\n /**\\n @notice \\n The deployer associated with this implementation. Used to rule out double initialization.\\n */\\n address public immutable override projectPayerDeployer;\\n\\n //*********************************************************************//\\n // --------------------- public stored properties -------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n The ID of the project that should be used to forward this contract's received payments.\\n */\\n uint256 public override defaultProjectId;\\n\\n /** \\n @notice \\n The beneficiary that should be used in the payment made when this contract receives payments.\\n */\\n address payable public override defaultBeneficiary;\\n\\n /** \\n @notice \\n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\\n */\\n bool public override defaultPreferClaimedTokens;\\n\\n /** \\n @notice \\n The memo that should be used in the payment made when this contract receives payments.\\n */\\n string public override defaultMemo;\\n\\n /** \\n @notice \\n The metadata that should be used in the payment made when this contract receives payments.\\n */\\n bytes public override defaultMetadata;\\n\\n /**\\n @notice \\n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\\n */\\n bool public override defaultPreferAddToBalance;\\n\\n //*********************************************************************//\\n // ------------------------- public views ---------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Indicates if this contract adheres to the specified interface.\\n\\n @dev \\n See {IERC165-supportsInterface}.\\n\\n @param _interfaceId The ID of the interface to check for adherance to.\\n */\\n function supportsInterface(bytes4 _interfaceId)\\n public\\n view\\n virtual\\n override(ERC165, IERC165)\\n returns (bool)\\n {\\n return\\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\\n }\\n\\n //*********************************************************************//\\n // -------------------------- constructors --------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @dev This is the constructor of the implementation. The directory is shared between project payers and is\\n immutable. If a new JBDirectory is needed, a new JBProjectPayerDeployer should be deployed.\\n @param _directory A contract storing directories of terminals and controllers for each project.\\n */\\n constructor(IJBDirectory _directory) {\\n directory = _directory;\\n projectPayerDeployer = msg.sender;\\n }\\n\\n /** \\n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\\n @param _defaultBeneficiary The address that'll receive the project's tokens. \\n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \\n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\\n @param _owner The address that will own the contract.\\n */\\n function initialize(\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string memory _defaultMemo,\\n bytes memory _defaultMetadata,\\n bool _defaultPreferAddToBalance,\\n address _owner\\n ) public {\\n if(msg.sender != projectPayerDeployer) revert ALREADY_INITIALIZED();\\n\\n defaultProjectId = _defaultProjectId;\\n defaultBeneficiary = _defaultBeneficiary;\\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\\n defaultMemo = _defaultMemo;\\n defaultMetadata = _defaultMetadata;\\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\\n _transferOwnership(_owner);\\n }\\n\\n //*********************************************************************//\\n // ------------------------- default receive ------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Received funds are paid to the default project ID using the stored default properties.\\n\\n @dev\\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\\n\\n @dev\\n This function is called automatically when the contract receives an ETH payment.\\n */\\n receive() external payable virtual override {\\n if (defaultPreferAddToBalance)\\n _addToBalanceOf(\\n defaultProjectId,\\n JBTokens.GAS_TOKEN,\\n address(this).balance,\\n 18, // balance is a fixed point number with 18 decimals.\\n defaultMemo,\\n defaultMetadata\\n );\\n else\\n _pay(\\n defaultProjectId,\\n JBTokens.GAS_TOKEN,\\n address(this).balance,\\n 18, // balance is a fixed point number with 18 decimals.\\n defaultBeneficiary == address(0) ? tx.origin : defaultBeneficiary,\\n 0, // Can't determine expectation of returned tokens ahead of time.\\n defaultPreferClaimedTokens,\\n defaultMemo,\\n defaultMetadata\\n );\\n }\\n\\n //*********************************************************************//\\n // ---------------------- external transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\\n\\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\\n @param _beneficiary The address that'll receive the project's tokens. \\n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \\n @param _memo The memo that'll be used. \\n @param _metadata The metadata that'll be sent. \\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\\n */\\n function setDefaultValues(\\n uint256 _projectId,\\n address payable _beneficiary,\\n bool _preferClaimedTokens,\\n string memory _memo,\\n bytes memory _metadata,\\n bool _defaultPreferAddToBalance\\n ) external virtual override onlyOwner {\\n // Set the default project ID if it has changed.\\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\\n\\n // Set the default beneficiary if it has changed.\\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\\n\\n // Set the default claimed token preference if it has changed.\\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\\n defaultPreferClaimedTokens = _preferClaimedTokens;\\n\\n // Set the default memo if it has changed.\\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\\n defaultMemo = _memo;\\n\\n // Set the default metadata if it has changed.\\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\\n defaultMetadata = _metadata;\\n\\n // Set the add to balance preference if it has changed.\\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\\n\\n emit SetDefaultValues(\\n _projectId,\\n _beneficiary,\\n _preferClaimedTokens,\\n _memo,\\n _metadata,\\n _defaultPreferAddToBalance,\\n msg.sender\\n );\\n }\\n\\n //*********************************************************************//\\n // ----------------------- public transactions ----------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n Make a payment to the specified project.\\n\\n @param _projectId The ID of the project that is being paid.\\n @param _token The token being paid in.\\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\\n @param _beneficiary The address who will receive tokens from the payment.\\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\\n */\\n function pay(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) public payable virtual override {\\n // ETH shouldn't be sent if the token isn't ETH.\\n if (address(_token) != JBTokens.GAS_TOKEN) {\\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\\n\\n // Get a reference to the balance before receiving tokens.\\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\\n\\n // Transfer tokens to this contract from the msg sender.\\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\\n\\n // The amount should reflect the change in balance.\\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\\n } else {\\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\\n _amount = msg.value;\\n _decimals = 18;\\n }\\n\\n _pay(\\n _projectId,\\n _token,\\n _amount,\\n _decimals,\\n _beneficiary,\\n _minReturnedTokens,\\n _preferClaimedTokens,\\n _memo,\\n _metadata\\n );\\n }\\n\\n /** \\n @notice \\n Add to the balance of the specified project.\\n\\n @param _projectId The ID of the project that is being paid.\\n @param _token The token being paid in.\\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Extra data to pass along to the terminal.\\n */\\n function addToBalanceOf(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) public payable virtual override {\\n // ETH shouldn't be sent if the token isn't ETH.\\n if (address(_token) != JBTokens.GAS_TOKEN) {\\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\\n\\n // Get a reference to the balance before receiving tokens.\\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\\n\\n // Transfer tokens to this contract from the msg sender.\\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\\n\\n // The amount should reflect the change in balance.\\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\\n } else {\\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\\n _amount = msg.value;\\n _decimals = 18;\\n }\\n\\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\\n }\\n\\n //*********************************************************************//\\n // ---------------------- internal transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n Make a payment to the specified project.\\n\\n @param _projectId The ID of the project that is being paid.\\n @param _token The token being paid in.\\n @param _amount The amount of tokens being paid, as a fixed point number. \\n @param _decimals The number of decimals in the `_amount` fixed point number. \\n @param _beneficiary The address who will receive tokens from the payment.\\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _metadata Bytes to send along to the data source and delegate, if provided.\\n */\\n function _pay(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string memory _memo,\\n bytes memory _metadata\\n ) internal virtual {\\n // Find the terminal for the specified project.\\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\\n\\n // There must be a terminal.\\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\\n\\n // The amount's decimals must match the terminal's expected decimals.\\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\\n\\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).safeApprove(address(_terminal), _amount);\\n\\n // If the token is ETH, send it in msg.value.\\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\\n\\n // Send funds to the terminal.\\n // If the token is ETH, send it in msg.value.\\n _terminal.pay{value: _payableValue}(\\n _projectId,\\n _amount, // ignored if the token is JBTokens.GAS_TOKEN.\\n _token,\\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\\n ? defaultBeneficiary\\n : tx.origin,\\n _minReturnedTokens,\\n _preferClaimedTokens,\\n _memo,\\n _metadata\\n );\\n }\\n\\n /** \\n @notice \\n Add to the balance of the specified project.\\n\\n @param _projectId The ID of the project that is being paid.\\n @param _token The token being paid in.\\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Extra data to pass along to the terminal.\\n */\\n function _addToBalanceOf(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n string memory _memo,\\n bytes memory _metadata\\n ) internal virtual {\\n // Find the terminal for the specified project.\\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\\n\\n // There must be a terminal.\\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\\n\\n // The amount's decimals must match the terminal's expected decimals.\\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\\n\\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).safeApprove(address(_terminal), _amount);\\n\\n // If the token is ETH, send it in msg.value.\\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\\n\\n // Add to balance so tokens don't get issued.\\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\\n }\\n}\\n\",\"keccak256\":\"0xcbadf8e217bb9c43d18161ce576235277834988ea7cb51d58b5a794914e9156c\",\"license\":\"MIT\"},\"contracts/JBGasTokenERC20SplitsPayer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport '@openzeppelin/contracts/utils/Address.sol';\\nimport '@paulrberg/contracts/math/PRBMath.sol';\\nimport './interfaces/IJBSplitsPayer.sol';\\nimport './interfaces/IJBSplitsStore.sol';\\nimport './libraries/JBConstants.sol';\\nimport './JBGasTokenERC20ProjectPayer.sol';\\n\\n/** \\n @notice \\n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\\n\\n @dev\\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\\n\\n @dev\\n Adheres to -\\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n\\n @dev\\n Inherits from -\\n JBGasTokenERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\\n*/\\ncontract JBGasTokenERC20SplitsPayer is JBGasTokenERC20ProjectPayer, ReentrancyGuard, IJBSplitsPayer {\\n using SafeERC20 for IERC20;\\n\\n //*********************************************************************//\\n // ---------------- public immutable stored properties --------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The contract that stores splits for each project.\\n */\\n IJBSplitsStore public immutable override splitsStore;\\n\\n //*********************************************************************//\\n // --------------------- public stored properties -------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The ID of project for which the default splits are stored. \\n */\\n uint256 public override defaultSplitsProjectId;\\n\\n /**\\n @notice\\n The domain within which the default splits are stored. \\n */\\n uint256 public override defaultSplitsDomain;\\n\\n /**\\n @notice\\n The group within which the default splits are stored. \\n */\\n uint256 public override defaultSplitsGroup;\\n\\n //*********************************************************************//\\n // -------------------------- public views --------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Indicates if this contract adheres to the specified interface.\\n\\n @dev \\n See {IERC165-supportsInterface}.\\n\\n @param _interfaceId The ID of the interface to check for adherance to.\\n\\n @return A flag indicating if this contract adheres to the specified interface.\\n */\\n function supportsInterface(bytes4 _interfaceId)\\n public\\n view\\n virtual\\n override(JBGasTokenERC20ProjectPayer, IERC165)\\n returns (bool)\\n {\\n return\\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\\n }\\n\\n //*********************************************************************//\\n // -------------------------- constructor ---------------------------- //\\n //*********************************************************************//\\n/**\\n @param _splitsStore A contract that stores splits for each project.\\n*/\\n constructor(\\n IJBSplitsStore _splitsStore\\n )\\n JBGasTokenERC20ProjectPayer(\\n _splitsStore.directory()\\n )\\n {\\n splitsStore = _splitsStore;\\n }\\n /**\\n @dev The re-initialize check is done in the inherited paroject payer\\n \\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\\n @param _defaultBeneficiary The address that'll receive the project's tokens. \\n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \\n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\\n @param _owner The address that will own the contract.\\n */\\n function initialize(\\n uint256 _defaultSplitsProjectId,\\n uint256 _defaultSplitsDomain,\\n uint256 _defaultSplitsGroup,\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string memory _defaultMemo,\\n bytes memory _defaultMetadata,\\n bool _preferAddToBalance,\\n address _owner\\n ) external override {\\n\\n super.initialize(\\n _defaultProjectId,\\n _defaultBeneficiary,\\n _defaultPreferClaimedTokens,\\n _defaultMemo,\\n _defaultMetadata,\\n _preferAddToBalance,\\n _owner\\n );\\n\\n defaultSplitsProjectId = _defaultSplitsProjectId;\\n defaultSplitsDomain = _defaultSplitsDomain;\\n defaultSplitsGroup = _defaultSplitsGroup;\\n }\\n\\n\\n\\n //*********************************************************************//\\n // ------------------------- default receive ------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Received funds are paid to the default split group using the stored default properties.\\n\\n @dev\\n This function is called automatically when the contract receives an ETH payment.\\n */\\n receive() external payable virtual override nonReentrant {\\n // Pay the splits and get a reference to the amount leftover.\\n uint256 _leftoverAmount = _payToSplits(\\n defaultSplitsProjectId,\\n defaultSplitsDomain,\\n defaultSplitsGroup,\\n JBTokens.GAS_TOKEN,\\n address(this).balance,\\n 18, // decimals.\\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\\n );\\n\\n // If there is no leftover amount, nothing left to pay.\\n if (_leftoverAmount == 0) return;\\n\\n // If there's a default project ID, try to pay it.\\n if (defaultProjectId != 0)\\n if (defaultPreferAddToBalance)\\n // Pay the project by adding to its balance if prefered.\\n _addToBalanceOf(\\n defaultProjectId,\\n JBTokens.GAS_TOKEN,\\n _leftoverAmount,\\n 18, // decimals.\\n defaultMemo,\\n defaultMetadata\\n );\\n // Otherwise, issue a payment to the project.\\n else\\n _pay(\\n defaultProjectId,\\n JBTokens.GAS_TOKEN,\\n _leftoverAmount,\\n 18, // decimals.\\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\\n 0, // min returned tokens.\\n defaultPreferClaimedTokens,\\n defaultMemo,\\n defaultMetadata\\n );\\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\\n else\\n Address.sendValue(\\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(tx.origin),\\n _leftoverAmount\\n );\\n }\\n\\n //*********************************************************************//\\n // ---------------------- external transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Sets the splits in the splits store that payments this contract receives will be split between.\\n\\n @param _projectId The ID of project for which the default splits are stored. \\n @param _domain The domain within which the default splits are stored. \\n @param _group The group within which the default splits are stored. \\n @param _groupedSplits The split groups to set.\\n */\\n function setDefaultSplits(\\n uint256 _projectId,\\n uint256 _domain,\\n uint256 _group,\\n JBGroupedSplits[] memory _groupedSplits\\n ) external virtual override onlyOwner {\\n // Set the splits in the store.\\n splitsStore.set(_projectId, _domain, _groupedSplits);\\n\\n // Set the splits reference.\\n setDefaultSplitsReference(_projectId, _domain, _group);\\n }\\n\\n //*********************************************************************//\\n // ----------------------- public transactions ----------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Sets the location of the splits that payments this contract receives will be split between.\\n\\n @param _projectId The ID of project for which the default splits are stored. \\n @param _domain The domain within which the default splits are stored. \\n @param _group The group within which the default splits are stored. \\n */\\n function setDefaultSplitsReference(\\n uint256 _projectId,\\n uint256 _domain,\\n uint256 _group\\n ) public virtual override onlyOwner {\\n // Set the default splits project ID if it's changing.\\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\\n\\n // Set the default splits domain if it's changing.\\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\\n\\n // Set the default splits group if it's changing.\\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\\n\\n emit SetDefaultSplitsReference(_projectId, _domain, _group, msg.sender);\\n }\\n\\n /** \\n @notice \\n Make a payment to the specified project after first splitting the amount among the stored default splits.\\n\\n @param _projectId The ID of the project that is being paid after.\\n @param _token The token being paid in.\\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\\n */\\n function pay(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) public payable virtual override nonReentrant {\\n // ETH shouldn't be sent if the token isn't ETH.\\n if (address(_token) != JBTokens.GAS_TOKEN) {\\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\\n\\n // Get a reference to the balance before receiving tokens.\\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\\n\\n // Transfer tokens to this contract from the msg sender.\\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\\n\\n // The amount should reflect the change in balance.\\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\\n } else {\\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\\n _amount = msg.value;\\n _decimals = 18;\\n }\\n\\n // Pay the splits and get a reference to the amount leftover.\\n uint256 _leftoverAmount = _payToSplits(\\n defaultSplitsProjectId,\\n defaultSplitsDomain,\\n defaultSplitsGroup,\\n _token,\\n _amount,\\n _decimals,\\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\\n );\\n\\n // Pay any leftover amount.\\n if (_leftoverAmount > 0) {\\n // If there's a default project ID, try to pay it.\\n if (_projectId != 0) {\\n _pay(\\n _projectId,\\n _token,\\n _leftoverAmount,\\n _decimals,\\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\\n ? defaultBeneficiary\\n : tx.origin,\\n _minReturnedTokens,\\n _preferClaimedTokens,\\n _memo,\\n _metadata\\n );\\n }\\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\\n else {\\n // Transfer the ETH.\\n if (_token == JBTokens.GAS_TOKEN)\\n Address.sendValue(\\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\\n _beneficiary != address(0) ? payable(_beneficiary) : defaultBeneficiary != address(0)\\n ? defaultBeneficiary\\n : payable(tx.origin),\\n _leftoverAmount\\n );\\n // Or, transfer the ERC20.\\n else\\n IERC20(_token).safeTransfer(\\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\\n ? defaultBeneficiary\\n : tx.origin,\\n _leftoverAmount\\n );\\n }\\n }\\n\\n emit Pay(\\n _projectId,\\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\\n ? defaultBeneficiary\\n : tx.origin,\\n _token,\\n _amount,\\n _decimals,\\n _leftoverAmount,\\n _minReturnedTokens,\\n _preferClaimedTokens,\\n _memo,\\n _metadata,\\n msg.sender\\n );\\n }\\n\\n /** \\n @notice \\n Add to the balance of the specified project after first splitting the amount among the stored default splits.\\n\\n @param _projectId The ID of the project that is being paid after.\\n @param _token The token being paid in.\\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\\n @param _memo A memo to pass along to the emitted event. \\n @param _metadata Extra data to pass along to the terminal.\\n */\\n function addToBalanceOf(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) public payable virtual override nonReentrant {\\n // ETH shouldn't be sent if this terminal's token isn't ETH.\\n if (address(_token) != JBTokens.GAS_TOKEN) {\\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\\n\\n // Get a reference to the balance before receiving tokens.\\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\\n\\n // Transfer tokens to this contract from the msg sender.\\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\\n\\n // The amount should reflect the change in balance.\\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\\n } else {\\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\\n _amount = msg.value;\\n _decimals = 18;\\n }\\n\\n // Pay the splits and get a reference to the amount leftover.\\n uint256 _leftoverAmount = _payToSplits(\\n defaultSplitsProjectId,\\n defaultSplitsDomain,\\n defaultSplitsGroup,\\n _token,\\n _amount,\\n _decimals,\\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\\n );\\n\\n // Distribute any leftover amount.\\n if (_leftoverAmount > 0) {\\n // If there's a default project ID, try to add to its balance.\\n if (_projectId != 0)\\n // Add to the project's balance.\\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\\n\\n // Otherwise, send a payment to the beneficiary.\\n else {\\n // Transfer the ETH.\\n if (_token == JBTokens.GAS_TOKEN)\\n Address.sendValue(\\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(tx.origin),\\n _leftoverAmount\\n );\\n // Or, transfer the ERC20.\\n else\\n IERC20(_token).safeTransfer(\\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\\n _leftoverAmount\\n );\\n }\\n }\\n\\n emit AddToBalance(\\n _projectId,\\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\\n _token,\\n _amount,\\n _decimals,\\n _leftoverAmount,\\n _memo,\\n _metadata,\\n msg.sender\\n );\\n }\\n\\n //*********************************************************************//\\n // ---------------------- internal transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n Split an amount between all splits.\\n\\n @param _splitsProjectId The ID of the project to which the splits belong.\\n @param _splitsDomain The splits domain to which the group belongs.\\n @param _splitsGroup The splits group to pay.\\n @param _token The token the amonut being split is in.\\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\\n @param _decimals The number of decimals in the `_amount` fixed point number. \\n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\\n\\n @return leftoverAmount The amount leftover after all splits were paid.\\n */\\n function _payToSplits(\\n uint256 _splitsProjectId,\\n uint256 _splitsDomain,\\n uint256 _splitsGroup,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n address _defaultBeneficiary\\n ) internal virtual returns (uint256 leftoverAmount) {\\n // Pay the splits.\\n leftoverAmount = _payTo(\\n splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup),\\n _token,\\n _amount,\\n _decimals,\\n _defaultBeneficiary\\n );\\n emit DistributeToSplitGroup(_splitsProjectId, _splitsDomain, _splitsGroup, msg.sender);\\n }\\n\\n /** \\n @notice \\n Split an amount between all splits.\\n\\n @param _splits The splits.\\n @param _token The token the amonut being split is in.\\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\\n @param _decimals The number of decimals in the `_amount` fixed point number. \\n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\\n\\n @return leftoverAmount The amount leftover after all splits were paid.\\n */\\n function _payTo(\\n JBSplit[] memory _splits,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n address _defaultBeneficiary\\n ) internal virtual returns (uint256 leftoverAmount) {\\n // Set the leftover amount to the initial balance.\\n leftoverAmount = _amount;\\n\\n // Settle between all splits.\\n for (uint256 i; i < _splits.length; ) {\\n // Get a reference to the split being iterated on.\\n JBSplit memory _split = _splits[i];\\n\\n // The amount to send towards the split.\\n uint256 _splitAmount = PRBMath.mulDiv(\\n _amount,\\n _split.percent,\\n JBConstants.SPLITS_TOTAL_PERCENT\\n );\\n\\n if (_splitAmount > 0) {\\n // Transfer tokens to the split.\\n // If there's an allocator set, transfer to its `allocate` function.\\n if (_split.allocator != IJBSplitAllocator(address(0))) {\\n // Create the data to send to the allocator.\\n JBSplitAllocationData memory _data = JBSplitAllocationData(\\n _token,\\n _splitAmount,\\n _decimals,\\n defaultProjectId,\\n 0,\\n _split\\n );\\n\\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\\n if (_token != JBTokens.GAS_TOKEN)\\n IERC20(_token).safeApprove(address(_split.allocator), _splitAmount);\\n\\n // If the token is ETH, send it in msg.value.\\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _splitAmount : 0;\\n\\n // Trigger the allocator's `allocate` function.\\n _split.allocator.allocate{value: _payableValue}(_data);\\n\\n // Otherwise, if a project is specified, make a payment to it.\\n } else if (_split.projectId != 0) {\\n if (_split.preferAddToBalance)\\n _addToBalanceOf(\\n _split.projectId,\\n _token,\\n _splitAmount,\\n _decimals,\\n defaultMemo,\\n defaultMetadata\\n );\\n else\\n _pay(\\n _split.projectId,\\n _token,\\n _splitAmount,\\n _decimals,\\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\\n 0,\\n _split.preferClaimed,\\n defaultMemo,\\n defaultMetadata\\n );\\n } else {\\n // Transfer the ETH.\\n if (_token == JBTokens.GAS_TOKEN)\\n Address.sendValue(\\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\\n _split.beneficiary != address(0) ? _split.beneficiary : payable(_defaultBeneficiary),\\n _splitAmount\\n );\\n // Or, transfer the ERC20.\\n else {\\n IERC20(_token).safeTransfer(\\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\\n _splitAmount\\n );\\n }\\n }\\n\\n // Subtract from the amount to be sent to the beneficiary.\\n leftoverAmount = leftoverAmount - _splitAmount;\\n }\\n\\n emit DistributeToSplit(_split, _splitAmount, _defaultBeneficiary, msg.sender);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x19b81077f19b544d6ad5c6b945584fd9187c774f0f85e2965475ade2da15ae42\",\"license\":\"MIT\"},\"contracts/JBGasTokenERC20SplitsPayerDeployer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport { Clones } from '@openzeppelin/contracts/proxy/Clones.sol';\\n\\nimport './interfaces/IJBGasTokenERC20SplitsPayerDeployer.sol';\\nimport './structs/JBSplit.sol';\\nimport './structs/JBGroupedSplits.sol';\\nimport './JBGasTokenERC20SplitsPayer.sol';\\n\\n/** \\n @notice \\n Deploys splits payer contracts.\\n\\n @dev\\n Adheres to -\\n IJBGasTokenERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n*/\\ncontract JBGasTokenERC20SplitsPayerDeployer is IJBGasTokenERC20SplitsPayerDeployer {\\n\\n address immutable implementation;\\n\\n IJBSplitsStore immutable splitsStore;\\n\\n constructor(IJBSplitsStore _splitsStore) {\\n implementation = address(new JBGasTokenERC20SplitsPayer(_splitsStore));\\n splitsStore = _splitsStore;\\n }\\n\\n //*********************************************************************//\\n // ---------------------- external transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n Allows anyone to deploy a new splits payer contract.\\n\\n @dev\\n This contract must have Operator permissions over the SET_SPLITS permission of the specified `_defaultSplitsProjectId`.\\n\\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\\n @param _defaultSplits The splits to payout when this contract receives direct payments.\\n @param _splitsStore A contract that stores splits for each project.\\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \\n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \\n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \\n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\\n @param _owner The address that will own the splits payer.\\n\\n @return splitsPayer The splits payer contract.\\n */\\n function deploySplitsPayerWithSplits(\\n uint256 _defaultSplitsProjectId,\\n JBSplit[] memory _defaultSplits,\\n IJBSplitsStore _splitsStore,\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string memory _defaultMemo,\\n bytes memory _defaultMetadata,\\n bool _defaultPreferAddToBalance,\\n address _owner\\n ) external override returns (IJBSplitsPayer splitsPayer) {\\n // Use this contract's address as the domain.\\n uint256 _domain = uint256(uint160(address(this)));\\n\\n // Create the random hash using data unique to this instance that'll be used as the storage domain.\\n uint256 _group = uint256(keccak256(abi.encodePacked(msg.sender, block.number)));\\n\\n // Set the splits in the store.\\n JBGroupedSplits[] memory _groupedSplits;\\n _groupedSplits = new JBGroupedSplits[](1);\\n _groupedSplits[0] = JBGroupedSplits(_group, _defaultSplits);\\n _splitsStore.set(_defaultSplitsProjectId, _domain, _groupedSplits);\\n\\n return\\n deploySplitsPayer(\\n _defaultSplitsProjectId,\\n _domain,\\n _group,\\n _defaultProjectId,\\n _defaultBeneficiary,\\n _defaultPreferClaimedTokens,\\n _defaultMemo,\\n _defaultMetadata,\\n _defaultPreferAddToBalance,\\n _owner\\n );\\n }\\n\\n //*********************************************************************//\\n // ---------------------- public transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n Allows anyone to deploy a new splits payer contract.\\n\\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \\n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \\n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \\n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\\n @param _owner The address that will own the splits payer.\\n\\n @return splitsPayer The splits payer contract.\\n */\\n function deploySplitsPayer(\\n uint256 _defaultSplitsProjectId,\\n uint256 _defaultSplitsDomain,\\n uint256 _defaultSplitsGroup,\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string memory _defaultMemo,\\n bytes memory _defaultMetadata,\\n bool _defaultPreferAddToBalance,\\n address _owner\\n ) public override returns (IJBSplitsPayer splitsPayer) {\\n\\n // Deploy the splits payer.\\n splitsPayer = IJBSplitsPayer(payable(Clones.clone(implementation)));\\n\\n splitsPayer.initialize(\\n _defaultSplitsProjectId,\\n _defaultSplitsDomain,\\n _defaultSplitsGroup,\\n _defaultProjectId,\\n _defaultBeneficiary,\\n _defaultPreferClaimedTokens,\\n _defaultMemo,\\n _defaultMetadata,\\n _defaultPreferAddToBalance,\\n _owner\\n );\\n\\n emit DeploySplitsPayer(\\n splitsPayer,\\n _defaultSplitsProjectId,\\n _defaultSplitsDomain,\\n _defaultSplitsGroup,\\n splitsStore,\\n _defaultProjectId,\\n _defaultBeneficiary,\\n _defaultPreferClaimedTokens,\\n _defaultMemo,\\n _defaultMetadata,\\n _defaultPreferAddToBalance,\\n _owner,\\n msg.sender\\n );\\n }\\n}\\n\",\"keccak256\":\"0x1d772589f0079d573ea80929092e23a4b2bc9a41f0e930dc1efb10d7fc731d81\",\"license\":\"MIT\"},\"contracts/enums/JBBallotState.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nenum JBBallotState {\\n Active,\\n Approved,\\n Failed\\n}\\n\",\"keccak256\":\"0x891fcac63470398b3a11239da7feba6b07d640809fcefd2404303b823d7378f8\",\"license\":\"MIT\"},\"contracts/interfaces/IJBDirectory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBProjects.sol';\\n\\ninterface IJBDirectory {\\n event SetController(uint256 indexed projectId, address indexed controller, address caller);\\n\\n event AddTerminal(uint256 indexed projectId, IJBPaymentTerminal indexed terminal, address caller);\\n\\n event SetTerminals(uint256 indexed projectId, IJBPaymentTerminal[] terminals, address caller);\\n\\n event SetPrimaryTerminal(\\n uint256 indexed projectId,\\n address indexed token,\\n IJBPaymentTerminal indexed terminal,\\n address caller\\n );\\n\\n event SetIsAllowedToSetFirstController(address indexed addr, bool indexed flag, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function controllerOf(uint256 _projectId) external view returns (address);\\n\\n function isAllowedToSetFirstController(address _address) external view returns (bool);\\n\\n function terminalsOf(uint256 _projectId) external view returns (IJBPaymentTerminal[] memory);\\n\\n function isTerminalOf(uint256 _projectId, IJBPaymentTerminal _terminal)\\n external\\n view\\n returns (bool);\\n\\n function primaryTerminalOf(uint256 _projectId, address _token)\\n external\\n view\\n returns (IJBPaymentTerminal);\\n\\n function setControllerOf(uint256 _projectId, address _controller) external;\\n\\n function setTerminalsOf(uint256 _projectId, IJBPaymentTerminal[] calldata _terminals) external;\\n\\n function setPrimaryTerminalOf(\\n uint256 _projectId,\\n address _token,\\n IJBPaymentTerminal _terminal\\n ) external;\\n\\n function setIsAllowedToSetFirstController(address _address, bool _flag) external;\\n}\\n\",\"keccak256\":\"0x715321646db00514d1355ed43c40cd3f01e94959552fd07797b315d9c49cdb1d\",\"license\":\"MIT\"},\"contracts/interfaces/IJBGasTokenERC20SplitsPayerDeployer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBSplitsPayer.sol';\\nimport './IJBSplitsStore.sol';\\n\\ninterface IJBGasTokenERC20SplitsPayerDeployer {\\n event DeploySplitsPayer(\\n IJBSplitsPayer indexed splitsPayer,\\n uint256 defaultSplitsProjectId,\\n uint256 defaultSplitsDomain,\\n uint256 defaultSplitsGroup,\\n IJBSplitsStore splitsStore,\\n uint256 defaultProjectId,\\n address defaultBeneficiary,\\n bool defaultPreferClaimedTokens,\\n string defaultMemo,\\n bytes defaultMetadata,\\n bool preferAddToBalance,\\n address owner,\\n address caller\\n );\\n\\n function deploySplitsPayer(\\n uint256 _defaultSplitsProjectId,\\n uint256 _defaultSplitsDomain,\\n uint256 _defaultSplitsGroup,\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string calldata _defaultMemo,\\n bytes calldata _defaultMetadata,\\n bool _preferAddToBalance,\\n address _owner\\n ) external returns (IJBSplitsPayer splitsPayer);\\n\\n function deploySplitsPayerWithSplits(\\n uint256 _defaultSplitsProjectId,\\n JBSplit[] memory _defaultSplits,\\n IJBSplitsStore _splitsStore,\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string memory _defaultMemo,\\n bytes memory _defaultMetadata,\\n bool _defaultPreferAddToBalance,\\n address _owner\\n ) external returns (IJBSplitsPayer splitsPayer);\\n}\\n\",\"keccak256\":\"0xc476797aa84a54530cdbaff6a9e8c2fc8bf90a051dd51a17a00c51345db2798c\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleBallot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../enums/JBBallotState.sol';\\n\\ninterface IJBFundingCycleBallot is IERC165 {\\n function duration() external view returns (uint256);\\n\\n function stateOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n uint256 _start\\n ) external view returns (JBBallotState);\\n}\\n\",\"keccak256\":\"0x49553a56209237846bc400cf27f260824a6bd06fd8094a7eb5abb9de75779598\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../enums/JBBallotState.sol';\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBFundingCycleData.sol';\\n\\ninterface IJBFundingCycleStore {\\n event Configure(\\n uint256 indexed configuration,\\n uint256 indexed projectId,\\n JBFundingCycleData data,\\n uint256 metadata,\\n uint256 mustStartAtOrAfter,\\n address caller\\n );\\n\\n event Init(uint256 indexed configuration, uint256 indexed projectId, uint256 indexed basedOn);\\n\\n function latestConfigurationOf(uint256 _projectId) external view returns (uint256);\\n\\n function get(uint256 _projectId, uint256 _configuration)\\n external\\n view\\n returns (JBFundingCycle memory);\\n\\n function latestConfiguredOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBBallotState ballotState);\\n\\n function queuedOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentBallotStateOf(uint256 _projectId) external view returns (JBBallotState);\\n\\n function configureFor(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n uint256 _metadata,\\n uint256 _mustStartAtOrAfter\\n ) external returns (JBFundingCycle memory fundingCycle);\\n}\\n\",\"keccak256\":\"0xaead823851433be0c2ddc8f8086813e6cd647de3a1bc0f7570a5d6b38c378b5a\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\n\\ninterface IJBPaymentTerminal is IERC165 {\\n function acceptsToken(address _token, uint256 _projectId) external view returns (bool);\\n\\n function currencyForToken(address _token) external view returns (uint256);\\n\\n function decimalsForToken(address _token) external view returns (uint256);\\n\\n // Return value must be a fixed point number with 18 decimals.\\n function currentEthOverflowOf(uint256 _projectId) external view returns (uint256);\\n\\n function pay(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable returns (uint256 beneficiaryTokenCount);\\n\\n function addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable;\\n}\\n\",\"keccak256\":\"0xb7826f5ed609359ce322c09e83236c47ba385df1c3cad3607e56fd0a2e00eee2\",\"license\":\"MIT\"},\"contracts/interfaces/IJBProjectPayer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './IJBDirectory.sol';\\n\\ninterface IJBProjectPayer is IERC165 {\\n event SetDefaultValues(\\n uint256 indexed projectId,\\n address indexed beneficiary,\\n bool preferClaimedTokens,\\n string memo,\\n bytes metadata,\\n bool preferAddToBalance,\\n address caller\\n );\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function projectPayerDeployer() external view returns (address);\\n\\n function defaultProjectId() external view returns (uint256);\\n\\n function defaultBeneficiary() external view returns (address payable);\\n\\n function defaultPreferClaimedTokens() external view returns (bool);\\n\\n function defaultMemo() external view returns (string memory);\\n\\n function defaultMetadata() external view returns (bytes memory);\\n\\n function defaultPreferAddToBalance() external view returns (bool);\\n\\n function initialize(\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string memory _defaultMemo,\\n bytes memory _defaultMetadata,\\n bool _defaultPreferAddToBalance,\\n address _owner\\n ) external;\\n\\n function setDefaultValues(\\n uint256 _projectId,\\n address payable _beneficiary,\\n bool _preferClaimedTokens,\\n string memory _memo,\\n bytes memory _metadata,\\n bool _defaultPreferAddToBalance\\n ) external;\\n\\n function pay(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string memory _memo,\\n bytes memory _metadata\\n ) external payable;\\n\\n function addToBalanceOf(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n string memory _memo,\\n bytes memory _metadata\\n ) external payable;\\n\\n receive() external payable;\\n}\\n\",\"keccak256\":\"0x85f4cbd5482e26618994f742c149a5bd3cb3dc39dbeba85b21c36b3215007df6\",\"license\":\"MIT\"},\"contracts/interfaces/IJBProjects.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBTokenUriResolver.sol';\\n\\ninterface IJBProjects is IERC721 {\\n event Create(\\n uint256 indexed projectId,\\n address indexed owner,\\n JBProjectMetadata metadata,\\n address caller\\n );\\n\\n event SetMetadata(uint256 indexed projectId, JBProjectMetadata metadata, address caller);\\n\\n event SetTokenUriResolver(IJBTokenUriResolver indexed resolver, address caller);\\n\\n function count() external view returns (uint256);\\n\\n function metadataContentOf(uint256 _projectId, uint256 _domain)\\n external\\n view\\n returns (string memory);\\n\\n function tokenUriResolver() external view returns (IJBTokenUriResolver);\\n\\n function createFor(address _owner, JBProjectMetadata calldata _metadata)\\n external\\n returns (uint256 projectId);\\n\\n function setMetadataOf(uint256 _projectId, JBProjectMetadata calldata _metadata) external;\\n\\n function setTokenUriResolver(IJBTokenUriResolver _newResolver) external;\\n}\\n\",\"keccak256\":\"0x7cfc021d0bd7e73b1ba8f4845d7d35e3419d6a14d3d25ca3a8010e7f91062fe4\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSplitAllocator.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport '../structs/JBSplitAllocationData.sol';\\n\\n/**\\n @title\\n Split allocator\\n\\n @notice\\n Provide a way to process a single split with extra logic\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n\\n @dev\\n The contract address should be set as an allocator in the adequate split\\n*/\\ninterface IJBSplitAllocator is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.distributePayoutOf(..), during the processing of the split including it\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control. The token and/or eth are optimistically transfered\\n to the allocator for its logic.\\n \\n @param _data the data passed by the terminal, as a JBSplitAllocationData struct:\\n address token;\\n uint256 amount;\\n uint256 decimals;\\n uint256 projectId;\\n uint256 group;\\n JBSplit split;\\n */\\n function allocate(JBSplitAllocationData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0x5efb6f51fc161f42ff58989386ad99028e4039a0ba897d66f358c3dfcf686105\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSplitsPayer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBSplit.sol';\\nimport './../structs/JBGroupedSplits.sol';\\nimport './IJBSplitsStore.sol';\\n\\ninterface IJBSplitsPayer is IERC165 {\\n event SetDefaultSplitsReference(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n address caller\\n );\\n event Pay(\\n uint256 indexed projectId,\\n address beneficiary,\\n address token,\\n uint256 amount,\\n uint256 decimals,\\n uint256 leftoverAmount,\\n uint256 minReturnedTokens,\\n bool preferClaimedTokens,\\n string memo,\\n bytes metadata,\\n address caller\\n );\\n\\n event AddToBalance(\\n uint256 indexed projectId,\\n address beneficiary,\\n address token,\\n uint256 amount,\\n uint256 decimals,\\n uint256 leftoverAmount,\\n string memo,\\n bytes metadata,\\n address caller\\n );\\n\\n event DistributeToSplitGroup(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n address caller\\n );\\n\\n event DistributeToSplit(\\n JBSplit split,\\n uint256 amount,\\n address defaultBeneficiary,\\n address caller\\n );\\n\\n function defaultSplitsProjectId() external view returns (uint256);\\n\\n function defaultSplitsDomain() external view returns (uint256);\\n\\n function defaultSplitsGroup() external view returns (uint256);\\n\\n function splitsStore() external view returns (IJBSplitsStore);\\n\\n function initialize(\\n uint256 _defaultSplitsProjectId,\\n uint256 _defaultSplitsDomain,\\n uint256 _defaultSplitsGroup,\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string memory _defaultMemo,\\n bytes memory _defaultMetadata,\\n bool _preferAddToBalance,\\n address _owner\\n ) external;\\n\\n function setDefaultSplitsReference(\\n uint256 _projectId,\\n uint256 _domain,\\n uint256 _group\\n ) external;\\n\\n function setDefaultSplits(\\n uint256 _projectId,\\n uint256 _domain,\\n uint256 _group,\\n JBGroupedSplits[] memory _splitsGroup\\n ) external;\\n}\\n\",\"keccak256\":\"0xb37aebcf7b3db4d026d635212ff27fca7467e5d6c0084d8331819f41555d4f20\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSplitsStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBGroupedSplits.sol';\\nimport './../structs/JBSplit.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBProjects.sol';\\n\\ninterface IJBSplitsStore {\\n event SetSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n address caller\\n );\\n\\n function projects() external view returns (IJBProjects);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function splitsOf(\\n uint256 _projectId,\\n uint256 _domain,\\n uint256 _group\\n ) external view returns (JBSplit[] memory);\\n\\n function set(\\n uint256 _projectId,\\n uint256 _domain,\\n JBGroupedSplits[] memory _groupedSplits\\n ) external;\\n}\\n\",\"keccak256\":\"0x66dab3dd394e318b850401ca92c2963b906cc0ad5562fa5d4f6f850175d1c77a\",\"license\":\"MIT\"},\"contracts/interfaces/IJBTokenUriResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBTokenUriResolver {\\n function getUri(uint256 _projectId) external view returns (string memory tokenUri);\\n}\\n\",\"keccak256\":\"0xd267fd8ca7c21c2c71794acdb9a98314c33a35fc559e0bf0897a6686d196d174\",\"license\":\"MIT\"},\"contracts/libraries/JBConstants.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/**\\n @notice\\n Global constants used across Juicebox contracts.\\n*/\\nlibrary JBConstants {\\n uint256 public constant MAX_RESERVED_RATE = 10_000;\\n uint256 public constant MAX_REDEMPTION_RATE = 10_000;\\n uint256 public constant MAX_DISCOUNT_RATE = 1_000_000_000;\\n uint256 public constant SPLITS_TOTAL_PERCENT = 1_000_000_000;\\n uint256 public constant MAX_FEE = 1_000_000_000;\\n uint256 public constant MAX_FEE_DISCOUNT = 1_000_000_000;\\n}\\n\",\"keccak256\":\"0x34362846a1cd428a8bdedf4ab6857e11402f345cb87b994b2e7fb6d2474b808d\",\"license\":\"MIT\"},\"contracts/libraries/JBTokens.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBTokens {\\n /** \\n @notice \\n The ETH token address in Juicebox is represented by 0x000000000000000000000000000000000000EEEe.\\n */\\n address public constant ETH = address(0x000000000000000000000000000000000000EEEe);\\n}\\n\",\"keccak256\":\"0xecf82992f7b827766aa55f16872517a646521eef414d8cc9786617ea377e5463\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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.\\n @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.\\n @member basedOn The `configuration` of the funding cycle that was active when this cycle was created.\\n @member start The timestamp marking the moment from which the funding cycle is considered active. It is a unix timestamp measured in seconds.\\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n @member metadata Extra data that can be associated with a funding cycle.\\n*/\\nstruct JBFundingCycle {\\n uint256 number;\\n uint256 configuration;\\n uint256 basedOn;\\n uint256 start;\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n uint256 metadata;\\n}\\n\",\"keccak256\":\"0xcdd3ac9b6fa67e62ada88d09b73bc35ade1cd77d43db712289266a788928b4c2\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycleData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n*/\\nstruct JBFundingCycleData {\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n}\\n\",\"keccak256\":\"0x2aa6368bf4dfc5797e8b02a978293de0c777fae2658de2c825a103587240f3b0\",\"license\":\"MIT\"},\"contracts/structs/JBGroupedSplits.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBSplit.sol';\\n\\n/** \\n @member group The group indentifier.\\n @member splits The splits to associate with the group.\\n*/\\nstruct JBGroupedSplits {\\n uint256 group;\\n JBSplit[] splits;\\n}\\n\",\"keccak256\":\"0x80be1b220da4ac04851ea540ebb94c1ec2b0442ec5bd1e88fdf78a56becd8b5a\",\"license\":\"MIT\"},\"contracts/structs/JBProjectMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member content The metadata content.\\n @member domain The domain within which the metadata applies.\\n*/\\nstruct JBProjectMetadata {\\n string content;\\n uint256 domain;\\n}\\n\",\"keccak256\":\"0x90ad7b1014c0a9f945fe7a2efde9d5de41e40574fa27969070b1d2ff52033ea0\",\"license\":\"MIT\"},\"contracts/structs/JBSplit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBSplitAllocator.sol';\\n\\n/** \\n @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.\\n @member preferAddToBalance A flag indicating if a distribution to a project should prefer triggering it's addToBalance function instead of its pay function.\\n @member percent The percent of the whole group that this split occupies. This number is out of `JBConstants.SPLITS_TOTAL_PERCENT`.\\n @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.\\n @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.\\n @member lockedUntil Specifies if the split should be unchangeable until the specified time, with the exception of extending the locked period.\\n @member allocator If an allocator is specified, funds will be sent to the allocator contract along with all properties of this split.\\n*/\\nstruct JBSplit {\\n bool preferClaimed;\\n bool preferAddToBalance;\\n uint256 percent;\\n uint256 projectId;\\n address payable beneficiary;\\n uint256 lockedUntil;\\n IJBSplitAllocator allocator;\\n}\\n\",\"keccak256\":\"0xc80a16606da8abf76d0f73abc38aee041e24f29342c1939018f70c286e89f105\",\"license\":\"MIT\"},\"contracts/structs/JBSplitAllocationData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBSplit.sol';\\n\\n/** \\n @member token The token being sent to the split allocator.\\n @member amount The amount being sent to the split allocator, as a fixed point number.\\n @member decimals The number of decimals in the amount.\\n @member projectId The project to which the split belongs.\\n @member group The group to which the split belongs.\\n @member split The split that caused the allocation.\\n*/\\nstruct JBSplitAllocationData {\\n address token;\\n uint256 amount;\\n uint256 decimals;\\n uint256 projectId;\\n uint256 group;\\n JBSplit split;\\n}\\n\",\"keccak256\":\"0x39f5c41bd31d36774744698ac94484b6cab62d7038df2f29d947668959782e63\",\"license\":\"MIT\"},\"prb-math/contracts/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivFixedPointOverflow(uint256 prod1);\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivOverflow(uint256 prod1, uint256 denominator);\\n\\n/// @notice Emitted when one of the inputs is type(int256).min.\\nerror PRBMath__MulDivSignedInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows int256.\\nerror PRBMath__MulDivSignedOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is MIN_SD59x18.\\nerror PRBMathSD59x18__AbsInputTooSmall();\\n\\n/// @notice Emitted when ceiling a number overflows SD59x18.\\nerror PRBMathSD59x18__CeilOverflow(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__DivInputTooSmall();\\n\\n/// @notice Emitted when one of the intermediary unsigned results overflows SD59x18.\\nerror PRBMathSD59x18__DivOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathSD59x18__ExpInputTooBig(int256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathSD59x18__Exp2InputTooBig(int256 x);\\n\\n/// @notice Emitted when flooring a number underflows SD59x18.\\nerror PRBMathSD59x18__FloorUnderflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format overflows SD59x18.\\nerror PRBMathSD59x18__FromIntOverflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format underflows SD59x18.\\nerror PRBMathSD59x18__FromIntUnderflow(int256 x);\\n\\n/// @notice Emitted when the product of the inputs is negative.\\nerror PRBMathSD59x18__GmNegativeProduct(int256 x, int256 y);\\n\\n/// @notice Emitted when multiplying the inputs overflows SD59x18.\\nerror PRBMathSD59x18__GmOverflow(int256 x, int256 y);\\n\\n/// @notice Emitted when the input is less than or equal to zero.\\nerror PRBMathSD59x18__LogInputTooSmall(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__MulInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__MulOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__PowuOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is negative.\\nerror PRBMathSD59x18__SqrtNegativeInput(int256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows SD59x18.\\nerror PRBMathSD59x18__SqrtOverflow(int256 x);\\n\\n/// @notice Emitted when addition overflows UD60x18.\\nerror PRBMathUD60x18__AddOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when ceiling a number overflows UD60x18.\\nerror PRBMathUD60x18__CeilOverflow(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathUD60x18__ExpInputTooBig(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathUD60x18__Exp2InputTooBig(uint256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format format overflows UD60x18.\\nerror PRBMathUD60x18__FromUintOverflow(uint256 x);\\n\\n/// @notice Emitted when multiplying the inputs overflows UD60x18.\\nerror PRBMathUD60x18__GmOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when the input is less than 1.\\nerror PRBMathUD60x18__LogInputTooSmall(uint256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows UD60x18.\\nerror PRBMathUD60x18__SqrtOverflow(uint256 x);\\n\\n/// @notice Emitted when subtraction underflows UD60x18.\\nerror PRBMathUD60x18__SubUnderflow(uint256 x, uint256 y);\\n\\n/// @dev Common mathematical functions used in both PRBMathSD59x18 and PRBMathUD60x18. Note that this shared library\\n/// does not always assume the signed 59.18-decimal fixed-point or the unsigned 60.18-decimal fixed-point\\n/// representation. When it does not, it is explicitly mentioned in the NatSpec documentation.\\nlibrary PRBMath {\\n /// STRUCTS ///\\n\\n struct SD59x18 {\\n int256 value;\\n }\\n\\n struct UD60x18 {\\n uint256 value;\\n }\\n\\n /// STORAGE ///\\n\\n /// @dev How many trailing decimals can be represented.\\n uint256 internal constant SCALE = 1e18;\\n\\n /// @dev Largest power of two divisor of SCALE.\\n uint256 internal constant SCALE_LPOTD = 262144;\\n\\n /// @dev SCALE inverted mod 2^256.\\n uint256 internal constant SCALE_INVERSE =\\n 78156646155174841979727994598816262306175212592076161876661_508869554232690281;\\n\\n /// FUNCTIONS ///\\n\\n /// @notice Calculates the binary exponent of x using the binary fraction method.\\n /// @dev Has to use 192.64-bit fixed-point numbers.\\n /// See https://ethereum.stackexchange.com/a/96594/24693.\\n /// @param x The exponent as an unsigned 192.64-bit fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp2(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n // Start from 0.5 in the 192.64-bit fixed-point format.\\n result = 0x800000000000000000000000000000000000000000000000;\\n\\n // Multiply the result by root(2, 2^-i) when the bit at position i is 1. None of the intermediary results overflows\\n // because the initial result is 2^191 and all magic factors are less than 2^65.\\n if (x & 0x8000000000000000 > 0) {\\n result = (result * 0x16A09E667F3BCC909) >> 64;\\n }\\n if (x & 0x4000000000000000 > 0) {\\n result = (result * 0x1306FE0A31B7152DF) >> 64;\\n }\\n if (x & 0x2000000000000000 > 0) {\\n result = (result * 0x1172B83C7D517ADCE) >> 64;\\n }\\n if (x & 0x1000000000000000 > 0) {\\n result = (result * 0x10B5586CF9890F62A) >> 64;\\n }\\n if (x & 0x800000000000000 > 0) {\\n result = (result * 0x1059B0D31585743AE) >> 64;\\n }\\n if (x & 0x400000000000000 > 0) {\\n result = (result * 0x102C9A3E778060EE7) >> 64;\\n }\\n if (x & 0x200000000000000 > 0) {\\n result = (result * 0x10163DA9FB33356D8) >> 64;\\n }\\n if (x & 0x100000000000000 > 0) {\\n result = (result * 0x100B1AFA5ABCBED61) >> 64;\\n }\\n if (x & 0x80000000000000 > 0) {\\n result = (result * 0x10058C86DA1C09EA2) >> 64;\\n }\\n if (x & 0x40000000000000 > 0) {\\n result = (result * 0x1002C605E2E8CEC50) >> 64;\\n }\\n if (x & 0x20000000000000 > 0) {\\n result = (result * 0x100162F3904051FA1) >> 64;\\n }\\n if (x & 0x10000000000000 > 0) {\\n result = (result * 0x1000B175EFFDC76BA) >> 64;\\n }\\n if (x & 0x8000000000000 > 0) {\\n result = (result * 0x100058BA01FB9F96D) >> 64;\\n }\\n if (x & 0x4000000000000 > 0) {\\n result = (result * 0x10002C5CC37DA9492) >> 64;\\n }\\n if (x & 0x2000000000000 > 0) {\\n result = (result * 0x1000162E525EE0547) >> 64;\\n }\\n if (x & 0x1000000000000 > 0) {\\n result = (result * 0x10000B17255775C04) >> 64;\\n }\\n if (x & 0x800000000000 > 0) {\\n result = (result * 0x1000058B91B5BC9AE) >> 64;\\n }\\n if (x & 0x400000000000 > 0) {\\n result = (result * 0x100002C5C89D5EC6D) >> 64;\\n }\\n if (x & 0x200000000000 > 0) {\\n result = (result * 0x10000162E43F4F831) >> 64;\\n }\\n if (x & 0x100000000000 > 0) {\\n result = (result * 0x100000B1721BCFC9A) >> 64;\\n }\\n if (x & 0x80000000000 > 0) {\\n result = (result * 0x10000058B90CF1E6E) >> 64;\\n }\\n if (x & 0x40000000000 > 0) {\\n result = (result * 0x1000002C5C863B73F) >> 64;\\n }\\n if (x & 0x20000000000 > 0) {\\n result = (result * 0x100000162E430E5A2) >> 64;\\n }\\n if (x & 0x10000000000 > 0) {\\n result = (result * 0x1000000B172183551) >> 64;\\n }\\n if (x & 0x8000000000 > 0) {\\n result = (result * 0x100000058B90C0B49) >> 64;\\n }\\n if (x & 0x4000000000 > 0) {\\n result = (result * 0x10000002C5C8601CC) >> 64;\\n }\\n if (x & 0x2000000000 > 0) {\\n result = (result * 0x1000000162E42FFF0) >> 64;\\n }\\n if (x & 0x1000000000 > 0) {\\n result = (result * 0x10000000B17217FBB) >> 64;\\n }\\n if (x & 0x800000000 > 0) {\\n result = (result * 0x1000000058B90BFCE) >> 64;\\n }\\n if (x & 0x400000000 > 0) {\\n result = (result * 0x100000002C5C85FE3) >> 64;\\n }\\n if (x & 0x200000000 > 0) {\\n result = (result * 0x10000000162E42FF1) >> 64;\\n }\\n if (x & 0x100000000 > 0) {\\n result = (result * 0x100000000B17217F8) >> 64;\\n }\\n if (x & 0x80000000 > 0) {\\n result = (result * 0x10000000058B90BFC) >> 64;\\n }\\n if (x & 0x40000000 > 0) {\\n result = (result * 0x1000000002C5C85FE) >> 64;\\n }\\n if (x & 0x20000000 > 0) {\\n result = (result * 0x100000000162E42FF) >> 64;\\n }\\n if (x & 0x10000000 > 0) {\\n result = (result * 0x1000000000B17217F) >> 64;\\n }\\n if (x & 0x8000000 > 0) {\\n result = (result * 0x100000000058B90C0) >> 64;\\n }\\n if (x & 0x4000000 > 0) {\\n result = (result * 0x10000000002C5C860) >> 64;\\n }\\n if (x & 0x2000000 > 0) {\\n result = (result * 0x1000000000162E430) >> 64;\\n }\\n if (x & 0x1000000 > 0) {\\n result = (result * 0x10000000000B17218) >> 64;\\n }\\n if (x & 0x800000 > 0) {\\n result = (result * 0x1000000000058B90C) >> 64;\\n }\\n if (x & 0x400000 > 0) {\\n result = (result * 0x100000000002C5C86) >> 64;\\n }\\n if (x & 0x200000 > 0) {\\n result = (result * 0x10000000000162E43) >> 64;\\n }\\n if (x & 0x100000 > 0) {\\n result = (result * 0x100000000000B1721) >> 64;\\n }\\n if (x & 0x80000 > 0) {\\n result = (result * 0x10000000000058B91) >> 64;\\n }\\n if (x & 0x40000 > 0) {\\n result = (result * 0x1000000000002C5C8) >> 64;\\n }\\n if (x & 0x20000 > 0) {\\n result = (result * 0x100000000000162E4) >> 64;\\n }\\n if (x & 0x10000 > 0) {\\n result = (result * 0x1000000000000B172) >> 64;\\n }\\n if (x & 0x8000 > 0) {\\n result = (result * 0x100000000000058B9) >> 64;\\n }\\n if (x & 0x4000 > 0) {\\n result = (result * 0x10000000000002C5D) >> 64;\\n }\\n if (x & 0x2000 > 0) {\\n result = (result * 0x1000000000000162E) >> 64;\\n }\\n if (x & 0x1000 > 0) {\\n result = (result * 0x10000000000000B17) >> 64;\\n }\\n if (x & 0x800 > 0) {\\n result = (result * 0x1000000000000058C) >> 64;\\n }\\n if (x & 0x400 > 0) {\\n result = (result * 0x100000000000002C6) >> 64;\\n }\\n if (x & 0x200 > 0) {\\n result = (result * 0x10000000000000163) >> 64;\\n }\\n if (x & 0x100 > 0) {\\n result = (result * 0x100000000000000B1) >> 64;\\n }\\n if (x & 0x80 > 0) {\\n result = (result * 0x10000000000000059) >> 64;\\n }\\n if (x & 0x40 > 0) {\\n result = (result * 0x1000000000000002C) >> 64;\\n }\\n if (x & 0x20 > 0) {\\n result = (result * 0x10000000000000016) >> 64;\\n }\\n if (x & 0x10 > 0) {\\n result = (result * 0x1000000000000000B) >> 64;\\n }\\n if (x & 0x8 > 0) {\\n result = (result * 0x10000000000000006) >> 64;\\n }\\n if (x & 0x4 > 0) {\\n result = (result * 0x10000000000000003) >> 64;\\n }\\n if (x & 0x2 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n if (x & 0x1 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n\\n // We're doing two things at the same time:\\n //\\n // 1. Multiply the result by 2^n + 1, where \\\"2^n\\\" is the integer part and the one is added to account for\\n // the fact that we initially set the result to 0.5. This is accomplished by subtracting from 191\\n // rather than 192.\\n // 2. Convert the result to the unsigned 60.18-decimal fixed-point format.\\n //\\n // This works because 2^(191-ip) = 2^ip / 2^191, where \\\"ip\\\" is the integer part \\\"2^n\\\".\\n result *= SCALE;\\n result >>= (191 - (x >> 64));\\n }\\n }\\n\\n /// @notice Finds the zero-based index of the first one in the binary representation of x.\\n /// @dev See the note on msb in the \\\"Find First Set\\\" Wikipedia article https://en.wikipedia.org/wiki/Find_first_set\\n /// @param x The uint256 number for which to find the index of the most significant bit.\\n /// @return msb The index of the most significant bit as an uint256.\\n function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\\n if (x >= 2**128) {\\n x >>= 128;\\n msb += 128;\\n }\\n if (x >= 2**64) {\\n x >>= 64;\\n msb += 64;\\n }\\n if (x >= 2**32) {\\n x >>= 32;\\n msb += 32;\\n }\\n if (x >= 2**16) {\\n x >>= 16;\\n msb += 16;\\n }\\n if (x >= 2**8) {\\n x >>= 8;\\n msb += 8;\\n }\\n if (x >= 2**4) {\\n x >>= 4;\\n msb += 4;\\n }\\n if (x >= 2**2) {\\n x >>= 2;\\n msb += 2;\\n }\\n if (x >= 2**1) {\\n // No need to shift x any more.\\n msb += 1;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.\\n ///\\n /// Requirements:\\n /// - The denominator cannot be zero.\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The multiplicand as an uint256.\\n /// @param y The multiplier as an uint256.\\n /// @param denominator The divisor as an uint256.\\n /// @return result The result as an uint256.\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n unchecked {\\n result = prod0 / denominator;\\n }\\n return result;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n if (prod1 >= denominator) {\\n revert PRBMath__MulDivOverflow(prod1, denominator);\\n }\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n unchecked {\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 lpotdod = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by lpotdod.\\n denominator := div(denominator, lpotdod)\\n\\n // Divide [prod1 prod0] by lpotdod.\\n prod0 := div(prod0, lpotdod)\\n\\n // Flip lpotdod such that it is 2^256 / lpotdod. If lpotdod is zero, then it becomes one.\\n lpotdod := add(div(sub(0, lpotdod), lpotdod), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * lpotdod;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f71e18) with full precision.\\n ///\\n /// @dev Variant of \\\"mulDiv\\\" with constant folding, i.e. in which the denominator is always 1e18. Before returning the\\n /// final result, we add 1 if (x * y) % SCALE >= HALF_SCALE. Without this, 6.6e-19 would be truncated to 0 instead of\\n /// being rounded to 1e-18. See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717.\\n ///\\n /// Requirements:\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - The body is purposely left uncommented; see the NatSpec comments in \\\"PRBMath.mulDiv\\\" to understand how this works.\\n /// - It is assumed that the result can never be type(uint256).max when x and y solve the following two equations:\\n /// 1. x * y = type(uint256).max * SCALE\\n /// 2. (x * y) % SCALE >= SCALE / 2\\n ///\\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function mulDivFixedPoint(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n uint256 prod0;\\n uint256 prod1;\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n if (prod1 >= SCALE) {\\n revert PRBMath__MulDivFixedPointOverflow(prod1);\\n }\\n\\n uint256 remainder;\\n uint256 roundUpUnit;\\n assembly {\\n remainder := mulmod(x, y, SCALE)\\n roundUpUnit := gt(remainder, 499999999999999999)\\n }\\n\\n if (prod1 == 0) {\\n unchecked {\\n result = (prod0 / SCALE) + roundUpUnit;\\n return result;\\n }\\n }\\n\\n assembly {\\n result := add(\\n mul(\\n or(\\n div(sub(prod0, remainder), SCALE_LPOTD),\\n mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, SCALE_LPOTD), SCALE_LPOTD), 1))\\n ),\\n SCALE_INVERSE\\n ),\\n roundUpUnit\\n )\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev An extension of \\\"mulDiv\\\" for signed numbers. Works by computing the signs and the absolute values separately.\\n ///\\n /// Requirements:\\n /// - None of the inputs can be type(int256).min.\\n /// - The result must fit within int256.\\n ///\\n /// @param x The multiplicand as an int256.\\n /// @param y The multiplier as an int256.\\n /// @param denominator The divisor as an int256.\\n /// @return result The result as an int256.\\n function mulDivSigned(\\n int256 x,\\n int256 y,\\n int256 denominator\\n ) internal pure returns (int256 result) {\\n if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {\\n revert PRBMath__MulDivSignedInputTooSmall();\\n }\\n\\n // Get hold of the absolute values of x, y and the denominator.\\n uint256 ax;\\n uint256 ay;\\n uint256 ad;\\n unchecked {\\n ax = x < 0 ? uint256(-x) : uint256(x);\\n ay = y < 0 ? uint256(-y) : uint256(y);\\n ad = denominator < 0 ? uint256(-denominator) : uint256(denominator);\\n }\\n\\n // Compute the absolute value of (x*y)\\u00f7denominator. The result must fit within int256.\\n uint256 rAbs = mulDiv(ax, ay, ad);\\n if (rAbs > uint256(type(int256).max)) {\\n revert PRBMath__MulDivSignedOverflow(rAbs);\\n }\\n\\n // Get the signs of x, y and the denominator.\\n uint256 sx;\\n uint256 sy;\\n uint256 sd;\\n assembly {\\n sx := sgt(x, sub(0, 1))\\n sy := sgt(y, sub(0, 1))\\n sd := sgt(denominator, sub(0, 1))\\n }\\n\\n // XOR over sx, sy and sd. This is checking whether there are one or three negative signs in the inputs.\\n // If yes, the result should be negative.\\n result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs);\\n }\\n\\n /// @notice Calculates the square root of x, rounding down.\\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The uint256 number for which to calculate the square root.\\n /// @return result The result as an uint256.\\n function sqrt(uint256 x) internal pure returns (uint256 result) {\\n if (x == 0) {\\n return 0;\\n }\\n\\n // Set the initial guess to the closest power of two that is higher than x.\\n uint256 xAux = uint256(x);\\n result = 1;\\n if (xAux >= 0x100000000000000000000000000000000) {\\n xAux >>= 128;\\n result <<= 64;\\n }\\n if (xAux >= 0x10000000000000000) {\\n xAux >>= 64;\\n result <<= 32;\\n }\\n if (xAux >= 0x100000000) {\\n xAux >>= 32;\\n result <<= 16;\\n }\\n if (xAux >= 0x10000) {\\n xAux >>= 16;\\n result <<= 8;\\n }\\n if (xAux >= 0x100) {\\n xAux >>= 8;\\n result <<= 4;\\n }\\n if (xAux >= 0x10) {\\n xAux >>= 4;\\n result <<= 2;\\n }\\n if (xAux >= 0x8) {\\n result <<= 1;\\n }\\n\\n // The operations can never overflow because the result is max 2^127 when it enters this block.\\n unchecked {\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1; // Seven iterations should be enough\\n uint256 roundedDownResult = x / result;\\n return result >= roundedDownResult ? roundedDownResult : result;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x62cbabae4910e168e99b9c2c3e3b5c9c7ad5e7abd961dcc63b7ea3d83d8ea87e\",\"license\":\"Unlicense\"}},\"version\":1}", "bytecode": "0x60c060405234801561001057600080fd5b506040516147ad3803806147ad83398101604081905261002f9161008d565b8060405161003c90610080565b6001600160a01b039091168152602001604051809103906000f080158015610068573d6000803e3d6000fd5b506001600160a01b039081166080521660a0526100bd565b613b7e80610c2f83390190565b60006020828403121561009f57600080fd5b81516001600160a01b03811681146100b657600080fd5b9392505050565b60805160a051610b4e6100e1600039600061018b0152600060910152610b4e6000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80631a2a1a201461003b5780632d3fb8a314610077575b600080fd5b61004e6100493660046105b5565b61008a565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b61004e61008536600461077a565b6101e0565b60006100b57f000000000000000000000000000000000000000000000000000000000000000061035a565b6040517fec818c8900000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff82169063ec818c899061011c908e908e908e908e908e908e908e908e908e908e90600401610870565b600060405180830381600087803b15801561013657600080fd5b505af115801561014a573d6000803e3d6000fd5b505050508073ffffffffffffffffffffffffffffffffffffffff167f9d8d9335be0008f50a6547966dd6a854fd9df1f0be7838b8a445b562513627448c8c8c7f00000000000000000000000000000000000000000000000000000000000000008d8d8d8d8d8d8d336040516101ca9c9b9a999897969594939291906108fa565b60405180910390a29a9950505050505050505050565b6040517fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003360601b16602082015243603482015260009030908290605401604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815282825280516020909101206001808452838301909252925060609190816020015b60408051808201909152600081526060602082015281526020019060019003908161026a57905050905060405180604001604052808381526020018e815250816000815181106102bc576102bc6109c6565b60200260200101819052508b73ffffffffffffffffffffffffffffffffffffffff1663f2da44b68f85846040518463ffffffff1660e01b8152600401610304939291906109f5565b600060405180830381600087803b15801561031e57600080fd5b505af1158015610332573d6000803e3d6000fd5b505050506103488e84848e8e8e8e8e8e8e61008a565b9e9d5050505050505050505050505050565b60006040517f3d602d80600a3d3981f3363d3d373d3d3d363d7300000000000000000000000081528260601b60148201527f5af43d82803e903d91602b57fd5bf3000000000000000000000000000000000060288201526037816000f091505073ffffffffffffffffffffffffffffffffffffffff811661043b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f455243313136373a20637265617465206661696c656400000000000000000000604482015260640160405180910390fd5b919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461046257600080fd5b50565b803561043b81610440565b8035801515811461043b57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160e0810167ffffffffffffffff811182821017156104d2576104d2610480565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561051f5761051f610480565b604052919050565b600082601f83011261053857600080fd5b813567ffffffffffffffff81111561055257610552610480565b61058360207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016104d8565b81815284602083860101111561059857600080fd5b816020850160208301376000918101602001919091529392505050565b6000806000806000806000806000806101408b8d0312156105d557600080fd5b8a35995060208b0135985060408b0135975060608b013596506105fa60808c01610465565b955061060860a08c01610470565b945060c08b013567ffffffffffffffff8082111561062557600080fd5b6106318e838f01610527565b955060e08d013591508082111561064757600080fd5b506106548d828e01610527565b9350506106646101008c01610470565b91506106736101208c01610465565b90509295989b9194979a5092959850565b600082601f83011261069557600080fd5b8135602067ffffffffffffffff8211156106b1576106b1610480565b6106bf818360051b016104d8565b82815260e092830285018201928282019190878511156106de57600080fd5b8387015b8581101561076d5781818a0312156106fa5760008081fd5b6107026104af565b61070b82610470565b8152610718868301610470565b81870152604082810135908201526060808301359082015260808083013561073f81610440565b9082015260a0828101359082015260c08083013561075c81610440565b9082015284529284019281016106e2565b5090979650505050505050565b6000806000806000806000806000806101408b8d03121561079a57600080fd5b8a35995060208b013567ffffffffffffffff808211156107b957600080fd5b6107c58e838f01610684565b9a506107d360408e01610465565b995060608d013598506107e860808e01610465565b97506107f660a08e01610470565b965060c08d013591508082111561062557600080fd5b6000815180845260005b8181101561083257602081850181015186830182015201610816565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60006101408c83528b60208401528a604084015289606084015273ffffffffffffffffffffffffffffffffffffffff808a16608085015288151560a08501528160c08501526108c18285018961080c565b915083820360e08501526108d5828861080c565b925085151561010085015280851661012085015250509b9a5050505050505050505050565b60006101808e83528d60208401528c604084015273ffffffffffffffffffffffffffffffffffffffff808d1660608501528b6080850152808b1660a08501525088151560c08401528060e08401526109548184018961080c565b9050828103610100840152610969818861080c565b91505084151561012083015261099861014083018573ffffffffffffffffffffffffffffffffffffffff169052565b73ffffffffffffffffffffffffffffffffffffffff83166101608301529d9c50505050505050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060608083018684526020868186015260408381870152828751808552608094508488019150848160051b890101848a0160005b83811015610b06578a83037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff800185528151805184528701518784018790528051878501819052908801906000908b8601905b80831015610af15783518051151583528b81015115158c8401528a8101518b8401528d8101518e8401528c81015173ffffffffffffffffffffffffffffffffffffffff9081168e85015260a0808301519085015260c0918201511690830152928a01926001929092019160e090910190610a7c565b50968901969450505090860190600101610a2a565b50909c9b50505050505050505050505056fea26469706673582212200ce553bd906a6acfb51f721c67147d428b61e4bb20e8c11fdbe007a2536e8b7364736f6c6343000810003360e06040523480156200001157600080fd5b5060405162003b7e38038062003b7e83398101604081905262000034916200012e565b806001600160a01b031663c41c2f246040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000073573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200009991906200012e565b620000a433620000c5565b6001600160a01b039081166080523360a05260016006551660c05262000155565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146200012b57600080fd5b50565b6000602082840312156200014157600080fd5b81516200014e8162000115565b9392505050565b60805160a05160c0516139d6620001a8600039600081816105910152818161086e0152611c330152600081816106630152611cc70152600081816107c00152818161096f0152610bd301526139d66000f3fe6080604052600436106101845760003560e01c8063715018a6116100d6578063ae16f56a1161007f578063c41c2f2411610059578063c41c2f24146107ae578063ec818c89146107e2578063f2fde38b1461080257600080fd5b8063ae16f56a14610759578063b96053df14610779578063c0048ca51461078e57600080fd5b80638da5cb5b116100b05780638da5cb5b146106ef57806393b7f1541461070d578063a4919eb11461072757600080fd5b8063715018a6146106a55780637e646549146106ba5780638293fee6146106dc57600080fd5b80633ce9830b1161013857806354ab58af1161011257806354ab58af1461063157806364d3ed271461065157806371277d571461068557600080fd5b80633ce9830b146105ef578063421a2fb5146106055780635380cf8f1461061b57600080fd5b80630e45f78e116101695780630e45f78e1461055f5780632bdfe0041461057f5780633c212b1c146105cb57600080fd5b806301ffc9a71461051557806309a6b7e51461054a57600080fd5b36610510576002600654036101e05760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b60026006819055600754600854600954925460009361022893929161eeee9047906012906001600160a01b03166102175732610822565b6002546001600160a01b0316610822565b9050806000036102385750610507565b600154156104d85760055460ff16156103775761037260015461eeee83601260038054610264906128dd565b80601f0160208091040260200160405190810160405280929190818152602001828054610290906128dd565b80156102dd5780601f106102b2576101008083540402835291602001916102dd565b820191906000526020600020905b8154815290600101906020018083116102c057829003601f168201915b5050505050600480546102ef906128dd565b80601f016020809104026020016040519081016040528092919081815260200182805461031b906128dd565b80156103685780601f1061033d57610100808354040283529160200191610368565b820191906000526020600020905b81548152906001019060200180831161034b57829003601f168201915b505050505061092d565b610505565b600154600254610372919061eeee9084906012906001600160a01b031661039e57326103ab565b6002546001600160a01b03165b6000600260149054906101000a900460ff16600380546103ca906128dd565b80601f01602080910402602001604051908101604052809291908181526020018280546103f6906128dd565b80156104435780601f1061041857610100808354040283529160200191610443565b820191906000526020600020905b81548152906001019060200180831161042657829003601f168201915b505050505060048054610455906128dd565b80601f0160208091040260200160405190810160405280929190818152602001828054610481906128dd565b80156104ce5780601f106104a3576101008083540402835291602001916104ce565b820191906000526020600020905b8154815290600101906020018083116104b157829003601f168201915b5050505050610b91565b600254610505906001600160a01b03166104f257326104ff565b6002546001600160a01b03165b82610e52565b505b60016006819055005b600080fd5b34801561052157600080fd5b50610535610530366004612930565b610f70565b60405190151581526020015b60405180910390f35b61055d6105583660046129e0565b610fcc565b005b34801561056b57600080fd5b5061055d61057a366004612bb4565b61135f565b34801561058b57600080fd5b506105b37f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610541565b3480156105d757600080fd5b506105e160095481565b604051908152602001610541565b3480156105fb57600080fd5b506105e160015481565b34801561061157600080fd5b506105e160075481565b34801561062757600080fd5b506105e160085481565b34801561063d57600080fd5b506002546105b3906001600160a01b031681565b34801561065d57600080fd5b506105b37f000000000000000000000000000000000000000000000000000000000000000081565b34801561069157600080fd5b5061055d6106a0366004612c5a565b6115c2565b3480156106b157600080fd5b5061055d611687565b3480156106c657600080fd5b506106cf6116ed565b6040516105419190612cd6565b61055d6106ea366004612ce9565b61177b565b3480156106fb57600080fd5b506000546001600160a01b03166105b3565b34801561071957600080fd5b506005546105359060ff1681565b34801561073357600080fd5b506002546105359074010000000000000000000000000000000000000000900460ff1681565b34801561076557600080fd5b5061055d610774366004612de9565b611ba9565b34801561078557600080fd5b506106cf611caf565b34801561079a57600080fd5b5061055d6107a9366004613031565b611cbc565b3480156107ba57600080fd5b506105b37f000000000000000000000000000000000000000000000000000000000000000081565b3480156107ee57600080fd5b5061055d6107fd3660046130eb565b611dcb565b34801561080e57600080fd5b5061055d61081d3660046131ba565b611df2565b6040517f69e11cc50000000000000000000000000000000000000000000000000000000081526004810188905260248101879052604481018690526000906108e6906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906369e11cc590606401600060405180830381865afa1580156108b5573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108dd91908101906131d7565b86868686611ed4565b604051338152909150869088908a907f2522c1d6a5eb94bdf38d0007aadcdd12c34a8b834b915ab71117e8c0a7e5df809060200160405180910390a4979650505050505050565b6040517f86202650000000000000000000000000000000000000000000000000000000008152600481018790526001600160a01b0386811660248301526000917f000000000000000000000000000000000000000000000000000000000000000090911690638620265090604401602060405180830381865afa1580156109b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109dc91906132e1565b90506001600160a01b038116610a1e576040517ffba10dd600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fb7bad1b10000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015285919083169063b7bad1b190602401602060405180830381865afa158015610a80573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aa491906132fe565b14610adb576040517fb972592400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03861661eeee14610b0157610b016001600160a01b038716828761220f565b60006001600160a01b03871661eeee14610b1c576000610b1e565b855b9050816001600160a01b0316630cf8e858828a898b89896040518763ffffffff1660e01b8152600401610b55959493929190613317565b6000604051808303818588803b158015610b6e57600080fd5b505af1158015610b82573d6000803e3d6000fd5b50505050505050505050505050565b6040517f86202650000000000000000000000000000000000000000000000000000000008152600481018a90526001600160a01b0389811660248301526000917f000000000000000000000000000000000000000000000000000000000000000090911690638620265090604401602060405180830381865afa158015610c1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c4091906132e1565b90506001600160a01b038116610c82576040517ffba10dd600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fb7bad1b10000000000000000000000000000000000000000000000000000000081526001600160a01b038a8116600483015288919083169063b7bad1b190602401602060405180830381865afa158015610ce4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d0891906132fe565b14610d3f576040517fb972592400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03891661eeee14610d6557610d656001600160a01b038a16828a61220f565b60006001600160a01b038a1661eeee14610d80576000610d82565b885b9050816001600160a01b0316631ebc263f828d8c8e60006001600160a01b03168d6001600160a01b031603610dd8576002546001600160a01b0316610dc75732610dda565b6002546001600160a01b0316610dda565b8c5b8c8c8c8c6040518a63ffffffff1660e01b8152600401610e01989796959493929190613363565b60206040518083038185885af1158015610e1f573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610e4491906132fe565b505050505050505050505050565b80471015610ea25760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e636500000060448201526064016101d7565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114610eef576040519150601f19603f3d011682016040523d82523d6000602084013e610ef4565b606091505b5050905080610f6b5760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d6179206861766520726576657274656400000000000060648201526084016101d7565b505050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f35d42f96000000000000000000000000000000000000000000000000000000001480610fc65750610fc6826123bd565b92915050565b60026006540361101e5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016101d7565b60026006556001600160a01b03871661eeee1461119d57341561106d576040517fbcfd35be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038916906370a0823190602401602060405180830381865afa1580156110cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110f191906132fe565b90506111086001600160a01b03891633308a612454565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015281906001600160a01b038a16906370a0823190602401602060405180830381865afa158015611167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061118b91906132fe565b61119591906133cd565b9650506111a5565b349550601294505b6007546008546009546002546000936111d593909290918c908c908c906001600160a01b03166102175732610822565b905080156112e157881561125f5761125a8989838989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8d018190048102820181019092528b815292508b91508a908190840183828082843760009201919091525061092d92505050565b6112e1565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11126001600160a01b038916016112a95760025461125a906001600160a01b03166104f257326104ff565b6002546112e1906001600160a01b03166112c357326112d0565b6002546001600160a01b03165b6001600160a01b038a1690836124a5565b60025489907f5f17f788c7f8d3fd7332fb1e6c42a67accbf9bb129ac8e4389fe693b506369f1906001600160a01b031661131b5732611328565b6002546001600160a01b03165b8a8a8a868b8b8b8b336040516113479a99989796959493929190613432565b60405180910390a25050600160065550505050505050565b6000546001600160a01b031633146113b95760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016101d7565b60015486146113c85760018690555b6002546001600160a01b0386811691161461141157600280547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0387161790555b600260149054906101000a900460ff1615158415151461146f57600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000861515021790555b60036040516020016114819190613532565b60405160208183030381529060405280519060200120836040516020016114a8919061353e565b60405160208183030381529060405280519060200120146114d15760036114cf84826135a8565b505b60046040516020016114e39190613532565b604051602081830303815290604052805190602001208260405160200161150a919061353e565b604051602081830303815290604052805190602001201461153357600461153183826135a8565b505b60055460ff1615158115151461157057600580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168215151790555b846001600160a01b0316867f36b1c5cef608e320317b9ee5155756634c65fe7055b424ce57e2f6c59eec794786868686336040516115b29594939291906136a4565b60405180910390a3505050505050565b6000546001600160a01b0316331461161c5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016101d7565b600754831461162b5760078390555b600854821461163a5760088290555b60095481146116495760098190555b6040513381528190839085907f5ef5a6931855992f84842284a6bba50d74bfe8654238b4d6325427473a90f3a59060200160405180910390a4505050565b6000546001600160a01b031633146116e15760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016101d7565b6116eb60006124ee565b565b600480546116fa906128dd565b80601f0160208091040260200160405190810160405280929190818152602001828054611726906128dd565b80156117735780601f1061174857610100808354040283529160200191611773565b820191906000526020600020905b81548152906001019060200180831161175657829003601f168201915b505050505081565b6002600654036117cd5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016101d7565b60026006556001600160a01b038a1661eeee1461194c57341561181c576040517fbcfd35be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038c16906370a0823190602401602060405180830381865afa15801561187c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118a091906132fe565b90506118b76001600160a01b038c1633308d612454565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015281906001600160a01b038d16906370a0823190602401602060405180830381865afa158015611916573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061193a91906132fe565b61194491906133cd565b995050611954565b349850601297505b60075460085460095460025460009361198493909290918f908f908f906001600160a01b03166102175732610822565b90508015611b12578b15611a5857611a538c8c838c6001600160a01b038d166119ce576002546001600160a01b03166119bd57326119d0565b6002546001600160a01b03166119d0565b8c5b8c8c8c8c8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610b9192505050565b611b12565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11126001600160a01b038c1601611ac757611a536001600160a01b038916611ac0576002546001600160a01b0316611aaf57326104ff565b6002546001600160a01b03166104ff565b8882610e52565b611b126001600160a01b038916611aff576002546001600160a01b0316611aee5732611b01565b6002546001600160a01b0316611b01565b885b6001600160a01b038d1690836124a5565b8b7f72877920bfc936c0f18c54961abe3105d7d2990103eaa013cd8420fecacb0b606001600160a01b038a16611b69576002546001600160a01b0316611b585732611b6b565b6002546001600160a01b0316611b6b565b895b8d8d8d868d8d8d8d8d8d33604051611b8e9c9b9a999897969594939291906136f4565b60405180910390a25050600160065550505050505050505050565b6000546001600160a01b03163314611c035760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016101d7565b6040517ff2da44b60000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063f2da44b690611c6c90879087908690600401613774565b600060405180830381600087803b158015611c8657600080fd5b505af1158015611c9a573d6000803e3d6000fd5b50505050611ca98484846115c2565b50505050565b600380546116fa906128dd565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611d1e576040517f439a74c900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018790556002805486151574010000000000000000000000000000000000000000027fffffffffffffffffffffff0000000000000000000000000000000000000000009091166001600160a01b038916171790556003611d7f85826135a8565b506004611d8c84826135a8565b50600580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016831515179055611dc2816124ee565b50505050505050565b611dda87878787878787611cbc565b50505060079690965550505060089190915560095550565b6000546001600160a01b03163314611e4c5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016101d7565b6001600160a01b038116611ec85760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016101d7565b611ed1816124ee565b50565b8260005b8651811015612205576000878281518110611ef557611ef561389d565b602002602001015190506000611f14878360400151633b9aca00612556565b905080156121be5760c08201516001600160a01b0316156120ae576040805160c0810182526001600160a01b038a168082526020820184905291810188905260015460608201526000608082015260a081018490529061eeee14611f8c5760c0830151611f8c906001600160a01b038b16908461220f565b60006001600160a01b038a1661eeee14611fa7576000611fa9565b825b60c080860151604080517f9d740bfa00000000000000000000000000000000000000000000000000000000815286516001600160a01b03908116600483015260208089015160248401528389015160448401526060808a015160648501526080808b0151608486015260a0808c01518051151560a488015293840151151560c48701529583015160e486015290820151610104850152810151821661012484015292830151610144830152919093015181166101648401529293509190911690639d740bfa908390610184016000604051808303818588803b15801561208e57600080fd5b505af11580156120a2573d6000803e3d6000fd5b505050505050506121b1565b606082015115612128578160200151156120df576120da826060015189838960038054610264906128dd565b6121b1565b6120da826060015189838960006001600160a01b031687608001516001600160a01b03160361210e5789612114565b86608001515b60008860000151600380546103ca906128dd565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11126001600160a01b0389160161217f5760808201516120da906001600160a01b031661217457856104ff565b826080015182610e52565b60808201516121b1906001600160a01b031661219b57856112d0565b82608001516001600160a01b038a1690836124a5565b6121bb81856133cd565b93505b7ff44ffe151def7bd57d653ffdd625b5cfff3e6992ad5b8eb1f021cdaca6599544828287336040516121f394939291906138cc565b60405180910390a15050600101611ed8565b5095945050505050565b8015806122a257506040517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa15801561227c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122a091906132fe565b155b6123145760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e63650000000000000000000060648201526084016101d7565b6040516001600160a01b038316602482015260448101829052610f6b9084907f095ea7b300000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612660565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7ddb72fc000000000000000000000000000000000000000000000000000000001480610fc657507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831614610fc6565b6040516001600160a01b0380851660248301528316604482015260648101829052611ca99085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401612359565b6040516001600160a01b038316602482015260448101829052610f6b9084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401612359565b600080546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600080807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff858709858702925082811083820303915050806000036125ae578382816125a4576125a4613954565b0492505050612659565b8381106125f1576040517f773cc18c00000000000000000000000000000000000000000000000000000000815260048101829052602481018590526044016101d7565b600084868809851960019081018716968790049682860381900495909211909303600082900391909104909201919091029190911760038402600290811880860282030280860282030280860282030280860282030280860282030280860290910302029150505b9392505050565b60006126b5826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166127459092919063ffffffff16565b805190915015610f6b57808060200190518101906126d39190613983565b610f6b5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016101d7565b6060612754848460008561275c565b949350505050565b6060824710156127d45760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016101d7565b6001600160a01b0385163b61282b5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016101d7565b600080866001600160a01b03168587604051612847919061353e565b60006040518083038185875af1925050503d8060008114612884576040519150601f19603f3d011682016040523d82523d6000602084013e612889565b606091505b50915091506128998282866128a4565b979650505050505050565b606083156128b3575081612659565b8251156128c35782518084602001fd5b8160405162461bcd60e51b81526004016101d79190612cd6565b600181811c908216806128f157607f821691505b60208210810361292a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60006020828403121561294257600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461265957600080fd5b6001600160a01b0381168114611ed157600080fd5b803561299281612972565b919050565b60008083601f8401126129a957600080fd5b50813567ffffffffffffffff8111156129c157600080fd5b6020830191508360208285010111156129d957600080fd5b9250929050565b60008060008060008060008060c0898b0312156129fc57600080fd5b883597506020890135612a0e81612972565b96506040890135955060608901359450608089013567ffffffffffffffff80821115612a3957600080fd5b612a458c838d01612997565b909650945060a08b0135915080821115612a5e57600080fd5b50612a6b8b828c01612997565b999c989b5096995094979396929594505050565b8015158114611ed157600080fd5b803561299281612a7f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715612aea57612aea612a98565b60405290565b60405160e0810167ffffffffffffffff81118282101715612aea57612aea612a98565b604051601f8201601f1916810167ffffffffffffffff81118282101715612b3c57612b3c612a98565b604052919050565b600082601f830112612b5557600080fd5b813567ffffffffffffffff811115612b6f57612b6f612a98565b612b826020601f19601f84011601612b13565b818152846020838601011115612b9757600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060c08789031215612bcd57600080fd5b863595506020870135612bdf81612972565b94506040870135612bef81612a7f565b9350606087013567ffffffffffffffff80821115612c0c57600080fd5b612c188a838b01612b44565b94506080890135915080821115612c2e57600080fd5b50612c3b89828a01612b44565b92505060a0870135612c4c81612a7f565b809150509295509295509295565b600080600060608486031215612c6f57600080fd5b505081359360208301359350604090920135919050565b60005b83811015612ca1578181015183820152602001612c89565b50506000910152565b60008151808452612cc2816020860160208601612c86565b601f01601f19169290920160200192915050565b6020815260006126596020830184612caa565b60008060008060008060008060008060006101208c8e031215612d0b57600080fd5b8b359a50612d1c60208d0135612972565b60208c0135995060408c0135985060608c01359750612d3e60808d0135612972565b60808c0135965060a08c01359550612d5860c08d01612a8d565b945067ffffffffffffffff8060e08e01351115612d7457600080fd5b612d848e60e08f01358f01612997565b90955093506101008d0135811015612d9b57600080fd5b50612dad8d6101008e01358e01612997565b81935080925050509295989b509295989b9093969950565b600067ffffffffffffffff821115612ddf57612ddf612a98565b5060051b60200190565b60008060008060808587031215612dff57600080fd5b84359350602085013592506040850135915067ffffffffffffffff60608601351115612e2a57600080fd5b85601f606087013587010112612e3f57600080fd5b612e57612e526060870135870135612dc5565b612b13565b6060860135860180358083526020808401939260059290921b90910101881015612e8057600080fd5b602060608801358801015b60608801358801803560051b016020018110156130245767ffffffffffffffff81351115612eb857600080fd5b6040601f19823560608b01358b01018b03011215612ed557600080fd5b612edd612ac7565b606089013589018235016020810135825267ffffffffffffffff6040909101351115612f0857600080fd5b60608901358901823501604081013501603f81018b13612f2757600080fd5b612f37612e526020830135612dc5565b602082810135808352908201919060e00283016040018d1015612f5957600080fd5b604083015b604060e060208601350285010181101561300b5760e0818f031215612f8257600080fd5b612f8a612af0565b612f948235612a7f565b81358152612fa56020830135612a7f565b602082013560208201526040820135604082015260608201356060820152612fd06080830135612972565b6080820135608082015260a082013560a0820152612ff160c0830135612972565b60c08281013590820152835260209092019160e001612f5e565b5060208481019190915292865250509283019201612e8b565b5094979396509194505050565b600080600080600080600060e0888a03121561304c57600080fd5b87359650602088013561305e81612972565b9550604088013561306e81612a7f565b9450606088013567ffffffffffffffff8082111561308b57600080fd5b6130978b838c01612b44565b955060808a01359150808211156130ad57600080fd5b506130ba8a828b01612b44565b93505060a08801356130cb81612a7f565b915060c08801356130db81612972565b8091505092959891949750929550565b6000806000806000806000806000806101408b8d03121561310b57600080fd5b8a35995060208b0135985060408b0135975060608b0135965061313060808c01612987565b955061313e60a08c01612a8d565b945060c08b013567ffffffffffffffff8082111561315b57600080fd5b6131678e838f01612b44565b955060e08d013591508082111561317d57600080fd5b5061318a8d828e01612b44565b93505061319a6101008c01612a8d565b91506131a96101208c01612987565b90509295989b9194979a5092959850565b6000602082840312156131cc57600080fd5b813561265981612972565b600060208083850312156131ea57600080fd5b825167ffffffffffffffff81111561320157600080fd5b8301601f8101851361321257600080fd5b8051613220612e5282612dc5565b81815260e0918202830184019184820191908884111561323f57600080fd5b938501935b838510156132d55780858a03121561325c5760008081fd5b613264612af0565b855161326f81612a7f565b81528587015161327e81612a7f565b8188015260408681015190820152606080870151908201526080808701516132a581612972565b9082015260a0868101519082015260c0808701516132c281612972565b9082015283529384019391850191613244565b50979650505050505050565b6000602082840312156132f357600080fd5b815161265981612972565b60006020828403121561331057600080fd5b5051919050565b8581528460208201526001600160a01b038416604082015260a06060820152600061334560a0830185612caa565b82810360808401526133578185612caa565b98975050505050505050565b60006101008a83528960208401526001600160a01b03808a16604085015280891660608501525086608084015285151560a08401528060c08401526133aa81840186612caa565b905082810360e08401526133be8185612caa565b9b9a5050505050505050505050565b81810381811115610fc6577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818352818160208501375060006020828401015260006020601f19601f840116840101905092915050565b60006101006001600160a01b03808e168452808d1660208501528b60408501528a60608501528960808501528160a0850152613471828501898b613407565b915083820360c0850152613486828789613407565b925080851660e085015250509b9a5050505050505050505050565b600081546134ae816128dd565b600182811680156134c657600181146134f957613528565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0084168752821515830287019450613528565b8560005260208060002060005b8581101561351f5781548a820152908401908201613506565b50505082870194505b5050505092915050565b600061265982846134a1565b60008251613550818460208701612c86565b9190910192915050565b601f821115610f6b57600081815260208120601f850160051c810160208610156135815750805b601f850160051c820191505b818110156135a05782815560010161358d565b505050505050565b815167ffffffffffffffff8111156135c2576135c2612a98565b6135d6816135d084546128dd565b8461355a565b602080601f83116001811461362957600084156135f35750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556135a0565b600085815260208120601f198616915b8281101561365857888601518255948401946001909101908401613639565b508582101561369457878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b851515815260a0602082015260006136bf60a0830187612caa565b82810360408401526136d18187612caa565b941515606084015250506001600160a01b03919091166080909101529392505050565b60006001600160a01b03808f168352808e1660208401528c60408401528b60608401528a60808401528960a084015288151560c084015261014060e08401526137426101408401888a613407565b838103610100850152613756818789613407565b925050808416610120840152509d9c50505050505050505050505050565b60006060808301868452602086818601526040838187015282875180855260808801915060808160051b89010194508389016000805b8381101561388b578a88037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff800185528251805189528701518789018790528051878a018190529088019083908b8b01905b8083101561387657613860828551805115158252602081015115156020830152604081015160408301526060810151606083015260808101516001600160a01b03808216608085015260a083015160a08501528060c08401511660c085015250505050565b60e0820191508a840193506001830192506137fb565b509950505093860193918601916001016137aa565b50959c9b505050505050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b610140810161392d8287805115158252602081015115156020830152604081015160408301526060810151606083015260808101516001600160a01b03808216608085015260a083015160a08501528060c08401511660c085015250505050565b60e08201949094526001600160a01b03928316610100820152911661012090910152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006020828403121561399557600080fd5b815161265981612a7f56fea26469706673582212208c9af2b4648981cff6fb1cbd7aa3f4bb5ce48d5a26e15246a6f617cd311d398764736f6c63430008100033", "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80631a2a1a201461003b5780632d3fb8a314610077575b600080fd5b61004e6100493660046105b5565b61008a565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b61004e61008536600461077a565b6101e0565b60006100b57f000000000000000000000000000000000000000000000000000000000000000061035a565b6040517fec818c8900000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff82169063ec818c899061011c908e908e908e908e908e908e908e908e908e908e90600401610870565b600060405180830381600087803b15801561013657600080fd5b505af115801561014a573d6000803e3d6000fd5b505050508073ffffffffffffffffffffffffffffffffffffffff167f9d8d9335be0008f50a6547966dd6a854fd9df1f0be7838b8a445b562513627448c8c8c7f00000000000000000000000000000000000000000000000000000000000000008d8d8d8d8d8d8d336040516101ca9c9b9a999897969594939291906108fa565b60405180910390a29a9950505050505050505050565b6040517fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003360601b16602082015243603482015260009030908290605401604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815282825280516020909101206001808452838301909252925060609190816020015b60408051808201909152600081526060602082015281526020019060019003908161026a57905050905060405180604001604052808381526020018e815250816000815181106102bc576102bc6109c6565b60200260200101819052508b73ffffffffffffffffffffffffffffffffffffffff1663f2da44b68f85846040518463ffffffff1660e01b8152600401610304939291906109f5565b600060405180830381600087803b15801561031e57600080fd5b505af1158015610332573d6000803e3d6000fd5b505050506103488e84848e8e8e8e8e8e8e61008a565b9e9d5050505050505050505050505050565b60006040517f3d602d80600a3d3981f3363d3d373d3d3d363d7300000000000000000000000081528260601b60148201527f5af43d82803e903d91602b57fd5bf3000000000000000000000000000000000060288201526037816000f091505073ffffffffffffffffffffffffffffffffffffffff811661043b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f455243313136373a20637265617465206661696c656400000000000000000000604482015260640160405180910390fd5b919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461046257600080fd5b50565b803561043b81610440565b8035801515811461043b57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160e0810167ffffffffffffffff811182821017156104d2576104d2610480565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561051f5761051f610480565b604052919050565b600082601f83011261053857600080fd5b813567ffffffffffffffff81111561055257610552610480565b61058360207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016104d8565b81815284602083860101111561059857600080fd5b816020850160208301376000918101602001919091529392505050565b6000806000806000806000806000806101408b8d0312156105d557600080fd5b8a35995060208b0135985060408b0135975060608b013596506105fa60808c01610465565b955061060860a08c01610470565b945060c08b013567ffffffffffffffff8082111561062557600080fd5b6106318e838f01610527565b955060e08d013591508082111561064757600080fd5b506106548d828e01610527565b9350506106646101008c01610470565b91506106736101208c01610465565b90509295989b9194979a5092959850565b600082601f83011261069557600080fd5b8135602067ffffffffffffffff8211156106b1576106b1610480565b6106bf818360051b016104d8565b82815260e092830285018201928282019190878511156106de57600080fd5b8387015b8581101561076d5781818a0312156106fa5760008081fd5b6107026104af565b61070b82610470565b8152610718868301610470565b81870152604082810135908201526060808301359082015260808083013561073f81610440565b9082015260a0828101359082015260c08083013561075c81610440565b9082015284529284019281016106e2565b5090979650505050505050565b6000806000806000806000806000806101408b8d03121561079a57600080fd5b8a35995060208b013567ffffffffffffffff808211156107b957600080fd5b6107c58e838f01610684565b9a506107d360408e01610465565b995060608d013598506107e860808e01610465565b97506107f660a08e01610470565b965060c08d013591508082111561062557600080fd5b6000815180845260005b8181101561083257602081850181015186830182015201610816565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60006101408c83528b60208401528a604084015289606084015273ffffffffffffffffffffffffffffffffffffffff808a16608085015288151560a08501528160c08501526108c18285018961080c565b915083820360e08501526108d5828861080c565b925085151561010085015280851661012085015250509b9a5050505050505050505050565b60006101808e83528d60208401528c604084015273ffffffffffffffffffffffffffffffffffffffff808d1660608501528b6080850152808b1660a08501525088151560c08401528060e08401526109548184018961080c565b9050828103610100840152610969818861080c565b91505084151561012083015261099861014083018573ffffffffffffffffffffffffffffffffffffffff169052565b73ffffffffffffffffffffffffffffffffffffffff83166101608301529d9c50505050505050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060608083018684526020868186015260408381870152828751808552608094508488019150848160051b890101848a0160005b83811015610b06578a83037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff800185528151805184528701518784018790528051878501819052908801906000908b8601905b80831015610af15783518051151583528b81015115158c8401528a8101518b8401528d8101518e8401528c81015173ffffffffffffffffffffffffffffffffffffffff9081168e85015260a0808301519085015260c0918201511690830152928a01926001929092019160e090910190610a7c565b50968901969450505090860190600101610a2a565b50909c9b50505050505050505050505056fea26469706673582212200ce553bd906a6acfb51f721c67147d428b61e4bb20e8c11fdbe007a2536e8b7364736f6c63430008100033", "devdoc": { - "details": "Adheres to - IJBETHERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.", + "details": "Adheres to - IJBGasTokenERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.", "kind": "dev", "methods": { "deploySplitsPayer(uint256,uint256,uint256,uint256,address,bool,string,bytes,bool,address)": { diff --git a/deployments/goerli/JBETHPaymentTerminal.json b/deployments/goerli/JBETHPaymentTerminal.json index a92e88604..9dd1ce9ea 100644 --- a/deployments/goerli/JBETHPaymentTerminal.json +++ b/deployments/goerli/JBETHPaymentTerminal.json @@ -1717,7 +1717,7 @@ ], "numDeployments": 1, "solcInputHash": "7f5ae5369c2a685c882e67f75315b841", - "metadata": "{\"compiler\":{\"version\":\"0.8.16+commit.07a7930e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_baseWeightCurrency\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBOperatorStore\",\"name\":\"_operatorStore\",\"type\":\"address\"},{\"internalType\":\"contract IJBProjects\",\"name\":\"_projects\",\"type\":\"address\"},{\"internalType\":\"contract IJBDirectory\",\"name\":\"_directory\",\"type\":\"address\"},{\"internalType\":\"contract IJBSplitsStore\",\"name\":\"_splitsStore\",\"type\":\"address\"},{\"internalType\":\"contract IJBPrices\",\"name\":\"_prices\",\"type\":\"address\"},{\"internalType\":\"contract IJBSingleTokenPaymentTerminalStore\",\"name\":\"_store\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"FEE_TOO_HIGH\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INADEQUATE_DISTRIBUTION_AMOUNT\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INADEQUATE_RECLAIM_AMOUNT\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INADEQUATE_TOKEN_COUNT\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NO_MSG_VALUE_ALLOWED\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PAY_TO_ZERO_ADDRESS\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"prod1\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"denominator\",\"type\":\"uint256\"}],\"name\":\"PRBMath__MulDivOverflow\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PROJECT_TERMINAL_MISMATCH\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"REDEEM_TO_ZERO_ADDRESS\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TERMINAL_IN_SPLIT_ZERO_ADDRESS\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TERMINAL_TOKENS_INCOMPATIBLE\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UNAUTHORIZED\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"refundedFees\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AddToBalance\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IJBPayDelegate\",\"name\":\"delegate\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"currentFundingCycleConfiguration\",\"type\":\"uint256\"},{\"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\"},{\"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\":\"forwardedAmount\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"projectTokenCount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"preferClaimedTokens\",\"type\":\"bool\"},{\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"struct JBDidPayData\",\"name\":\"data\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"delegatedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"DelegateDidPay\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IJBRedemptionDelegate\",\"name\":\"delegate\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"currentFundingCycleConfiguration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"projectTokenCount\",\"type\":\"uint256\"},{\"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\":\"reclaimedAmount\",\"type\":\"tuple\"},{\"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\":\"forwardedAmount\",\"type\":\"tuple\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"struct JBDidRedeemData\",\"name\":\"data\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"delegatedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"DelegateDidRedeem\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleConfiguration\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleNumber\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"distributedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"beneficiaryDistributionAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"DistributePayouts\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"domain\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"group\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"preferClaimed\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"preferAddToBalance\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"percent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"lockedUntil\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBSplitAllocator\",\"name\":\"allocator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"struct JBSplit\",\"name\":\"split\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"DistributeToPayoutSplit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"feeDiscount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"HoldFee\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"contract IJBPaymentTerminal\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Migrate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleConfiguration\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleNumber\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"beneficiaryTokenCount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Pay\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"wasHeld\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"ProcessFee\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleConfiguration\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleNumber\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenCount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"reclaimedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"RedeemTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"refundedFees\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"leftoverAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"RefundHeldFees\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"SetFee\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IJBFeeGauge\",\"name\":\"feeGauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"SetFeeGauge\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"addrs\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"flag\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"SetFeelessAddress\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleConfiguration\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleNumber\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"distributedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"netDistributedamount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"UseAllowance\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"}],\"name\":\"acceptsToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"addToBalanceOf\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"baseWeightCurrency\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currency\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"currencyForToken\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"}],\"name\":\"currentEthOverflowOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"decimalsForToken\",\"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\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_currency\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_minReturnedTokens\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"}],\"name\":\"distributePayoutsOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"netLeftoverDistributionAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"feeGauge\",\"outputs\":[{\"internalType\":\"contract IJBFeeGauge\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"}],\"name\":\"heldFeesOf\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"fee\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"feeDiscount\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"internalType\":\"struct JBFee[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isFeelessAddress\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBPaymentTerminal\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"migrate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"operatorStore\",\"outputs\":[{\"internalType\":\"contract IJBOperatorStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_minReturnedTokens\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"_preferClaimedTokens\",\"type\":\"bool\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"pay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"payoutSplitsGroup\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"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\"}],\"name\":\"processFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"projects\",\"outputs\":[{\"internalType\":\"contract IJBProjects\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_holder\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_tokenCount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_minReturnedTokens\",\"type\":\"uint256\"},{\"internalType\":\"address payable\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"redeemTokensOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"reclaimAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_fee\",\"type\":\"uint256\"}],\"name\":\"setFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IJBFeeGauge\",\"name\":\"_feeGauge\",\"type\":\"address\"}],\"name\":\"setFeeGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_flag\",\"type\":\"bool\"}],\"name\":\"setFeelessAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"splitsStore\",\"outputs\":[{\"internalType\":\"contract IJBSplitsStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"store\",\"outputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminalStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_currency\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_minReturnedTokens\",\"type\":\"uint256\"},{\"internalType\":\"address payable\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"}],\"name\":\"useAllowanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"netDistributedAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Inherits from - JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\",\"kind\":\"dev\",\"methods\":{\"acceptsToken(address,uint256)\":{\"params\":{\"_projectId\":\"The project ID to check for token acceptance.\",\"_token\":\"The token to check if this terminal accepts or not.\"},\"returns\":{\"_0\":\"The flag.\"}},\"addToBalanceOf(uint256,uint256,address,string,bytes)\":{\"params\":{\"_amount\":\"The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\",\"_memo\":\"A memo to pass along to the emitted event.\",\"_metadata\":\"Extra data to pass along to the emitted event.\",\"_projectId\":\"The ID of the project to which the funds received belong.\",\"_token\":\"The token being paid. This terminal ignores this property since it only manages one currency. \"}},\"constructor\":{\"params\":{\"_baseWeightCurrency\":\"The currency to base token issuance on.\",\"_directory\":\"A contract storing directories of terminals and controllers for each project.\",\"_operatorStore\":\"A contract storing operator assignments.\",\"_owner\":\"The address that will own this contract.\",\"_prices\":\"A contract that exposes price feeds.\",\"_projects\":\"A contract which mints ERC-721's that represent project ownership and transfers.\",\"_splitsStore\":\"A contract that stores splits for each project.\",\"_store\":\"A contract that stores the terminal's data.\"}},\"currencyForToken(address)\":{\"params\":{\"_token\":\"The token to check for the currency of.\"},\"returns\":{\"_0\":\"The currency index.\"}},\"currentEthOverflowOf(uint256)\":{\"details\":\"The current overflow is represented as a fixed point number with 18 decimals.\",\"params\":{\"_projectId\":\"The ID of the project to get overflow for.\"},\"returns\":{\"_0\":\"The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\"}},\"decimalsForToken(address)\":{\"params\":{\"_token\":\"The token to check for the decimals of.\"},\"returns\":{\"_0\":\"The number of decimals for the token.\"}},\"distributePayoutsOf(uint256,uint256,uint256,address,uint256,string)\":{\"details\":\"Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\",\"params\":{\"_amount\":\"The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\",\"_currency\":\"The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\",\"_memo\":\"A memo to pass along to the emitted event.\",\"_minReturnedTokens\":\"The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\",\"_projectId\":\"The ID of the project having its payouts distributed.\",\"_token\":\"The token being distributed. This terminal ignores this property since it only manages one token. \"},\"returns\":{\"netLeftoverDistributionAmount\":\"The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\"}},\"heldFeesOf(uint256)\":{\"params\":{\"_projectId\":\"The ID of the project for which fees are being held.\"},\"returns\":{\"_0\":\"An array of fees that are being held.\"}},\"migrate(uint256,address)\":{\"details\":\"Only a project's owner or a designated operator can migrate it.\",\"params\":{\"_projectId\":\"The ID of the project being migrated.\",\"_to\":\"The terminal contract that will gain the project's funds.\"},\"returns\":{\"balance\":\"The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pay(uint256,uint256,address,address,uint256,bool,string,bytes)\":{\"params\":{\"_amount\":\"The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\",\"_beneficiary\":\"The address to mint tokens for and pass along to the funding cycle's data source and delegate.\",\"_memo\":\"A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\",\"_metadata\":\"Bytes to send along to the data source, delegate, and emitted event, if provided.\",\"_minReturnedTokens\":\"The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\",\"_preferClaimedTokens\":\"A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\",\"_projectId\":\"The ID of the project being paid.\",\"_token\":\"The token being paid. This terminal ignores this property since it only manages one token. \"},\"returns\":{\"_0\":\"The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\"}},\"processFees(uint256)\":{\"details\":\"Only a project owner, an operator, or the contract's owner can process held fees.\",\"params\":{\"_projectId\":\"The ID of the project whos held fees should be processed.\"}},\"redeemTokensOf(address,uint256,uint256,address,uint256,address,string,bytes)\":{\"details\":\"Only a token holder or a designated operator can redeem its tokens.\",\"params\":{\"_beneficiary\":\"The address to send the terminal tokens to.\",\"_holder\":\"The account to redeem tokens for.\",\"_memo\":\"A memo to pass along to the emitted event.\",\"_metadata\":\"Bytes to send along to the data source, delegate, and emitted event, if provided.\",\"_minReturnedTokens\":\"The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\",\"_projectId\":\"The ID of the project to which the tokens being redeemed belong.\",\"_token\":\"The token being reclaimed. This terminal ignores this property since it only manages one token. \",\"_tokenCount\":\"The number of project tokens to redeem, as a fixed point number with 18 decimals.\"},\"returns\":{\"reclaimAmount\":\"The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"setFee(uint256)\":{\"details\":\"Only the owner of this contract can change the fee.\",\"params\":{\"_fee\":\"The new fee, out of MAX_FEE.\"}},\"setFeeGauge(address)\":{\"details\":\"Only the owner of this contract can change the fee gauge.\",\"params\":{\"_feeGauge\":\"The new fee gauge.\"}},\"setFeelessAddress(address,bool)\":{\"details\":\"Only the owner of this contract can set addresses as feeless.\",\"params\":{\"_address\":\"The address that can be paid towards while still bypassing fees.\",\"_flag\":\"A flag indicating whether the terminal should be feeless or not.\"}},\"supportsInterface(bytes4)\":{\"details\":\" See {IERC165-supportsInterface}.\",\"params\":{\"_interfaceId\":\"The ID of the interface to check for adherance to.\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"useAllowanceOf(uint256,uint256,uint256,address,uint256,address,string)\":{\"details\":\"Only a project's owner or a designated operator can use its allowance.Incurs the protocol fee.\",\"params\":{\"_amount\":\"The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\",\"_beneficiary\":\"The address to send the funds to.\",\"_currency\":\"The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\",\"_memo\":\"A memo to pass along to the emitted event.\",\"_minReturnedTokens\":\"The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\",\"_projectId\":\"The ID of the project to use the allowance of.\",\"_token\":\"The token being distributed. This terminal ignores this property since it only manages one token. \"},\"returns\":{\"netDistributedAmount\":\"The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\"}}},\"version\":1},\"userdoc\":{\"errors\":{\"PRBMath__MulDivOverflow(uint256,uint256)\":[{\"notice\":\"Emitted when the result overflows uint256.\"}]},\"kind\":\"user\",\"methods\":{\"acceptsToken(address,uint256)\":{\"notice\":\"A flag indicating if this terminal accepts the specified token.\"},\"addToBalanceOf(uint256,uint256,address,string,bytes)\":{\"notice\":\"Receives funds belonging to the specified project.\"},\"baseWeightCurrency()\":{\"notice\":\"The currency to base token issuance on.\"},\"currency()\":{\"notice\":\"The currency to use when resolving price feeds for this terminal.\"},\"currencyForToken(address)\":{\"notice\":\"The currency that should be used for the specified token.\"},\"currentEthOverflowOf(uint256)\":{\"notice\":\"Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\"},\"decimals()\":{\"notice\":\"The number of decimals the token fixed point amounts are expected to have.\"},\"decimalsForToken(address)\":{\"notice\":\"The decimals that should be used in fixed number accounting for the specified token.\"},\"directory()\":{\"notice\":\"The directory of terminals and controllers for projects.\"},\"distributePayoutsOf(uint256,uint256,uint256,address,uint256,string)\":{\"notice\":\"Distributes payouts for a project with the distribution limit of its current funding cycle.\"},\"fee()\":{\"notice\":\"The platform fee percent.\"},\"feeGauge()\":{\"notice\":\"The data source that returns a discount to apply to a project's fee.\"},\"heldFeesOf(uint256)\":{\"notice\":\"The fees that are currently being held to be processed later for each project.\"},\"isFeelessAddress(address)\":{\"notice\":\"Addresses that can be paid towards from this terminal without incurring a fee.\"},\"migrate(uint256,address)\":{\"notice\":\"Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\"},\"operatorStore()\":{\"notice\":\" A contract storing operator assignments.\"},\"pay(uint256,uint256,address,address,uint256,bool,string,bytes)\":{\"notice\":\"Contribute tokens to a project.\"},\"payoutSplitsGroup()\":{\"notice\":\"The group that payout splits coming from this terminal are identified by.\"},\"prices()\":{\"notice\":\"The contract that exposes price feeds.\"},\"processFees(uint256)\":{\"notice\":\"Process any fees that are being held for the project.\"},\"projects()\":{\"notice\":\"Mints ERC-721's that represent project ownership and transfers.\"},\"redeemTokensOf(address,uint256,uint256,address,uint256,address,string,bytes)\":{\"notice\":\"Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\"},\"setFee(uint256)\":{\"notice\":\"Allows the fee to be updated.\"},\"setFeeGauge(address)\":{\"notice\":\"Allows the fee gauge to be updated.\"},\"setFeelessAddress(address,bool)\":{\"notice\":\"Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\"},\"splitsStore()\":{\"notice\":\"The contract that stores splits for each project.\"},\"store()\":{\"notice\":\"The contract that stores and manages the terminal's data.\"},\"supportsInterface(bytes4)\":{\"notice\":\"Indicates if this contract adheres to the specified interface.\"},\"token()\":{\"notice\":\"The token that this terminal accepts.\"},\"useAllowanceOf(uint256,uint256,uint256,address,uint256,address,string)\":{\"notice\":\"Allows a project to send funds from its overflow up to the preconfigured allowance.\"}},\"notice\":\"Manages all inflows and outflows of ETH funds into the protocol ecosystem.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/JBETHPaymentTerminal.sol\":\"JBETHPaymentTerminal\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0x24e0364e503a9bbde94c715d26573a76f14cd2a202d45f96f52134ab806b67b9\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool _approved) external;\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x516a22876c1fab47f49b1bc22b4614491cd05338af8bd2e7b382da090a079990\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3777e696b62134e6177440dbe6e6601c0c156a443f57167194b67e75527439de\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"@paulrberg/contracts/math/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\nimport \\\"prb-math/contracts/PRBMath.sol\\\";\\n\",\"keccak256\":\"0x42821345981bc0434a90ba2268a2f5278dfe9e38166981d72fc7f3b776a29495\",\"license\":\"Unlicense\"},\"contracts/JBETHPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport '@openzeppelin/contracts/utils/Address.sol';\\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\\nimport './libraries/JBSplitsGroups.sol';\\n\\n/**\\n @notice\\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\\n\\n @dev\\n Inherits from -\\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\\n*/\\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\\n //*********************************************************************//\\n // -------------------------- internal views ------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Checks the balance of tokens in this contract.\\n\\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\\n */\\n function _balance() internal view override returns (uint256) {\\n return address(this).balance;\\n }\\n\\n //*********************************************************************//\\n // -------------------------- constructor ---------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @param _baseWeightCurrency The currency to base token issuance on.\\n @param _operatorStore A contract storing operator assignments.\\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\\n @param _directory A contract storing directories of terminals and controllers for each project.\\n @param _splitsStore A contract that stores splits for each project.\\n @param _prices A contract that exposes price feeds.\\n @param _store A contract that stores the terminal's data.\\n @param _owner The address that will own this contract.\\n */\\n constructor(\\n uint256 _baseWeightCurrency,\\n IJBOperatorStore _operatorStore,\\n IJBProjects _projects,\\n IJBDirectory _directory,\\n IJBSplitsStore _splitsStore,\\n IJBPrices _prices,\\n IJBSingleTokenPaymentTerminalStore _store,\\n address _owner\\n )\\n JBPayoutRedemptionPaymentTerminal(\\n JBTokens.ETH,\\n 18, // 18 decimals.\\n JBCurrencies.ETH,\\n _baseWeightCurrency,\\n JBSplitsGroups.ETH_PAYOUT,\\n _operatorStore,\\n _projects,\\n _directory,\\n _splitsStore,\\n _prices,\\n _store,\\n _owner\\n )\\n // solhint-disable-next-line no-empty-blocks\\n {\\n\\n }\\n\\n //*********************************************************************//\\n // ---------------------- internal transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Transfers tokens.\\n\\n @param _from The address from which the transfer should originate.\\n @param _to The address to which the transfer should go.\\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\\n */\\n function _transferFrom(\\n address _from,\\n address payable _to,\\n uint256 _amount\\n ) internal override {\\n _from; // Prevents unused var compiler and natspec complaints.\\n\\n Address.sendValue(_to, _amount);\\n }\\n}\\n\",\"keccak256\":\"0x6afb443f7efddb2ecd7023237f6e1684c4281a1fad43e4e1b34fa0d50b407384\",\"license\":\"MIT\"},\"contracts/abstract/JBOperatable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport './../interfaces/IJBOperatable.sol';\\n\\n/** \\n @notice\\n Modifiers to allow access to functions based on the message sender's operator status.\\n\\n @dev\\n Adheres to -\\n IJBOperatable: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n*/\\nabstract contract JBOperatable is IJBOperatable {\\n //*********************************************************************//\\n // --------------------------- custom errors -------------------------- //\\n //*********************************************************************//\\n error UNAUTHORIZED();\\n\\n //*********************************************************************//\\n // ---------------------------- modifiers ---------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Only allows the speficied account or an operator of the account to proceed. \\n\\n @param _account The account to check for.\\n @param _domain The domain namespace to look for an operator within. \\n @param _permissionIndex The index of the permission to check for. \\n */\\n modifier requirePermission(\\n address _account,\\n uint256 _domain,\\n uint256 _permissionIndex\\n ) {\\n _requirePermission(_account, _domain, _permissionIndex);\\n _;\\n }\\n\\n /** \\n @notice\\n Only allows the speficied account, an operator of the account to proceed, or a truthy override flag. \\n\\n @param _account The account to check for.\\n @param _domain The domain namespace to look for an operator within. \\n @param _permissionIndex The index of the permission to check for. \\n @param _override A condition to force allowance for.\\n */\\n modifier requirePermissionAllowingOverride(\\n address _account,\\n uint256 _domain,\\n uint256 _permissionIndex,\\n bool _override\\n ) {\\n _requirePermissionAllowingOverride(_account, _domain, _permissionIndex, _override);\\n _;\\n }\\n\\n //*********************************************************************//\\n // ---------------- public immutable stored properties --------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n A contract storing operator assignments.\\n */\\n IJBOperatorStore public immutable override operatorStore;\\n\\n //*********************************************************************//\\n // -------------------------- constructor ---------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @param _operatorStore A contract storing operator assignments.\\n */\\n constructor(IJBOperatorStore _operatorStore) {\\n operatorStore = _operatorStore;\\n }\\n\\n //*********************************************************************//\\n // -------------------------- internal views ------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Require the message sender is either the account or has the specified permission.\\n\\n @param _account The account to allow.\\n @param _domain The domain namespace within which the permission index will be checked.\\n @param _permissionIndex The permission index that an operator must have within the specified domain to be allowed.\\n */\\n function _requirePermission(\\n address _account,\\n uint256 _domain,\\n uint256 _permissionIndex\\n ) internal view {\\n if (\\n msg.sender != _account &&\\n !operatorStore.hasPermission(msg.sender, _account, _domain, _permissionIndex) &&\\n !operatorStore.hasPermission(msg.sender, _account, 0, _permissionIndex)\\n ) revert UNAUTHORIZED();\\n }\\n\\n /** \\n @notice\\n Require the message sender is either the account, has the specified permission, or the override condition is true.\\n\\n @param _account The account to allow.\\n @param _domain The domain namespace within which the permission index will be checked.\\n @param _domain The permission index that an operator must have within the specified domain to be allowed.\\n @param _override The override condition to allow.\\n */\\n function _requirePermissionAllowingOverride(\\n address _account,\\n uint256 _domain,\\n uint256 _permissionIndex,\\n bool _override\\n ) internal view {\\n if (\\n !_override &&\\n msg.sender != _account &&\\n !operatorStore.hasPermission(msg.sender, _account, _domain, _permissionIndex) &&\\n !operatorStore.hasPermission(msg.sender, _account, 0, _permissionIndex)\\n ) revert UNAUTHORIZED();\\n }\\n}\\n\",\"keccak256\":\"0x9e62cac5c464eb973f881cf6c373b95aab31d2ddbeb048ee7ad82b5c9ab28add\",\"license\":\"MIT\"},\"contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport '@openzeppelin/contracts/access/Ownable.sol';\\nimport '@paulrberg/contracts/math/PRBMath.sol';\\nimport './../interfaces/IJBController.sol';\\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal.sol';\\nimport './../libraries/JBConstants.sol';\\nimport './../libraries/JBCurrencies.sol';\\nimport './../libraries/JBFixedPointNumber.sol';\\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\\nimport './../libraries/JBOperations.sol';\\nimport './../libraries/JBTokens.sol';\\nimport './../structs/JBPayDelegateAllocation.sol';\\nimport './../structs/JBTokenAmount.sol';\\nimport './JBOperatable.sol';\\nimport './JBSingleTokenPaymentTerminal.sol';\\n\\n/**\\n @notice\\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\\n\\n @dev\\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\\n\\n @dev\\n Adheres to -\\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n\\n @dev\\n Inherits from -\\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\\n*/\\nabstract contract JBPayoutRedemptionPaymentTerminal is\\n JBSingleTokenPaymentTerminal,\\n JBOperatable,\\n Ownable,\\n IJBPayoutRedemptionPaymentTerminal\\n{\\n // A library that parses the packed funding cycle metadata into a friendlier format.\\n using JBFundingCycleMetadataResolver for JBFundingCycle;\\n\\n //*********************************************************************//\\n // --------------------------- custom errors ------------------------- //\\n //*********************************************************************//\\n error FEE_TOO_HIGH();\\n error INADEQUATE_DISTRIBUTION_AMOUNT();\\n error INADEQUATE_RECLAIM_AMOUNT();\\n error INADEQUATE_TOKEN_COUNT();\\n error NO_MSG_VALUE_ALLOWED();\\n error PAY_TO_ZERO_ADDRESS();\\n error PROJECT_TERMINAL_MISMATCH();\\n error REDEEM_TO_ZERO_ADDRESS();\\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\\n error TERMINAL_TOKENS_INCOMPATIBLE();\\n\\n //*********************************************************************//\\n // ---------------------------- modifiers ---------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n A modifier that verifies this terminal is a terminal of provided project ID.\\n */\\n modifier isTerminalOf(uint256 _projectId) {\\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\\n _;\\n }\\n\\n //*********************************************************************//\\n // --------------------- internal stored constants ------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Maximum fee that can be set for a funding cycle configuration.\\n\\n @dev\\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\\n */\\n uint256 internal constant _FEE_CAP = 50_000_000;\\n\\n /**\\n @notice\\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\\n */\\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\\n\\n //*********************************************************************//\\n // --------------------- internal stored properties ------------------ //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Fees that are being held to be processed later.\\n\\n _projectId The ID of the project for which fees are being held.\\n */\\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\\n\\n //*********************************************************************//\\n // ---------------- public immutable stored properties --------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Mints ERC-721's that represent project ownership and transfers.\\n */\\n IJBProjects public immutable override projects;\\n\\n /**\\n @notice\\n The directory of terminals and controllers for projects.\\n */\\n IJBDirectory public immutable override directory;\\n\\n /**\\n @notice\\n The contract that stores splits for each project.\\n */\\n IJBSplitsStore public immutable override splitsStore;\\n\\n /**\\n @notice\\n The contract that exposes price feeds.\\n */\\n IJBPrices public immutable override prices;\\n\\n /**\\n @notice\\n The contract that stores and manages the terminal's data.\\n */\\n IJBSingleTokenPaymentTerminalStore public immutable override store;\\n\\n /**\\n @notice\\n The currency to base token issuance on.\\n\\n @dev\\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\\n */\\n uint256 public immutable override baseWeightCurrency;\\n\\n /**\\n @notice\\n The group that payout splits coming from this terminal are identified by.\\n */\\n uint256 public immutable override payoutSplitsGroup;\\n\\n //*********************************************************************//\\n // --------------------- public stored properties -------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The platform fee percent.\\n\\n @dev\\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\\n */\\n uint256 public override fee = 25_000_000; // 2.5%\\n\\n /**\\n @notice\\n The data source that returns a discount to apply to a project's fee.\\n */\\n IJBFeeGauge public override feeGauge;\\n\\n /**\\n @notice\\n Addresses that can be paid towards from this terminal without incurring a fee.\\n\\n @dev\\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\\n\\n _address The address that can be paid toward.\\n */\\n mapping(address => bool) public override isFeelessAddress;\\n\\n //*********************************************************************//\\n // ------------------------- external views -------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\\n\\n @dev\\n The current overflow is represented as a fixed point number with 18 decimals.\\n\\n @param _projectId The ID of the project to get overflow for.\\n\\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\\n */\\n function currentEthOverflowOf(uint256 _projectId)\\n external\\n view\\n virtual\\n override\\n returns (uint256)\\n {\\n // Get this terminal's current overflow.\\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\\n\\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\\n uint256 _adjustedOverflow = (decimals == 18)\\n ? _overflow\\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\\n\\n // Return the amount converted to ETH.\\n return\\n (currency == JBCurrencies.ETH)\\n ? _adjustedOverflow\\n : PRBMath.mulDiv(\\n _adjustedOverflow,\\n 10**decimals,\\n prices.priceFor(currency, JBCurrencies.ETH, decimals)\\n );\\n }\\n\\n /**\\n @notice\\n The fees that are currently being held to be processed later for each project.\\n\\n @param _projectId The ID of the project for which fees are being held.\\n\\n @return An array of fees that are being held.\\n */\\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\\n return _heldFeesOf[_projectId];\\n }\\n\\n //*********************************************************************//\\n // -------------------------- public views --------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Indicates if this contract adheres to the specified interface.\\n\\n @dev \\n See {IERC165-supportsInterface}.\\n\\n @param _interfaceId The ID of the interface to check for adherance to.\\n */\\n function supportsInterface(bytes4 _interfaceId)\\n public\\n view\\n virtual\\n override(JBSingleTokenPaymentTerminal, IERC165)\\n returns (bool)\\n {\\n return\\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\\n _interfaceId == type(IJBOperatable).interfaceId ||\\n super.supportsInterface(_interfaceId);\\n }\\n\\n //*********************************************************************//\\n // -------------------------- internal views ------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Checks the balance of tokens in this contract.\\n\\n @return The contract's balance.\\n */\\n function _balance() internal view virtual returns (uint256);\\n\\n //*********************************************************************//\\n // -------------------------- constructor ---------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @param _token The token that this terminal manages.\\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\\n @param _currency The currency that this terminal's token adheres to for price feeds.\\n @param _baseWeightCurrency The currency to base token issuance on.\\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\\n @param _operatorStore A contract storing operator assignments.\\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\\n @param _directory A contract storing directories of terminals and controllers for each project.\\n @param _splitsStore A contract that stores splits for each project.\\n @param _prices A contract that exposes price feeds.\\n @param _store A contract that stores the terminal's data.\\n @param _owner The address that will own this contract.\\n */\\n constructor(\\n // payable constructor save the gas used to check msg.value==0\\n address _token,\\n uint256 _decimals,\\n uint256 _currency,\\n uint256 _baseWeightCurrency,\\n uint256 _payoutSplitsGroup,\\n IJBOperatorStore _operatorStore,\\n IJBProjects _projects,\\n IJBDirectory _directory,\\n IJBSplitsStore _splitsStore,\\n IJBPrices _prices,\\n IJBSingleTokenPaymentTerminalStore _store,\\n address _owner\\n )\\n payable\\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\\n JBOperatable(_operatorStore)\\n {\\n baseWeightCurrency = _baseWeightCurrency;\\n payoutSplitsGroup = _payoutSplitsGroup;\\n projects = _projects;\\n directory = _directory;\\n splitsStore = _splitsStore;\\n prices = _prices;\\n store = _store;\\n\\n transferOwnership(_owner);\\n }\\n\\n //*********************************************************************//\\n // ---------------------- external transactions ---------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Contribute tokens to a project.\\n\\n @param _projectId The ID of the project being paid.\\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\\n\\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\\n */\\n function pay(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n // ETH shouldn't be sent if this terminal's token isn't ETH.\\n if (token != JBTokens.ETH) {\\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\\n\\n // Get a reference to the balance before receiving tokens.\\n uint256 _balanceBefore = _balance();\\n\\n // Transfer tokens to this terminal from the msg sender.\\n _transferFrom(msg.sender, payable(address(this)), _amount);\\n\\n // The amount should reflect the change in balance.\\n _amount = _balance() - _balanceBefore;\\n }\\n // If this terminal's token is ETH, override _amount with msg.value.\\n else _amount = msg.value;\\n\\n return\\n _pay(\\n _amount,\\n msg.sender,\\n _projectId,\\n _beneficiary,\\n _minReturnedTokens,\\n _preferClaimedTokens,\\n _memo,\\n _metadata\\n );\\n }\\n\\n /**\\n @notice\\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\\n\\n @dev\\n Only a token holder or a designated operator can redeem its tokens.\\n\\n @param _holder The account to redeem tokens for.\\n @param _projectId The ID of the project to which the tokens being redeemed belong.\\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\\n @param _beneficiary The address to send the terminal tokens to.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\\n\\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\\n */\\n function redeemTokensOf(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n address _token,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string memory _memo,\\n bytes memory _metadata\\n )\\n external\\n virtual\\n override\\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\\n returns (uint256 reclaimAmount)\\n {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n return\\n _redeemTokensOf(\\n _holder,\\n _projectId,\\n _tokenCount,\\n _minReturnedTokens,\\n _beneficiary,\\n _memo,\\n _metadata\\n );\\n }\\n\\n /**\\n @notice\\n Distributes payouts for a project with the distribution limit of its current funding cycle.\\n\\n @dev\\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\\n\\n @dev\\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\\n\\n @dev\\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\\n\\n @param _projectId The ID of the project having its payouts distributed.\\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\\n @param _memo A memo to pass along to the emitted event.\\n\\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\\n */\\n function distributePayoutsOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n address _token,\\n uint256 _minReturnedTokens,\\n string calldata _memo\\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\\n }\\n\\n /**\\n @notice\\n Allows a project to send funds from its overflow up to the preconfigured allowance.\\n\\n @dev\\n Only a project's owner or a designated operator can use its allowance.\\n\\n @dev\\n Incurs the protocol fee.\\n\\n @param _projectId The ID of the project to use the allowance of.\\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\\n @param _beneficiary The address to send the funds to.\\n @param _memo A memo to pass along to the emitted event.\\n\\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\\n */\\n function useAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n address _token,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string memory _memo\\n )\\n external\\n virtual\\n override\\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\\n returns (uint256 netDistributedAmount)\\n {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\\n }\\n\\n /**\\n @notice\\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\\n\\n @dev\\n Only a project's owner or a designated operator can migrate it.\\n\\n @param _projectId The ID of the project being migrated.\\n @param _to The terminal contract that will gain the project's funds.\\n\\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\\n */\\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\\n external\\n virtual\\n override\\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\\n returns (uint256 balance)\\n {\\n // The terminal being migrated to must accept the same token as this terminal.\\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\\n\\n // Record the migration in the store.\\n balance = store.recordMigration(_projectId);\\n\\n // Transfer the balance if needed.\\n if (balance > 0) {\\n // Trigger any inherited pre-transfer logic.\\n _beforeTransferTo(address(_to), balance);\\n\\n // If this terminal's token is ETH, send it in msg.value.\\n uint256 _payableValue = token == JBTokens.ETH ? balance : 0;\\n\\n // Withdraw the balance to transfer to the new terminal;\\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\\n }\\n\\n emit Migrate(_projectId, _to, balance, msg.sender);\\n }\\n\\n /**\\n @notice\\n Receives funds belonging to the specified project.\\n\\n @param _projectId The ID of the project to which the funds received belong.\\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Extra data to pass along to the emitted event.\\n */\\n function addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable virtual override isTerminalOf(_projectId) {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\\n if (token != JBTokens.ETH) {\\n // Amount must be greater than 0.\\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\\n\\n // Get a reference to the balance before receiving tokens.\\n uint256 _balanceBefore = _balance();\\n\\n // Transfer tokens to this terminal from the msg sender.\\n _transferFrom(msg.sender, payable(address(this)), _amount);\\n\\n // The amount should reflect the change in balance.\\n _amount = _balance() - _balanceBefore;\\n }\\n // If the terminal's token is ETH, override `_amount` with msg.value.\\n else _amount = msg.value;\\n\\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\\n }\\n\\n /**\\n @notice\\n Process any fees that are being held for the project.\\n\\n @dev\\n Only a project owner, an operator, or the contract's owner can process held fees.\\n\\n @param _projectId The ID of the project whos held fees should be processed.\\n */\\n function processFees(uint256 _projectId)\\n external\\n virtual\\n override\\n requirePermissionAllowingOverride(\\n projects.ownerOf(_projectId),\\n _projectId,\\n JBOperations.PROCESS_FEES,\\n msg.sender == owner()\\n )\\n {\\n // Get a reference to the project's held fees.\\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\\n\\n // Delete the held fees.\\n delete _heldFeesOf[_projectId];\\n\\n // Push array length in stack\\n uint256 _heldFeeLength = _heldFees.length;\\n\\n // Process each fee.\\n for (uint256 _i; _i < _heldFeeLength; ) {\\n // Get the fee amount.\\n uint256 _amount = _feeAmount(\\n _heldFees[_i].amount,\\n _heldFees[_i].fee,\\n _heldFees[_i].feeDiscount\\n );\\n\\n // Process the fee.\\n _processFee(_amount, _heldFees[_i].beneficiary);\\n\\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n\\n /**\\n @notice\\n Allows the fee to be updated.\\n\\n @dev\\n Only the owner of this contract can change the fee.\\n\\n @param _fee The new fee, out of MAX_FEE.\\n */\\n function setFee(uint256 _fee) external virtual override onlyOwner {\\n // The provided fee must be within the max.\\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\\n\\n // Store the new fee.\\n fee = _fee;\\n\\n emit SetFee(_fee, msg.sender);\\n }\\n\\n /**\\n @notice\\n Allows the fee gauge to be updated.\\n\\n @dev\\n Only the owner of this contract can change the fee gauge.\\n\\n @param _feeGauge The new fee gauge.\\n */\\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\\n // Store the new fee gauge.\\n feeGauge = _feeGauge;\\n\\n emit SetFeeGauge(_feeGauge, msg.sender);\\n }\\n\\n /**\\n @notice\\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\\n\\n @dev\\n Only the owner of this contract can set addresses as feeless.\\n\\n @param _address The address that can be paid towards while still bypassing fees.\\n @param _flag A flag indicating whether the terminal should be feeless or not.\\n */\\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\\n // Set the flag value.\\n isFeelessAddress[_address] = _flag;\\n\\n emit SetFeelessAddress(_address, _flag, msg.sender);\\n }\\n\\n //*********************************************************************//\\n // ---------------------- internal transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Transfers tokens.\\n\\n @param _from The address from which the transfer should originate.\\n @param _to The address to which the transfer should go.\\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\\n */\\n function _transferFrom(\\n address _from,\\n address payable _to,\\n uint256 _amount\\n ) internal virtual {\\n _from; // Prevents unused var compiler and natspec complaints.\\n _to; // Prevents unused var compiler and natspec complaints.\\n _amount; // Prevents unused var compiler and natspec complaints.\\n }\\n\\n /** \\n @notice\\n Logic to be triggered before transferring tokens from this terminal.\\n\\n @param _to The address to which the transfer is going.\\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\\n */\\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\\n _to; // Prevents unused var compiler and natspec complaints.\\n _amount; // Prevents unused var compiler and natspec complaints.\\n }\\n\\n /**\\n @notice\\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\\n\\n @dev\\n Only a token holder or a designated operator can redeem its tokens.\\n\\n @param _holder The account to redeem tokens for.\\n @param _projectId The ID of the project to which the tokens being redeemed belong.\\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\\n @param _beneficiary The address to send the terminal tokens to.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\\n\\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\\n */\\n function _redeemTokensOf(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string memory _memo,\\n bytes memory _metadata\\n ) internal returns (uint256 reclaimAmount) {\\n // Can't send reclaimed funds to the zero address.\\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\\n\\n // Define variables that will be needed outside the scoped section below.\\n // Keep a reference to the funding cycle during which the redemption is being made.\\n JBFundingCycle memory _fundingCycle;\\n\\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\\n {\\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\\n\\n // Record the redemption.\\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\\n _holder,\\n _projectId,\\n _tokenCount,\\n _memo,\\n _metadata\\n );\\n\\n // The amount being reclaimed must be at least as much as was expected.\\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\\n\\n // Burn the project tokens.\\n if (_tokenCount > 0)\\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\\n _holder,\\n _projectId,\\n _tokenCount,\\n '',\\n false\\n );\\n\\n // If delegate allocations were specified by the data source, fulfill them.\\n if (_delegateAllocations.length != 0) {\\n // Keep a reference to the token amount being forwarded to the delegate.\\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\\n\\n JBDidRedeemData memory _data = JBDidRedeemData(\\n _holder,\\n _projectId,\\n _fundingCycle.configuration,\\n _tokenCount,\\n JBTokenAmount(token, reclaimAmount, decimals, currency),\\n _forwardedAmount,\\n _beneficiary,\\n _memo,\\n _metadata\\n );\\n\\n uint256 _numDelegates = _delegateAllocations.length;\\n\\n for (uint256 _i; _i < _numDelegates; ) {\\n // Get a reference to the delegate being iterated on.\\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\\n\\n // Trigger any inherited pre-transfer logic.\\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\\n\\n // Keep track of the msg.value to use in the delegate call\\n uint256 _payableValue;\\n\\n // If this terminal's token is ETH, send it in msg.value.\\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\\n\\n // Pass the correct token forwardedAmount to the delegate\\n _data.forwardedAmount.value = _delegateAllocation.amount;\\n\\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\\n\\n emit DelegateDidRedeem(\\n _delegateAllocation.delegate,\\n _data,\\n _delegateAllocation.amount,\\n msg.sender\\n );\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n }\\n\\n // Send the reclaimed funds to the beneficiary.\\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\\n\\n emit RedeemTokens(\\n _fundingCycle.configuration,\\n _fundingCycle.number,\\n _projectId,\\n _holder,\\n _beneficiary,\\n _tokenCount,\\n reclaimAmount,\\n _memo,\\n _metadata,\\n msg.sender\\n );\\n }\\n\\n /**\\n @notice\\n Distributes payouts for a project with the distribution limit of its current funding cycle.\\n\\n @dev\\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\\n\\n @dev\\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\\n\\n @dev\\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\\n\\n @param _projectId The ID of the project having its payouts distributed.\\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\\n @param _memo A memo to pass along to the emitted event.\\n\\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\\n */\\n function _distributePayoutsOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n uint256 _minReturnedTokens,\\n string calldata _memo\\n ) internal returns (uint256 netLeftoverDistributionAmount) {\\n // Record the distribution.\\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\\n _projectId,\\n _amount,\\n _currency\\n );\\n\\n // The amount being distributed must be at least as much as was expected.\\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\\n\\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\\n // and receive any extra distributable funds not allocated to payout splits.\\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\\n\\n // Define variables that will be needed outside the scoped section below.\\n // Keep a reference to the fee amount that was paid.\\n uint256 _fee;\\n\\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\\n {\\n // Get the amount of discount that should be applied to any fees taken.\\n // If the fee is zero, set the discount to 100% for convenience.\\n uint256 _feeDiscount = fee == 0\\n ? JBConstants.MAX_FEE_DISCOUNT\\n : _currentFeeDiscount(_projectId);\\n\\n // The amount distributed that is eligible for incurring fees.\\n uint256 _feeEligibleDistributionAmount;\\n\\n // The amount leftover after distributing to the splits.\\n uint256 _leftoverDistributionAmount;\\n\\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\\n _projectId,\\n _fundingCycle.configuration,\\n payoutSplitsGroup,\\n _distributedAmount,\\n _feeDiscount\\n );\\n\\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\\n unchecked {\\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\\n }\\n }\\n\\n // Take the fee.\\n _fee = _feeEligibleDistributionAmount != 0\\n ? _takeFeeFrom(\\n _projectId,\\n _fundingCycle,\\n _feeEligibleDistributionAmount,\\n _projectOwner,\\n _feeDiscount\\n )\\n : 0;\\n\\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\\n if (_leftoverDistributionAmount != 0) {\\n // Subtract the fee from the net leftover amount.\\n netLeftoverDistributionAmount =\\n _leftoverDistributionAmount -\\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\\n\\n // Transfer the amount to the project owner.\\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\\n }\\n }\\n\\n emit DistributePayouts(\\n _fundingCycle.configuration,\\n _fundingCycle.number,\\n _projectId,\\n _projectOwner,\\n _amount,\\n _distributedAmount,\\n _fee,\\n netLeftoverDistributionAmount,\\n _memo,\\n msg.sender\\n );\\n }\\n\\n /**\\n @notice\\n Allows a project to send funds from its overflow up to the preconfigured allowance.\\n\\n @dev\\n Only a project's owner or a designated operator can use its allowance.\\n\\n @dev\\n Incurs the protocol fee.\\n\\n @param _projectId The ID of the project to use the allowance of.\\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\\n @param _beneficiary The address to send the funds to.\\n @param _memo A memo to pass along to the emitted event.\\n\\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\\n */\\n function _useAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string memory _memo\\n ) internal returns (uint256 netDistributedAmount) {\\n // Record the use of the allowance.\\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\\n _projectId,\\n _amount,\\n _currency\\n );\\n\\n // The amount being withdrawn must be at least as much as was expected.\\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\\n\\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\\n {\\n // Keep a reference to the fee amount that was paid.\\n uint256 _fee;\\n\\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\\n address _projectOwner = projects.ownerOf(_projectId);\\n\\n // Get the amount of discount that should be applied to any fees taken.\\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\\n ? JBConstants.MAX_FEE_DISCOUNT\\n : _currentFeeDiscount(_projectId);\\n\\n // Take a fee from the `_distributedAmount`, if needed.\\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\\n ? 0\\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\\n\\n unchecked {\\n // The net amount is the withdrawn amount without the fee.\\n netDistributedAmount = _distributedAmount - _fee;\\n }\\n\\n // Transfer any remaining balance to the beneficiary.\\n if (netDistributedAmount > 0)\\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\\n }\\n\\n emit UseAllowance(\\n _fundingCycle.configuration,\\n _fundingCycle.number,\\n _projectId,\\n _beneficiary,\\n _amount,\\n _distributedAmount,\\n netDistributedAmount,\\n _memo,\\n msg.sender\\n );\\n }\\n\\n /**\\n @notice\\n Pays out splits for a project's funding cycle configuration.\\n\\n @param _projectId The ID of the project for which payout splits are being distributed.\\n @param _domain The domain of the splits to distribute the payout between.\\n @param _group The group of the splits to distribute the payout between.\\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\\n\\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\\n */\\n function _distributeToPayoutSplitsOf(\\n uint256 _projectId,\\n uint256 _domain,\\n uint256 _group,\\n uint256 _amount,\\n uint256 _feeDiscount\\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\\n // Set the leftover amount to the initial amount.\\n leftoverAmount = _amount;\\n // The total percentage available to split\\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\\n\\n // Get a reference to the project's payout splits.\\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\\n\\n // Transfer between all splits.\\n for (uint256 _i; _i < _splits.length; ) {\\n // Get a reference to the split being iterated on.\\n JBSplit memory _split = _splits[_i];\\n\\n // The amount to send towards the split.\\n uint256 _payoutAmount = _split.percent == leftoverPercentage\\n ? leftoverAmount\\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\\n\\n // Decrement the leftover percentage.\\n leftoverPercentage -= _split.percent;\\n\\n // The payout amount substracting any applicable incurred fees.\\n uint256 _netPayoutAmount;\\n\\n if (_payoutAmount > 0) {\\n // Transfer tokens to the split.\\n // If there's an allocator set, transfer to its `allocate` function.\\n if (_split.allocator != IJBSplitAllocator(address(0))) {\\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\\n if (\\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\\n isFeelessAddress[address(_split.allocator)]\\n )\\n _netPayoutAmount = _payoutAmount;\\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\\n else {\\n unchecked {\\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\\n }\\n\\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\\n feeEligibleDistributionAmount += _payoutAmount;\\n }\\n\\n // Trigger any inherited pre-transfer logic.\\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\\n\\n // Create the data to send to the allocator.\\n JBSplitAllocationData memory _data = JBSplitAllocationData(\\n token,\\n _netPayoutAmount,\\n decimals,\\n _projectId,\\n _group,\\n _split\\n );\\n\\n // Trigger the allocator's `allocate` function.\\n // If this terminal's token is ETH, send it in msg.value.\\n _split.allocator.allocate{value: token == JBTokens.ETH ? _netPayoutAmount : 0}(_data);\\n\\n // Otherwise, if a project is specified, make a payment to it.\\n } else if (_split.projectId != 0) {\\n // Get a reference to the Juicebox terminal being used.\\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\\n\\n // The project must have a terminal to send funds to.\\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\\n\\n // Save gas if this contract is being used as the terminal.\\n if (_terminal == this) {\\n // This distribution does not incur a fee.\\n _netPayoutAmount = _payoutAmount;\\n\\n // Send the projectId in the metadata.\\n bytes memory _projectMetadata = new bytes(32);\\n _projectMetadata = bytes(abi.encodePacked(_projectId));\\n\\n // Add to balance if prefered.\\n if (_split.preferAddToBalance)\\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\\n else\\n _pay(\\n _netPayoutAmount,\\n address(this),\\n _split.projectId,\\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\\n 0,\\n _split.preferClaimed,\\n '',\\n _projectMetadata\\n );\\n } else {\\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\\n if (\\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_terminal)]\\n )\\n _netPayoutAmount = _payoutAmount;\\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\\n else {\\n unchecked {\\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\\n }\\n\\n feeEligibleDistributionAmount += _payoutAmount;\\n }\\n\\n // Trigger any inherited pre-transfer logic.\\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\\n\\n // If this terminal's token is ETH, send it in msg.value.\\n uint256 _payableValue = token == JBTokens.ETH ? _netPayoutAmount : 0;\\n\\n // Send the projectId in the metadata.\\n bytes memory _projectMetadata = new bytes(32);\\n _projectMetadata = bytes(abi.encodePacked(_projectId));\\n\\n // Add to balance if prefered.\\n if (_split.preferAddToBalance)\\n _terminal.addToBalanceOf{value: _payableValue}(\\n _split.projectId,\\n _netPayoutAmount,\\n token,\\n '',\\n _projectMetadata\\n );\\n else\\n _terminal.pay{value: _payableValue}(\\n _split.projectId,\\n _netPayoutAmount,\\n token,\\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\\n 0,\\n _split.preferClaimed,\\n '',\\n _projectMetadata\\n );\\n }\\n } else {\\n // Keep a reference to the beneficiary.\\n address payable _beneficiary = _split.beneficiary != address(0)\\n ? _split.beneficiary\\n : payable(msg.sender);\\n\\n // If there's a full discount, this distribution is not eligible for a fee.\\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\\n _netPayoutAmount = _payoutAmount;\\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\\n else {\\n unchecked {\\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\\n }\\n\\n feeEligibleDistributionAmount += _payoutAmount;\\n }\\n\\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\\n _transferFrom(address(this), _beneficiary, _netPayoutAmount);\\n }\\n\\n // Subtract from the amount to be sent to the beneficiary.\\n unchecked {\\n leftoverAmount = leftoverAmount - _payoutAmount;\\n }\\n }\\n\\n emit DistributeToPayoutSplit(\\n _projectId,\\n _domain,\\n _group,\\n _split,\\n _netPayoutAmount,\\n msg.sender\\n );\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n\\n /**\\n @notice\\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\\n\\n @param _projectId The ID of the project having fees taken from.\\n @param _fundingCycle The funding cycle during which the fee is being taken.\\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\\n @param _beneficiary The address to mint the platforms tokens for.\\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\\n\\n @return feeAmount The amount of the fee taken.\\n */\\n function _takeFeeFrom(\\n uint256 _projectId,\\n JBFundingCycle memory _fundingCycle,\\n uint256 _amount,\\n address _beneficiary,\\n uint256 _feeDiscount\\n ) internal returns (uint256 feeAmount) {\\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\\n\\n if (_fundingCycle.shouldHoldFees()) {\\n // Store the held fee.\\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\\n\\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\\n } else {\\n // Process the fee.\\n _processFee(feeAmount, _beneficiary); // Take the fee.\\n\\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\\n }\\n }\\n\\n /**\\n @notice\\n Process a fee of the specified amount.\\n\\n @param _amount The fee amount, as a floating point number with 18 decimals.\\n @param _beneficiary The address to mint the platform's tokens for.\\n */\\n function _processFee(uint256 _amount, address _beneficiary) internal {\\n // Get the terminal for the protocol project.\\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\\n\\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\\n if (_terminal == this)\\n _pay(\\n _amount,\\n address(this),\\n _FEE_BENEFICIARY_PROJECT_ID,\\n _beneficiary,\\n 0,\\n false,\\n '',\\n bytes('')\\n ); // Use the local pay call.\\n else {\\n // Trigger any inherited pre-transfer logic.\\n _beforeTransferTo(address(_terminal), _amount);\\n\\n // If this terminal's token is ETH, send it in msg.value.\\n uint256 _payableValue = token == JBTokens.ETH ? _amount : 0;\\n\\n // Send the payment.\\n _terminal.pay{value: _payableValue}(\\n _FEE_BENEFICIARY_PROJECT_ID,\\n _amount,\\n token,\\n _beneficiary,\\n 0,\\n false,\\n '',\\n bytes('')\\n ); // Use the external pay call of the correct terminal.\\n }\\n }\\n\\n /**\\n @notice\\n Contribute tokens to a project.\\n\\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\\n @param _payer The address making the payment.\\n @param _projectId The ID of the project being paid.\\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\\n\\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\\n */\\n function _pay(\\n uint256 _amount,\\n address _payer,\\n uint256 _projectId,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string memory _memo,\\n bytes memory _metadata\\n ) internal returns (uint256 beneficiaryTokenCount) {\\n // Cant send tokens to the zero address.\\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\\n\\n // Define variables that will be needed outside the scoped section below.\\n // Keep a reference to the funding cycle during which the payment is being made.\\n JBFundingCycle memory _fundingCycle;\\n\\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\\n {\\n JBPayDelegateAllocation[] memory _delegateAllocations;\\n uint256 _tokenCount;\\n\\n // Bundle the amount info into a JBTokenAmount struct.\\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\\n\\n // Record the payment.\\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\\n _payer,\\n _bundledAmount,\\n _projectId,\\n baseWeightCurrency,\\n _beneficiary,\\n _memo,\\n _metadata\\n );\\n\\n // Mint the tokens if needed.\\n if (_tokenCount > 0)\\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\\n _projectId,\\n _tokenCount,\\n _beneficiary,\\n '',\\n _preferClaimedTokens,\\n true\\n );\\n\\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\\n\\n // If delegate allocations were specified by the data source, fulfill them.\\n if (_delegateAllocations.length != 0) {\\n // Keep a reference to the token amount being forwarded to the delegate.\\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\\n\\n JBDidPayData memory _data = JBDidPayData(\\n _payer,\\n _projectId,\\n _fundingCycle.configuration,\\n _bundledAmount,\\n _forwardedAmount,\\n beneficiaryTokenCount,\\n _beneficiary,\\n _preferClaimedTokens,\\n _memo,\\n _metadata\\n );\\n\\n // Get a reference to the number of delegates to allocate to.\\n uint256 _numDelegates = _delegateAllocations.length;\\n\\n for (uint256 _i; _i < _numDelegates; ) {\\n // Get a reference to the delegate being iterated on.\\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\\n\\n // Trigger any inherited pre-transfer logic.\\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\\n\\n // Keep track of the msg.value to use in the delegate call\\n uint256 _payableValue;\\n\\n // If this terminal's token is ETH, send it in msg.value.\\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\\n\\n // Pass the correct token forwardedAmount to the delegate\\n _data.forwardedAmount.value = _delegateAllocation.amount;\\n\\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\\n\\n emit DelegateDidPay(\\n _delegateAllocation.delegate,\\n _data,\\n _delegateAllocation.amount,\\n msg.sender\\n );\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n }\\n\\n emit Pay(\\n _fundingCycle.configuration,\\n _fundingCycle.number,\\n _projectId,\\n _payer,\\n _beneficiary,\\n _amount,\\n beneficiaryTokenCount,\\n _memo,\\n _metadata,\\n msg.sender\\n );\\n }\\n\\n /**\\n @notice\\n Receives funds belonging to the specified project.\\n\\n @param _projectId The ID of the project to which the funds received belong.\\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Extra data to pass along to the emitted event.\\n */\\n function _addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n bool _shouldRefundHeldFees,\\n string memory _memo,\\n bytes memory _metadata\\n ) internal {\\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\\n\\n // Record the added funds with any refunded fees.\\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\\n\\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\\n }\\n\\n /**\\n @notice\\n Refund fees based on the specified amount.\\n\\n @param _projectId The project for which fees are being refunded.\\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\\n\\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\\n */\\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\\n internal\\n returns (uint256 refundedFees)\\n {\\n // Get a reference to the project's held fees.\\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\\n\\n // Delete the current held fees.\\n delete _heldFeesOf[_projectId];\\n\\n // Get a reference to the leftover amount once all fees have been settled.\\n uint256 leftoverAmount = _amount;\\n\\n // Push length in stack\\n uint256 _heldFeesLength = _heldFees.length;\\n\\n // Process each fee.\\n for (uint256 _i; _i < _heldFeesLength; ) {\\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\\n else if (leftoverAmount >= _heldFees[_i].amount) {\\n unchecked {\\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\\n refundedFees += _feeAmount(\\n _heldFees[_i].amount,\\n _heldFees[_i].fee,\\n _heldFees[_i].feeDiscount\\n );\\n }\\n } else {\\n unchecked {\\n _heldFeesOf[_projectId].push(\\n JBFee(\\n _heldFees[_i].amount - leftoverAmount,\\n _heldFees[_i].fee,\\n _heldFees[_i].feeDiscount,\\n _heldFees[_i].beneficiary\\n )\\n );\\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\\n }\\n leftoverAmount = 0;\\n }\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n\\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\\n }\\n\\n /** \\n @notice \\n Returns the fee amount based on the provided amount for the specified project.\\n\\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\\n @param _fee The percentage of the fee, out of MAX_FEE. \\n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\\n\\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\\n */\\n function _feeAmount(\\n uint256 _amount,\\n uint256 _fee,\\n uint256 _feeDiscount\\n ) internal pure returns (uint256) {\\n // Calculate the discounted fee.\\n uint256 _discountedFee = _fee -\\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\\n\\n // The amount of tokens from the `_amount` to pay as a fee.\\n return\\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\\n }\\n\\n /** \\n @notice\\n Get the fee discount from the fee gauge for the specified project.\\n\\n @param _projectId The ID of the project to get a fee discount for.\\n \\n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\\n */\\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\\n if (\\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\\n IJBPaymentTerminal(address(0))\\n ) return JBConstants.MAX_FEE_DISCOUNT;\\n\\n // Get the fee discount.\\n if (feeGauge != IJBFeeGauge(address(0)))\\n // If the guage reverts, keep the discount at 0.\\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\\n // If the fee discount is greater than the max, we ignore the return value\\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\\n } catch {\\n return 0;\\n }\\n\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0xbd19927d16eca865a8c894bed895c2704fa17ef361b97f90310b5ff0d43d9036\",\"license\":\"MIT\"},\"contracts/abstract/JBSingleTokenPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\\nimport './../interfaces/IJBSingleTokenPaymentTerminal.sol';\\n\\n/**\\n @notice\\n Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\\n\\n @dev\\n Adheres to -\\n IJBSingleTokenPaymentTerminals: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n\\n @dev\\n Inherits from -\\n ERC165: Introspection on interface adherance. \\n*/\\nabstract contract JBSingleTokenPaymentTerminal is ERC165, IJBSingleTokenPaymentTerminal {\\n //*********************************************************************//\\n // ---------------- public immutable stored properties --------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The token that this terminal accepts.\\n */\\n address public immutable override token;\\n\\n /**\\n @notice\\n The number of decimals the token fixed point amounts are expected to have.\\n */\\n uint256 public immutable override decimals;\\n\\n /**\\n @notice\\n The currency to use when resolving price feeds for this terminal.\\n */\\n uint256 public immutable override currency;\\n\\n //*********************************************************************//\\n // ------------------------- external views -------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n A flag indicating if this terminal accepts the specified token.\\n\\n @param _token The token to check if this terminal accepts or not.\\n @param _projectId The project ID to check for token acceptance.\\n\\n @return The flag.\\n */\\n function acceptsToken(address _token, uint256 _projectId) external view override returns (bool) {\\n _projectId; // Prevents unused var compiler and natspec complaints.\\n\\n return _token == token;\\n }\\n\\n /** \\n @notice\\n The decimals that should be used in fixed number accounting for the specified token.\\n\\n @param _token The token to check for the decimals of.\\n\\n @return The number of decimals for the token.\\n */\\n function decimalsForToken(address _token) external view override returns (uint256) {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n return decimals;\\n }\\n\\n /** \\n @notice\\n The currency that should be used for the specified token.\\n\\n @param _token The token to check for the currency of.\\n\\n @return The currency index.\\n */\\n function currencyForToken(address _token) external view override returns (uint256) {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n return currency;\\n }\\n\\n //*********************************************************************//\\n // -------------------------- public views --------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Indicates if this contract adheres to the specified interface.\\n\\n @dev \\n See {IERC165-supportsInterface}.\\n\\n @param _interfaceId The ID of the interface to check for adherance to.\\n */\\n function supportsInterface(bytes4 _interfaceId)\\n public\\n view\\n virtual\\n override(ERC165, IERC165)\\n returns (bool)\\n {\\n return\\n _interfaceId == type(IJBPaymentTerminal).interfaceId ||\\n _interfaceId == type(IJBSingleTokenPaymentTerminal).interfaceId ||\\n super.supportsInterface(_interfaceId);\\n }\\n\\n //*********************************************************************//\\n // -------------------------- constructor ---------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @param _token The token that this terminal manages.\\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\\n @param _currency The currency that this terminal's token adheres to for price feeds.\\n */\\n constructor(\\n address _token,\\n uint256 _decimals,\\n uint256 _currency\\n ) {\\n token = _token;\\n decimals = _decimals;\\n currency = _currency;\\n }\\n}\\n\",\"keccak256\":\"0xdc82ad3e01b918d3d21ffea8c9f30950d81e225137c851599d028dcd22125f89\",\"license\":\"MIT\"},\"contracts/enums/JBBallotState.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nenum JBBallotState {\\n Active,\\n Approved,\\n Failed\\n}\\n\",\"keccak256\":\"0x891fcac63470398b3a11239da7feba6b07d640809fcefd2404303b823d7378f8\",\"license\":\"MIT\"},\"contracts/interfaces/IJBAllowanceTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBAllowanceTerminal {\\n function useAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n address _token,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string calldata _memo\\n ) external returns (uint256 netDistributedAmount);\\n}\\n\",\"keccak256\":\"0x139d7628da9fc8510f53482d592cd4074d21c0cb6d72510ff2743076f3b17533\",\"license\":\"MIT\"},\"contracts/interfaces/IJBController.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBFundAccessConstraints.sol';\\nimport './../structs/JBFundingCycleData.sol';\\nimport './../structs/JBFundingCycleMetadata.sol';\\nimport './../structs/JBGroupedSplits.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBMigratable.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBSplitsStore.sol';\\nimport './IJBTokenStore.sol';\\n\\ninterface IJBController is IERC165 {\\n event LaunchProject(uint256 configuration, uint256 projectId, string memo, address caller);\\n\\n event LaunchFundingCycles(uint256 configuration, uint256 projectId, string memo, address caller);\\n\\n event ReconfigureFundingCycles(\\n uint256 configuration,\\n uint256 projectId,\\n string memo,\\n address caller\\n );\\n\\n event SetFundAccessConstraints(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n JBFundAccessConstraints constraints,\\n address caller\\n );\\n\\n event DistributeReservedTokens(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address beneficiary,\\n uint256 tokenCount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n address caller\\n );\\n\\n event DistributeToReservedTokenSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n uint256 tokenCount,\\n address caller\\n );\\n\\n event MintTokens(\\n address indexed beneficiary,\\n uint256 indexed projectId,\\n uint256 tokenCount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n uint256 reservedRate,\\n address caller\\n );\\n\\n event BurnTokens(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 tokenCount,\\n string memo,\\n address caller\\n );\\n\\n event Migrate(uint256 indexed projectId, IJBMigratable to, address caller);\\n\\n event PrepMigration(uint256 indexed projectId, address from, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function tokenStore() external view returns (IJBTokenStore);\\n\\n function splitsStore() external view returns (IJBSplitsStore);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function reservedTokenBalanceOf(uint256 _projectId, uint256 _reservedRate)\\n external\\n view\\n returns (uint256);\\n\\n function distributionLimitOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n IJBPaymentTerminal _terminal,\\n address _token\\n ) external view returns (uint256 distributionLimit, uint256 distributionLimitCurrency);\\n\\n function overflowAllowanceOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n IJBPaymentTerminal _terminal,\\n address _token\\n ) external view returns (uint256 overflowAllowance, uint256 overflowAllowanceCurrency);\\n\\n function totalOutstandingTokensOf(uint256 _projectId, uint256 _reservedRate)\\n external\\n view\\n returns (uint256);\\n\\n function getFundingCycleOf(uint256 _projectId, uint256 _configuration)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function latestConfiguredFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (\\n JBFundingCycle memory,\\n JBFundingCycleMetadata memory metadata,\\n JBBallotState\\n );\\n\\n function currentFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function queuedFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function launchProjectFor(\\n address _owner,\\n JBProjectMetadata calldata _projectMetadata,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n IJBPaymentTerminal[] memory _terminals,\\n string calldata _memo\\n ) external returns (uint256 projectId);\\n\\n function launchFundingCyclesFor(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n IJBPaymentTerminal[] memory _terminals,\\n string calldata _memo\\n ) external returns (uint256 configuration);\\n\\n function reconfigureFundingCyclesOf(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n string calldata _memo\\n ) external returns (uint256);\\n\\n function mintTokensOf(\\n uint256 _projectId,\\n uint256 _tokenCount,\\n address _beneficiary,\\n string calldata _memo,\\n bool _preferClaimedTokens,\\n bool _useReservedRate\\n ) external returns (uint256 beneficiaryTokenCount);\\n\\n function burnTokensOf(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n string calldata _memo,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function distributeReservedTokensOf(uint256 _projectId, string memory _memo)\\n external\\n returns (uint256);\\n\\n function migrate(uint256 _projectId, IJBMigratable _to) external;\\n}\\n\",\"keccak256\":\"0xb1ee4b41f2a06f28f69c74cb729b8964f2e75f3c545a68f85bd9082b5575bc85\",\"license\":\"MIT\"},\"contracts/interfaces/IJBDirectory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBProjects.sol';\\n\\ninterface IJBDirectory {\\n event SetController(uint256 indexed projectId, address indexed controller, address caller);\\n\\n event AddTerminal(uint256 indexed projectId, IJBPaymentTerminal indexed terminal, address caller);\\n\\n event SetTerminals(uint256 indexed projectId, IJBPaymentTerminal[] terminals, address caller);\\n\\n event SetPrimaryTerminal(\\n uint256 indexed projectId,\\n address indexed token,\\n IJBPaymentTerminal indexed terminal,\\n address caller\\n );\\n\\n event SetIsAllowedToSetFirstController(address indexed addr, bool indexed flag, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function controllerOf(uint256 _projectId) external view returns (address);\\n\\n function isAllowedToSetFirstController(address _address) external view returns (bool);\\n\\n function terminalsOf(uint256 _projectId) external view returns (IJBPaymentTerminal[] memory);\\n\\n function isTerminalOf(uint256 _projectId, IJBPaymentTerminal _terminal)\\n external\\n view\\n returns (bool);\\n\\n function primaryTerminalOf(uint256 _projectId, address _token)\\n external\\n view\\n returns (IJBPaymentTerminal);\\n\\n function setControllerOf(uint256 _projectId, address _controller) external;\\n\\n function setTerminalsOf(uint256 _projectId, IJBPaymentTerminal[] calldata _terminals) external;\\n\\n function setPrimaryTerminalOf(\\n uint256 _projectId,\\n address _token,\\n IJBPaymentTerminal _terminal\\n ) external;\\n\\n function setIsAllowedToSetFirstController(address _address, bool _flag) external;\\n}\\n\",\"keccak256\":\"0x715321646db00514d1355ed43c40cd3f01e94959552fd07797b315d9c49cdb1d\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFeeGauge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBFeeGauge {\\n function currentDiscountFor(uint256 _projectId) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x8e19959617191320fe1210760860e668a57319258c0c74fcfabac829ae0222c0\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleBallot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../enums/JBBallotState.sol';\\n\\ninterface IJBFundingCycleBallot is IERC165 {\\n function duration() external view returns (uint256);\\n\\n function stateOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n uint256 _start\\n ) external view returns (JBBallotState);\\n}\\n\",\"keccak256\":\"0x49553a56209237846bc400cf27f260824a6bd06fd8094a7eb5abb9de75779598\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../enums/JBBallotState.sol';\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBFundingCycleData.sol';\\n\\ninterface IJBFundingCycleStore {\\n event Configure(\\n uint256 indexed configuration,\\n uint256 indexed projectId,\\n JBFundingCycleData data,\\n uint256 metadata,\\n uint256 mustStartAtOrAfter,\\n address caller\\n );\\n\\n event Init(uint256 indexed configuration, uint256 indexed projectId, uint256 indexed basedOn);\\n\\n function latestConfigurationOf(uint256 _projectId) external view returns (uint256);\\n\\n function get(uint256 _projectId, uint256 _configuration)\\n external\\n view\\n returns (JBFundingCycle memory);\\n\\n function latestConfiguredOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBBallotState ballotState);\\n\\n function queuedOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentBallotStateOf(uint256 _projectId) external view returns (JBBallotState);\\n\\n function configureFor(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n uint256 _metadata,\\n uint256 _mustStartAtOrAfter\\n ) external returns (JBFundingCycle memory fundingCycle);\\n}\\n\",\"keccak256\":\"0xaead823851433be0c2ddc8f8086813e6cd647de3a1bc0f7570a5d6b38c378b5a\",\"license\":\"MIT\"},\"contracts/interfaces/IJBMigratable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBMigratable {\\n function prepForMigrationOf(uint256 _projectId, address _from) external;\\n}\\n\",\"keccak256\":\"0xc81053e4b4754fc510aa04fecd3ab1460f01e3e27761e7a8c94f631a978ae127\",\"license\":\"MIT\"},\"contracts/interfaces/IJBOperatable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBOperatorStore.sol';\\n\\ninterface IJBOperatable {\\n function operatorStore() external view returns (IJBOperatorStore);\\n}\\n\",\"keccak256\":\"0x09a55a91c6ce3625379334271d236cfa47bf36522a91568b406bf06f7239407e\",\"license\":\"MIT\"},\"contracts/interfaces/IJBOperatorStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBOperatorData.sol';\\n\\ninterface IJBOperatorStore {\\n event SetOperator(\\n address indexed operator,\\n address indexed account,\\n uint256 indexed domain,\\n uint256[] permissionIndexes,\\n uint256 packed\\n );\\n\\n function permissionsOf(\\n address _operator,\\n address _account,\\n uint256 _domain\\n ) external view returns (uint256);\\n\\n function hasPermission(\\n address _operator,\\n address _account,\\n uint256 _domain,\\n uint256 _permissionIndex\\n ) external view returns (bool);\\n\\n function hasPermissions(\\n address _operator,\\n address _account,\\n uint256 _domain,\\n uint256[] calldata _permissionIndexes\\n ) external view returns (bool);\\n\\n function setOperator(JBOperatorData calldata _operatorData) external;\\n\\n function setOperators(JBOperatorData[] calldata _operatorData) external;\\n}\\n\",\"keccak256\":\"0x17f4929812a356984795fafed8cb2be816a025c9a0771d85595ac0b5ff3cffc5\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPayDelegate.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBDidPayData.sol';\\n\\n/**\\n @title\\n Pay delegate\\n\\n @notice\\n Delegate called after JBTerminal.pay(..) logic completion (if passed by the funding cycle datasource)\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n*/\\ninterface IJBPayDelegate is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.pay(..), after the execution of its logic\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control\\n \\n @param _data the data passed by the terminal, as a JBDidPayData struct:\\n address payer;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n JBTokenAmount amount;\\n JBTokenAmount forwardedAmount;\\n uint256 projectTokenCount;\\n address beneficiary;\\n bool preferClaimedTokens;\\n string memo;\\n bytes metadata;\\n */\\n function didPay(JBDidPayData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0xa797de18b69eceba117e1f0b3810cf3cc2d2791417d580a5bdc510d1b868ab26\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\n\\ninterface IJBPaymentTerminal is IERC165 {\\n function acceptsToken(address _token, uint256 _projectId) external view returns (bool);\\n\\n function currencyForToken(address _token) external view returns (uint256);\\n\\n function decimalsForToken(address _token) external view returns (uint256);\\n\\n // Return value must be a fixed point number with 18 decimals.\\n function currentEthOverflowOf(uint256 _projectId) external view returns (uint256);\\n\\n function pay(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable returns (uint256 beneficiaryTokenCount);\\n\\n function addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable;\\n}\\n\",\"keccak256\":\"0xb7826f5ed609359ce322c09e83236c47ba385df1c3cad3607e56fd0a2e00eee2\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPayoutRedemptionPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBFee.sol';\\nimport './IJBAllowanceTerminal.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFeeGauge.sol';\\nimport './IJBPayDelegate.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBPayoutTerminal.sol';\\nimport './IJBPrices.sol';\\nimport './IJBProjects.sol';\\nimport './IJBRedemptionDelegate.sol';\\nimport './IJBRedemptionTerminal.sol';\\nimport './IJBSingleTokenPaymentTerminalStore.sol';\\nimport './IJBSplitsStore.sol';\\n\\ninterface IJBPayoutRedemptionPaymentTerminal is\\n IJBPaymentTerminal,\\n IJBPayoutTerminal,\\n IJBAllowanceTerminal,\\n IJBRedemptionTerminal\\n{\\n event AddToBalance(\\n uint256 indexed projectId,\\n uint256 amount,\\n uint256 refundedFees,\\n string memo,\\n bytes metadata,\\n address caller\\n );\\n\\n event Migrate(\\n uint256 indexed projectId,\\n IJBPaymentTerminal indexed to,\\n uint256 amount,\\n address caller\\n );\\n\\n event DistributePayouts(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address beneficiary,\\n uint256 amount,\\n uint256 distributedAmount,\\n uint256 fee,\\n uint256 beneficiaryDistributionAmount,\\n string memo,\\n address caller\\n );\\n\\n event UseAllowance(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address beneficiary,\\n uint256 amount,\\n uint256 distributedAmount,\\n uint256 netDistributedamount,\\n string memo,\\n address caller\\n );\\n\\n event HoldFee(\\n uint256 indexed projectId,\\n uint256 indexed amount,\\n uint256 indexed fee,\\n uint256 feeDiscount,\\n address beneficiary,\\n address caller\\n );\\n\\n event ProcessFee(\\n uint256 indexed projectId,\\n uint256 indexed amount,\\n bool indexed wasHeld,\\n address beneficiary,\\n address caller\\n );\\n\\n event RefundHeldFees(\\n uint256 indexed projectId,\\n uint256 indexed amount,\\n uint256 indexed refundedFees,\\n uint256 leftoverAmount,\\n address caller\\n );\\n\\n event Pay(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address payer,\\n address beneficiary,\\n uint256 amount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n bytes metadata,\\n address caller\\n );\\n\\n event DelegateDidPay(\\n IJBPayDelegate indexed delegate,\\n JBDidPayData data,\\n uint256 delegatedAmount,\\n address caller\\n );\\n\\n event RedeemTokens(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address holder,\\n address beneficiary,\\n uint256 tokenCount,\\n uint256 reclaimedAmount,\\n string memo,\\n bytes metadata,\\n address caller\\n );\\n\\n event DelegateDidRedeem(\\n IJBRedemptionDelegate indexed delegate,\\n JBDidRedeemData data,\\n uint256 delegatedAmount,\\n address caller\\n );\\n\\n event DistributeToPayoutSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n uint256 amount,\\n address caller\\n );\\n\\n event SetFee(uint256 fee, address caller);\\n\\n event SetFeeGauge(IJBFeeGauge indexed feeGauge, address caller);\\n\\n event SetFeelessAddress(address indexed addrs, bool indexed flag, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function splitsStore() external view returns (IJBSplitsStore);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function prices() external view returns (IJBPrices);\\n\\n function store() external view returns (IJBSingleTokenPaymentTerminalStore);\\n\\n function baseWeightCurrency() external view returns (uint256);\\n\\n function payoutSplitsGroup() external view returns (uint256);\\n\\n function heldFeesOf(uint256 _projectId) external view returns (JBFee[] memory);\\n\\n function fee() external view returns (uint256);\\n\\n function feeGauge() external view returns (IJBFeeGauge);\\n\\n function isFeelessAddress(address _contract) external view returns (bool);\\n\\n function migrate(uint256 _projectId, IJBPaymentTerminal _to) external returns (uint256 balance);\\n\\n function processFees(uint256 _projectId) external;\\n\\n function setFee(uint256 _fee) external;\\n\\n function setFeeGauge(IJBFeeGauge _feeGauge) external;\\n\\n function setFeelessAddress(address _contract, bool _flag) external;\\n}\\n\",\"keccak256\":\"0x5cd280eda38ee2d6e50604576e9260a788bf89b55dd7801a3ed1e8f876920450\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPayoutTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBPayoutTerminal {\\n function distributePayoutsOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n address _token,\\n uint256 _minReturnedTokens,\\n string calldata _memo\\n ) external returns (uint256 netLeftoverDistributionAmount);\\n}\\n\",\"keccak256\":\"0xbb556a74e4f82e9d65c3d1c40120bc57487440844b7bcf8c66935748aeab2dbd\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPriceFeed.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBPriceFeed {\\n function currentPrice(uint256 _targetDecimals) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x57c71282fec1b34b00cf991ffed2e36031c393e35bfa7ca5d723eb6572fb7122\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPrices.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBPriceFeed.sol';\\n\\ninterface IJBPrices {\\n event AddFeed(uint256 indexed currency, uint256 indexed base, IJBPriceFeed feed);\\n\\n function feedFor(uint256 _currency, uint256 _base) external view returns (IJBPriceFeed);\\n\\n function priceFor(\\n uint256 _currency,\\n uint256 _base,\\n uint256 _decimals\\n ) external view returns (uint256);\\n\\n function addFeedFor(\\n uint256 _currency,\\n uint256 _base,\\n IJBPriceFeed _priceFeed\\n ) external;\\n}\\n\",\"keccak256\":\"0x82a175b1f4b95b506c98406576cd59cbe04615e3df24f9cf3587b61b8ee323b1\",\"license\":\"MIT\"},\"contracts/interfaces/IJBProjects.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBTokenUriResolver.sol';\\n\\ninterface IJBProjects is IERC721 {\\n event Create(\\n uint256 indexed projectId,\\n address indexed owner,\\n JBProjectMetadata metadata,\\n address caller\\n );\\n\\n event SetMetadata(uint256 indexed projectId, JBProjectMetadata metadata, address caller);\\n\\n event SetTokenUriResolver(IJBTokenUriResolver indexed resolver, address caller);\\n\\n function count() external view returns (uint256);\\n\\n function metadataContentOf(uint256 _projectId, uint256 _domain)\\n external\\n view\\n returns (string memory);\\n\\n function tokenUriResolver() external view returns (IJBTokenUriResolver);\\n\\n function createFor(address _owner, JBProjectMetadata calldata _metadata)\\n external\\n returns (uint256 projectId);\\n\\n function setMetadataOf(uint256 _projectId, JBProjectMetadata calldata _metadata) external;\\n\\n function setTokenUriResolver(IJBTokenUriResolver _newResolver) external;\\n}\\n\",\"keccak256\":\"0x7cfc021d0bd7e73b1ba8f4845d7d35e3419d6a14d3d25ca3a8010e7f91062fe4\",\"license\":\"MIT\"},\"contracts/interfaces/IJBRedemptionDelegate.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBDidRedeemData.sol';\\n\\n/**\\n @title\\n Redemption delegate\\n\\n @notice\\n Delegate called after JBTerminal.redeemTokensOf(..) logic completion (if passed by the funding cycle datasource)\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n*/\\ninterface IJBRedemptionDelegate is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.redeemTokensOf(..), after the execution of its logic\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control\\n \\n @param _data the data passed by the terminal, as a JBDidRedeemData struct:\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 projectTokenCount;\\n JBTokenAmount reclaimedAmount;\\n JBTokenAmount forwardedAmount;\\n address payable beneficiary;\\n string memo;\\n bytes metadata;\\n */\\n function didRedeem(JBDidRedeemData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0x172d2c0be65e72e54f71ae521907067f0fa30e8ca05c4f88826903208aa437e2\",\"license\":\"MIT\"},\"contracts/interfaces/IJBRedemptionTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBRedemptionTerminal {\\n function redeemTokensOf(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n address _token,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external returns (uint256 reclaimAmount);\\n}\\n\",\"keccak256\":\"0xe26a6a03468401b802ae5328b39a266f53b9331a1c077fcbf7719d10ba74ff44\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSingleTokenPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBPaymentTerminal.sol';\\n\\ninterface IJBSingleTokenPaymentTerminal is IJBPaymentTerminal {\\n function token() external view returns (address);\\n\\n function currency() external view returns (uint256);\\n\\n function decimals() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xf6e78323caa9af7bbf024f44b2032a83fed0394e0b3a242a6346e73c85b2e46f\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSingleTokenPaymentTerminalStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBPayDelegateAllocation.sol';\\nimport './../structs/JBRedemptionDelegateAllocation.sol';\\nimport './../structs/JBTokenAmount.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBPrices.sol';\\nimport './IJBSingleTokenPaymentTerminal.sol';\\n\\ninterface IJBSingleTokenPaymentTerminalStore {\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function prices() external view returns (IJBPrices);\\n\\n function balanceOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\\n external\\n view\\n returns (uint256);\\n\\n function usedDistributionLimitOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _fundingCycleNumber\\n ) external view returns (uint256);\\n\\n function usedOverflowAllowanceOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _fundingCycleConfiguration\\n ) external view returns (uint256);\\n\\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\\n external\\n view\\n returns (uint256);\\n\\n function currentTotalOverflowOf(\\n uint256 _projectId,\\n uint256 _decimals,\\n uint256 _currency\\n ) external view returns (uint256);\\n\\n function currentReclaimableOverflowOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n bool _useTotalOverflow\\n ) external view returns (uint256);\\n\\n function currentReclaimableOverflowOf(\\n uint256 _projectId,\\n uint256 _tokenCount,\\n uint256 _totalSupply,\\n uint256 _overflow\\n ) external view returns (uint256);\\n\\n function recordPaymentFrom(\\n address _payer,\\n JBTokenAmount memory _amount,\\n uint256 _projectId,\\n uint256 _baseWeightCurrency,\\n address _beneficiary,\\n string calldata _memo,\\n bytes calldata _metadata\\n )\\n external\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 tokenCount,\\n JBPayDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n );\\n\\n function recordRedemptionFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n string calldata _memo,\\n bytes calldata _metadata\\n )\\n external\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 reclaimAmount,\\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n );\\n\\n function recordDistributionFor(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n ) external returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount);\\n\\n function recordUsedAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n ) external returns (JBFundingCycle memory fundingCycle, uint256 withdrawnAmount);\\n\\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external;\\n\\n function recordMigration(uint256 _projectId) external returns (uint256 balance);\\n}\\n\",\"keccak256\":\"0xd78929c9371fd7895b829ef5e4ad4b3786523c3580ac3f6f5f25d2b5941c0dd3\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSplitAllocator.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport '../structs/JBSplitAllocationData.sol';\\n\\n/**\\n @title\\n Split allocator\\n\\n @notice\\n Provide a way to process a single split with extra logic\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n\\n @dev\\n The contract address should be set as an allocator in the adequate split\\n*/\\ninterface IJBSplitAllocator is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.distributePayoutOf(..), during the processing of the split including it\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control. The token and/or eth are optimistically transfered\\n to the allocator for its logic.\\n \\n @param _data the data passed by the terminal, as a JBSplitAllocationData struct:\\n address token;\\n uint256 amount;\\n uint256 decimals;\\n uint256 projectId;\\n uint256 group;\\n JBSplit split;\\n */\\n function allocate(JBSplitAllocationData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0x5efb6f51fc161f42ff58989386ad99028e4039a0ba897d66f358c3dfcf686105\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSplitsStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBGroupedSplits.sol';\\nimport './../structs/JBSplit.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBProjects.sol';\\n\\ninterface IJBSplitsStore {\\n event SetSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n address caller\\n );\\n\\n function projects() external view returns (IJBProjects);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function splitsOf(\\n uint256 _projectId,\\n uint256 _domain,\\n uint256 _group\\n ) external view returns (JBSplit[] memory);\\n\\n function set(\\n uint256 _projectId,\\n uint256 _domain,\\n JBGroupedSplits[] memory _groupedSplits\\n ) external;\\n}\\n\",\"keccak256\":\"0x66dab3dd394e318b850401ca92c2963b906cc0ad5562fa5d4f6f850175d1c77a\",\"license\":\"MIT\"},\"contracts/interfaces/IJBToken.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBToken {\\n function projectId() external view returns (uint256);\\n\\n function decimals() external view returns (uint8);\\n\\n function totalSupply(uint256 _projectId) external view returns (uint256);\\n\\n function balanceOf(address _account, uint256 _projectId) external view returns (uint256);\\n\\n function mint(\\n uint256 _projectId,\\n address _account,\\n uint256 _amount\\n ) external;\\n\\n function burn(\\n uint256 _projectId,\\n address _account,\\n uint256 _amount\\n ) external;\\n\\n function approve(\\n uint256,\\n address _spender,\\n uint256 _amount\\n ) external;\\n\\n function transfer(\\n uint256 _projectId,\\n address _to,\\n uint256 _amount\\n ) external;\\n\\n function transferFrom(\\n uint256 _projectId,\\n address _from,\\n address _to,\\n uint256 _amount\\n ) external;\\n}\\n\",\"keccak256\":\"0xe8969210417736c85d71101bf1c0bd8ebbf9d1e62a93e758148bd5709a6c7097\",\"license\":\"MIT\"},\"contracts/interfaces/IJBTokenStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBProjects.sol';\\nimport './IJBToken.sol';\\n\\ninterface IJBTokenStore {\\n event Issue(\\n uint256 indexed projectId,\\n IJBToken indexed token,\\n string name,\\n string symbol,\\n address caller\\n );\\n\\n event Mint(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 amount,\\n bool tokensWereClaimed,\\n bool preferClaimedTokens,\\n address caller\\n );\\n\\n event Burn(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 amount,\\n uint256 initialUnclaimedBalance,\\n uint256 initialClaimedBalance,\\n bool preferClaimedTokens,\\n address caller\\n );\\n\\n event Claim(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 initialUnclaimedBalance,\\n uint256 amount,\\n address caller\\n );\\n\\n event Set(uint256 indexed projectId, IJBToken indexed newToken, address caller);\\n\\n event Transfer(\\n address indexed holder,\\n uint256 indexed projectId,\\n address indexed recipient,\\n uint256 amount,\\n address caller\\n );\\n\\n function tokenOf(uint256 _projectId) external view returns (IJBToken);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function unclaimedBalanceOf(address _holder, uint256 _projectId) external view returns (uint256);\\n\\n function unclaimedTotalSupplyOf(uint256 _projectId) external view returns (uint256);\\n\\n function totalSupplyOf(uint256 _projectId) external view returns (uint256);\\n\\n function balanceOf(address _holder, uint256 _projectId) external view returns (uint256 _result);\\n\\n function issueFor(\\n uint256 _projectId,\\n string calldata _name,\\n string calldata _symbol\\n ) external returns (IJBToken token);\\n\\n function setFor(uint256 _projectId, IJBToken _token) external;\\n\\n function burnFrom(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function mintFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function claimFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount\\n ) external;\\n\\n function transferFrom(\\n address _holder,\\n uint256 _projectId,\\n address _recipient,\\n uint256 _amount\\n ) external;\\n}\\n\",\"keccak256\":\"0x98459e3af050d41dfeffdc97f1c93330207ba450f8ff3613224b49a89eeca9c6\",\"license\":\"MIT\"},\"contracts/interfaces/IJBTokenUriResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBTokenUriResolver {\\n function getUri(uint256 _projectId) external view returns (string memory tokenUri);\\n}\\n\",\"keccak256\":\"0xd267fd8ca7c21c2c71794acdb9a98314c33a35fc559e0bf0897a6686d196d174\",\"license\":\"MIT\"},\"contracts/libraries/JBConstants.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/**\\n @notice\\n Global constants used across Juicebox contracts.\\n*/\\nlibrary JBConstants {\\n uint256 public constant MAX_RESERVED_RATE = 10_000;\\n uint256 public constant MAX_REDEMPTION_RATE = 10_000;\\n uint256 public constant MAX_DISCOUNT_RATE = 1_000_000_000;\\n uint256 public constant SPLITS_TOTAL_PERCENT = 1_000_000_000;\\n uint256 public constant MAX_FEE = 1_000_000_000;\\n uint256 public constant MAX_FEE_DISCOUNT = 1_000_000_000;\\n}\\n\",\"keccak256\":\"0x34362846a1cd428a8bdedf4ab6857e11402f345cb87b994b2e7fb6d2474b808d\",\"license\":\"MIT\"},\"contracts/libraries/JBCurrencies.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBCurrencies {\\n uint256 public constant ETH = 1;\\n uint256 public constant USD = 2;\\n}\\n\",\"keccak256\":\"0x7e417ff25c173608ee4fe6d9fc3dcd5e1458c78c889af12bac47b1189a436076\",\"license\":\"MIT\"},\"contracts/libraries/JBFixedPointNumber.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nlibrary JBFixedPointNumber {\\n function adjustDecimals(\\n uint256 _value,\\n uint256 _decimals,\\n uint256 _targetDecimals\\n ) internal pure returns (uint256) {\\n // If decimals need adjusting, multiply or divide the price by the decimal adjuster to get the normalized result.\\n if (_targetDecimals == _decimals) return _value;\\n else if (_targetDecimals > _decimals) return _value * 10**(_targetDecimals - _decimals);\\n else return _value / 10**(_decimals - _targetDecimals);\\n }\\n}\\n\",\"keccak256\":\"0x18efac48269f3a3bd7e9a1c770776f950e0afa86769e6f8b128002c3b8c6742c\",\"license\":\"MIT\"},\"contracts/libraries/JBFundingCycleMetadataResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBFundingCycleMetadata.sol';\\nimport './../structs/JBGlobalFundingCycleMetadata.sol';\\nimport './JBConstants.sol';\\nimport './JBGlobalFundingCycleMetadataResolver.sol';\\n\\nlibrary JBFundingCycleMetadataResolver {\\n function global(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (JBGlobalFundingCycleMetadata memory)\\n {\\n return JBGlobalFundingCycleMetadataResolver.expandMetadata(uint8(_fundingCycle.metadata >> 8));\\n }\\n\\n function reservedRate(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n return uint256(uint16(_fundingCycle.metadata >> 24));\\n }\\n\\n function redemptionRate(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n // Redemption rate is a number 0-10000. It's inverse was stored so the most common case of 100% results in no storage needs.\\n return JBConstants.MAX_REDEMPTION_RATE - uint256(uint16(_fundingCycle.metadata >> 40));\\n }\\n\\n function ballotRedemptionRate(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (uint256)\\n {\\n // Redemption rate is a number 0-10000. It's inverse was stored so the most common case of 100% results in no storage needs.\\n return JBConstants.MAX_REDEMPTION_RATE - uint256(uint16(_fundingCycle.metadata >> 56));\\n }\\n\\n function payPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 72) & 1) == 1;\\n }\\n\\n function distributionsPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 73) & 1) == 1;\\n }\\n\\n function redeemPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 74) & 1) == 1;\\n }\\n\\n function burnPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 75) & 1) == 1;\\n }\\n\\n function mintingAllowed(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 76) & 1) == 1;\\n }\\n\\n function terminalMigrationAllowed(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 77) & 1) == 1;\\n }\\n\\n function controllerMigrationAllowed(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 78) & 1) == 1;\\n }\\n\\n function shouldHoldFees(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 79) & 1) == 1;\\n }\\n\\n function preferClaimedTokenOverride(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 80) & 1) == 1;\\n }\\n\\n function useTotalOverflowForRedemptions(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 81) & 1) == 1;\\n }\\n\\n function useDataSourceForPay(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return (_fundingCycle.metadata >> 82) & 1 == 1;\\n }\\n\\n function useDataSourceForRedeem(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return (_fundingCycle.metadata >> 83) & 1 == 1;\\n }\\n\\n function dataSource(JBFundingCycle memory _fundingCycle) internal pure returns (address) {\\n return address(uint160(_fundingCycle.metadata >> 84));\\n }\\n\\n function metadata(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n return uint256(uint8(_fundingCycle.metadata >> 244));\\n }\\n\\n /**\\n @notice\\n Pack the funding cycle metadata.\\n\\n @param _metadata The metadata to validate and pack.\\n\\n @return packed The packed uint256 of all metadata params. The first 8 bits specify the version.\\n */\\n function packFundingCycleMetadata(JBFundingCycleMetadata memory _metadata)\\n internal\\n pure\\n returns (uint256 packed)\\n {\\n // version 1 in the bits 0-7 (8 bits).\\n packed = 1;\\n // global metadta in bits 8-23 (16 bits).\\n packed |=\\n JBGlobalFundingCycleMetadataResolver.packFundingCycleGlobalMetadata(_metadata.global) <<\\n 8;\\n // reserved rate in bits 24-39 (16 bits).\\n packed |= _metadata.reservedRate << 24;\\n // redemption rate in bits 40-55 (16 bits).\\n // redemption rate is a number 0-10000. Store the reverse so the most common case of 100% results in no storage needs.\\n packed |= (JBConstants.MAX_REDEMPTION_RATE - _metadata.redemptionRate) << 40;\\n // ballot redemption rate rate in bits 56-71 (16 bits).\\n // ballot redemption rate is a number 0-10000. Store the reverse so the most common case of 100% results in no storage needs.\\n packed |= (JBConstants.MAX_REDEMPTION_RATE - _metadata.ballotRedemptionRate) << 56;\\n // pause pay in bit 72.\\n if (_metadata.pausePay) packed |= 1 << 72;\\n // pause tap in bit 73.\\n if (_metadata.pauseDistributions) packed |= 1 << 73;\\n // pause redeem in bit 74.\\n if (_metadata.pauseRedeem) packed |= 1 << 74;\\n // pause burn in bit 75.\\n if (_metadata.pauseBurn) packed |= 1 << 75;\\n // allow minting in bit 76.\\n if (_metadata.allowMinting) packed |= 1 << 76;\\n // allow terminal migration in bit 77.\\n if (_metadata.allowTerminalMigration) packed |= 1 << 77;\\n // allow controller migration in bit 78.\\n if (_metadata.allowControllerMigration) packed |= 1 << 78;\\n // hold fees in bit 79.\\n if (_metadata.holdFees) packed |= 1 << 79;\\n // prefer claimed token override in bit 80.\\n if (_metadata.preferClaimedTokenOverride) packed |= 1 << 80;\\n // useTotalOverflowForRedemptions in bit 81.\\n if (_metadata.useTotalOverflowForRedemptions) packed |= 1 << 81;\\n // use pay data source in bit 82.\\n if (_metadata.useDataSourceForPay) packed |= 1 << 82;\\n // use redeem data source in bit 83.\\n if (_metadata.useDataSourceForRedeem) packed |= 1 << 83;\\n // data source address in bits 84-243.\\n packed |= uint256(uint160(address(_metadata.dataSource))) << 84;\\n // metadata in bits 244-252 (8 bits).\\n packed |= _metadata.metadata << 244;\\n }\\n\\n /**\\n @notice\\n Expand the funding cycle metadata.\\n\\n @param _fundingCycle The funding cycle having its metadata expanded.\\n\\n @return metadata The metadata object.\\n */\\n function expandMetadata(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (JBFundingCycleMetadata memory)\\n {\\n return\\n JBFundingCycleMetadata(\\n global(_fundingCycle),\\n reservedRate(_fundingCycle),\\n redemptionRate(_fundingCycle),\\n ballotRedemptionRate(_fundingCycle),\\n payPaused(_fundingCycle),\\n distributionsPaused(_fundingCycle),\\n redeemPaused(_fundingCycle),\\n burnPaused(_fundingCycle),\\n mintingAllowed(_fundingCycle),\\n terminalMigrationAllowed(_fundingCycle),\\n controllerMigrationAllowed(_fundingCycle),\\n shouldHoldFees(_fundingCycle),\\n preferClaimedTokenOverride(_fundingCycle),\\n useTotalOverflowForRedemptions(_fundingCycle),\\n useDataSourceForPay(_fundingCycle),\\n useDataSourceForRedeem(_fundingCycle),\\n dataSource(_fundingCycle),\\n metadata(_fundingCycle)\\n );\\n }\\n}\\n\",\"keccak256\":\"0x3d045c38593102cfb6ac67f3ddf2232e1ff5518d6d021423ae2681387599fbd3\",\"license\":\"MIT\"},\"contracts/libraries/JBGlobalFundingCycleMetadataResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport './../structs/JBFundingCycleMetadata.sol';\\n\\nlibrary JBGlobalFundingCycleMetadataResolver {\\n function setTerminalsAllowed(uint8 _data) internal pure returns (bool) {\\n return (_data & 1) == 1;\\n }\\n\\n function setControllerAllowed(uint8 _data) internal pure returns (bool) {\\n return ((_data >> 1) & 1) == 1;\\n }\\n\\n function transfersPaused(uint8 _data) internal pure returns (bool) {\\n return ((_data >> 2) & 1) == 1;\\n }\\n\\n /**\\n @notice\\n Pack the global funding cycle metadata.\\n\\n @param _metadata The metadata to validate and pack.\\n\\n @return packed The packed uint256 of all global metadata params. The first 8 bits specify the version.\\n */\\n function packFundingCycleGlobalMetadata(JBGlobalFundingCycleMetadata memory _metadata)\\n internal\\n pure\\n returns (uint256 packed)\\n {\\n // allow set terminals in bit 0.\\n if (_metadata.allowSetTerminals) packed |= 1;\\n // allow set controller in bit 1.\\n if (_metadata.allowSetController) packed |= 1 << 1;\\n // pause transfers in bit 2.\\n if (_metadata.pauseTransfers) packed |= 1 << 2;\\n }\\n\\n /**\\n @notice\\n Expand the global funding cycle metadata.\\n\\n @param _packedMetadata The packed metadata to expand.\\n\\n @return metadata The global metadata object.\\n */\\n function expandMetadata(uint8 _packedMetadata)\\n internal\\n pure\\n returns (JBGlobalFundingCycleMetadata memory metadata)\\n {\\n return\\n JBGlobalFundingCycleMetadata(\\n setTerminalsAllowed(_packedMetadata),\\n setControllerAllowed(_packedMetadata),\\n transfersPaused(_packedMetadata)\\n );\\n }\\n}\\n\",\"keccak256\":\"0x0d998f938026edeb755987a79421267cf860801161b5f171206a200b60f1061f\",\"license\":\"MIT\"},\"contracts/libraries/JBOperations.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBOperations {\\n uint256 public constant RECONFIGURE = 1;\\n uint256 public constant REDEEM = 2;\\n uint256 public constant MIGRATE_CONTROLLER = 3;\\n uint256 public constant MIGRATE_TERMINAL = 4;\\n uint256 public constant PROCESS_FEES = 5;\\n uint256 public constant SET_METADATA = 6;\\n uint256 public constant ISSUE = 7;\\n uint256 public constant SET_TOKEN = 8;\\n uint256 public constant MINT = 9;\\n uint256 public constant BURN = 10;\\n uint256 public constant CLAIM = 11;\\n uint256 public constant TRANSFER = 12;\\n uint256 public constant REQUIRE_CLAIM = 13; // unused in v3\\n uint256 public constant SET_CONTROLLER = 14;\\n uint256 public constant SET_TERMINALS = 15;\\n uint256 public constant SET_PRIMARY_TERMINAL = 16;\\n uint256 public constant USE_ALLOWANCE = 17;\\n uint256 public constant SET_SPLITS = 18;\\n}\\n\",\"keccak256\":\"0x7f8e501e6890297f4015b1c27cebdb44fadbf21204bea1f3162f5388c060f690\",\"license\":\"MIT\"},\"contracts/libraries/JBSplitsGroups.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBSplitsGroups {\\n uint256 public constant ETH_PAYOUT = 1;\\n uint256 public constant RESERVED_TOKENS = 2;\\n}\\n\",\"keccak256\":\"0x4183db6087bd8db645fc3a0d3d8afb0d6356e003650793f63c301ebbbae47269\",\"license\":\"MIT\"},\"contracts/libraries/JBTokens.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBTokens {\\n /** \\n @notice \\n The ETH token address in Juicebox is represented by 0x000000000000000000000000000000000000EEEe.\\n */\\n address public constant ETH = address(0x000000000000000000000000000000000000EEEe);\\n}\\n\",\"keccak256\":\"0xecf82992f7b827766aa55f16872517a646521eef414d8cc9786617ea377e5463\",\"license\":\"MIT\"},\"contracts/structs/JBDidPayData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member payer The address from which the payment originated.\\n @member projectId The ID of the project for which the payment was made.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the payment is being made.\\n @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.\\n @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.\\n @member projectTokenCount The number of project tokens minted for the beneficiary.\\n @member beneficiary The address to which the tokens were minted.\\n @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.\\n @member memo The memo that is being emitted alongside the payment.\\n @member metadata Extra data to send to the delegate.\\n*/\\nstruct JBDidPayData {\\n address payer;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n JBTokenAmount amount;\\n JBTokenAmount forwardedAmount;\\n uint256 projectTokenCount;\\n address beneficiary;\\n bool preferClaimedTokens;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0xf3c664309b37790f16047ae97b0459889ae0242dfcde7fc8902c8d10c7f8e6b6\",\"license\":\"MIT\"},\"contracts/structs/JBDidRedeemData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member holder The holder of the tokens being redeemed.\\n @member projectId The ID of the project with which the redeemed tokens are associated.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the redemption is being made.\\n @member projectTokenCount The number of project tokens being redeemed.\\n @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.\\n @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.\\n @member beneficiary The address to which the reclaimed amount will be sent.\\n @member memo The memo that is being emitted alongside the redemption.\\n @member metadata Extra data to send to the delegate.\\n*/\\nstruct JBDidRedeemData {\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 projectTokenCount;\\n JBTokenAmount reclaimedAmount;\\n JBTokenAmount forwardedAmount;\\n address payable beneficiary;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0xe2c401f39723a7ce915b8bef328744c66daaf57460843964b941456c2258a412\",\"license\":\"MIT\"},\"contracts/structs/JBFee.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member amount The total amount the fee was taken from, as a fixed point number with the same number of decimals as the terminal in which this struct was created.\\n @member fee The percent of the fee, out of MAX_FEE.\\n @member feeDiscount The discount of the fee.\\n @member beneficiary The address that will receive the tokens that are minted as a result of the fee payment.\\n*/\\nstruct JBFee {\\n uint256 amount;\\n uint32 fee;\\n uint32 feeDiscount;\\n address beneficiary;\\n}\\n\",\"keccak256\":\"0xf4759ff41fe7f1db0fd1ccc7b2a326b239389fd8d69df9b9ed5e1d5926f6fe38\",\"license\":\"MIT\"},\"contracts/structs/JBFundAccessConstraints.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBPaymentTerminal.sol';\\n\\n/** \\n @member terminal The terminal within which the distribution limit and the overflow allowance applies.\\n @member token The token for which the fund access constraints apply.\\n @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.\\n @member distributionLimitCurrency The currency of the distribution limit.\\n @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.\\n @member overflowAllowanceCurrency The currency of the overflow allowance.\\n*/\\nstruct JBFundAccessConstraints {\\n IJBPaymentTerminal terminal;\\n address token;\\n uint256 distributionLimit;\\n uint256 distributionLimitCurrency;\\n uint256 overflowAllowance;\\n uint256 overflowAllowanceCurrency;\\n}\\n\",\"keccak256\":\"0x85ebaa57b788cbdedc7a3d0eec4892eda5d79db7c1a6103797f10d0d989775b2\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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.\\n @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.\\n @member basedOn The `configuration` of the funding cycle that was active when this cycle was created.\\n @member start The timestamp marking the moment from which the funding cycle is considered active. It is a unix timestamp measured in seconds.\\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n @member metadata Extra data that can be associated with a funding cycle.\\n*/\\nstruct JBFundingCycle {\\n uint256 number;\\n uint256 configuration;\\n uint256 basedOn;\\n uint256 start;\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n uint256 metadata;\\n}\\n\",\"keccak256\":\"0xcdd3ac9b6fa67e62ada88d09b73bc35ade1cd77d43db712289266a788928b4c2\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycleData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n*/\\nstruct JBFundingCycleData {\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n}\\n\",\"keccak256\":\"0x2aa6368bf4dfc5797e8b02a978293de0c777fae2658de2c825a103587240f3b0\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycleMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBGlobalFundingCycleMetadata.sol';\\n\\n/** \\n @member global Data used globally in non-migratable ecosystem contracts.\\n @member reservedRate The reserved rate of the funding cycle. This number is a percentage calculated out of `JBConstants.MAX_RESERVED_RATE`.\\n @member redemptionRate The redemption rate of the funding cycle. This number is a percentage calculated out of `JBConstants.MAX_REDEMPTION_RATE`.\\n @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`.\\n @member pausePay A flag indicating if the pay functionality should be paused during the funding cycle.\\n @member pauseDistributions A flag indicating if the distribute functionality should be paused during the funding cycle.\\n @member pauseRedeem A flag indicating if the redeem functionality should be paused during the funding cycle.\\n @member pauseBurn A flag indicating if the burn functionality should be paused during the funding cycle.\\n @member allowMinting A flag indicating if minting tokens should be allowed during this funding cycle.\\n @member allowTerminalMigration A flag indicating if migrating terminals should be allowed during this funding cycle.\\n @member allowControllerMigration A flag indicating if migrating controllers should be allowed during this funding cycle.\\n @member holdFees A flag indicating if fees should be held during this funding cycle.\\n @member preferClaimedTokenOverride A flag indicating if claimed tokens should always be prefered to unclaimed tokens when minting.\\n @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.\\n @member useDataSourceForPay A flag indicating if the data source should be used for pay transactions during this funding cycle.\\n @member useDataSourceForRedeem A flag indicating if the data source should be used for redeem transactions during this funding cycle.\\n @member dataSource The data source to use during this funding cycle.\\n @member metadata Metadata of the metadata, up to uint8 in size.\\n*/\\nstruct JBFundingCycleMetadata {\\n JBGlobalFundingCycleMetadata global;\\n uint256 reservedRate;\\n uint256 redemptionRate;\\n uint256 ballotRedemptionRate;\\n bool pausePay;\\n bool pauseDistributions;\\n bool pauseRedeem;\\n bool pauseBurn;\\n bool allowMinting;\\n bool allowTerminalMigration;\\n bool allowControllerMigration;\\n bool holdFees;\\n bool preferClaimedTokenOverride;\\n bool useTotalOverflowForRedemptions;\\n bool useDataSourceForPay;\\n bool useDataSourceForRedeem;\\n address dataSource;\\n uint256 metadata;\\n}\\n\",\"keccak256\":\"0x783604440cac8d176332eab28166f188ee5c230378c08cfc95fea4f7187dc77d\",\"license\":\"MIT\"},\"contracts/structs/JBGlobalFundingCycleMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member allowSetTerminals A flag indicating if setting terminals should be allowed during this funding cycle.\\n @member allowSetController A flag indicating if setting a new controller should be allowed during this funding cycle.\\n @member pauseTransfers A flag indicating if the project token transfer functionality should be paused during the funding cycle.\\n*/\\nstruct JBGlobalFundingCycleMetadata {\\n bool allowSetTerminals;\\n bool allowSetController;\\n bool pauseTransfers;\\n}\\n\",\"keccak256\":\"0x05d85530305fec6d6eca54cdbc2cd9110cbda0146598032b0203aa4b622944ff\",\"license\":\"MIT\"},\"contracts/structs/JBGroupedSplits.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBSplit.sol';\\n\\n/** \\n @member group The group indentifier.\\n @member splits The splits to associate with the group.\\n*/\\nstruct JBGroupedSplits {\\n uint256 group;\\n JBSplit[] splits;\\n}\\n\",\"keccak256\":\"0x80be1b220da4ac04851ea540ebb94c1ec2b0442ec5bd1e88fdf78a56becd8b5a\",\"license\":\"MIT\"},\"contracts/structs/JBOperatorData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member operator The address of the operator.\\n @member domain The domain within which the operator is being given permissions. A domain of 0 is a wildcard domain, which gives an operator access to all domains.\\n @member permissionIndexes The indexes of the permissions the operator is being given.\\n*/\\nstruct JBOperatorData {\\n address operator;\\n uint256 domain;\\n uint256[] permissionIndexes;\\n}\\n\",\"keccak256\":\"0x3b85be7b69515976ee10770776283911666aceca820b0cf4e201ea4dbffeb6f0\",\"license\":\"MIT\"},\"contracts/structs/JBPayDelegateAllocation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '../interfaces/IJBPayDelegate.sol';\\n\\n/** \\n @member delegate A delegate contract to use for subsequent calls.\\n @member amount The amount to send to the delegate.\\n*/\\nstruct JBPayDelegateAllocation {\\n IJBPayDelegate delegate;\\n uint256 amount;\\n}\\n\",\"keccak256\":\"0xb4e558dc62231d89e9b48998012577d22c3e52b58e23401f22d9096827f6ea0c\",\"license\":\"MIT\"},\"contracts/structs/JBProjectMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member content The metadata content.\\n @member domain The domain within which the metadata applies.\\n*/\\nstruct JBProjectMetadata {\\n string content;\\n uint256 domain;\\n}\\n\",\"keccak256\":\"0x90ad7b1014c0a9f945fe7a2efde9d5de41e40574fa27969070b1d2ff52033ea0\",\"license\":\"MIT\"},\"contracts/structs/JBRedemptionDelegateAllocation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '../interfaces/IJBRedemptionDelegate.sol';\\n\\n/** \\n @member delegate A delegate contract to use for subsequent calls.\\n @member amount The amount to send to the delegate.\\n*/\\nstruct JBRedemptionDelegateAllocation {\\n IJBRedemptionDelegate delegate;\\n uint256 amount;\\n}\\n\",\"keccak256\":\"0x10c29d33dd0d875a0d4692a2b9a9355c2ebf433cc06a9a60253d4366b60d4d31\",\"license\":\"MIT\"},\"contracts/structs/JBSplit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBSplitAllocator.sol';\\n\\n/** \\n @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.\\n @member preferAddToBalance A flag indicating if a distribution to a project should prefer triggering it's addToBalance function instead of its pay function.\\n @member percent The percent of the whole group that this split occupies. This number is out of `JBConstants.SPLITS_TOTAL_PERCENT`.\\n @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.\\n @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.\\n @member lockedUntil Specifies if the split should be unchangeable until the specified time, with the exception of extending the locked period.\\n @member allocator If an allocator is specified, funds will be sent to the allocator contract along with all properties of this split.\\n*/\\nstruct JBSplit {\\n bool preferClaimed;\\n bool preferAddToBalance;\\n uint256 percent;\\n uint256 projectId;\\n address payable beneficiary;\\n uint256 lockedUntil;\\n IJBSplitAllocator allocator;\\n}\\n\",\"keccak256\":\"0xc80a16606da8abf76d0f73abc38aee041e24f29342c1939018f70c286e89f105\",\"license\":\"MIT\"},\"contracts/structs/JBSplitAllocationData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBSplit.sol';\\n\\n/** \\n @member token The token being sent to the split allocator.\\n @member amount The amount being sent to the split allocator, as a fixed point number.\\n @member decimals The number of decimals in the amount.\\n @member projectId The project to which the split belongs.\\n @member group The group to which the split belongs.\\n @member split The split that caused the allocation.\\n*/\\nstruct JBSplitAllocationData {\\n address token;\\n uint256 amount;\\n uint256 decimals;\\n uint256 projectId;\\n uint256 group;\\n JBSplit split;\\n}\\n\",\"keccak256\":\"0x39f5c41bd31d36774744698ac94484b6cab62d7038df2f29d947668959782e63\",\"license\":\"MIT\"},\"contracts/structs/JBTokenAmount.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/* \\n @member token The token the payment was made in.\\n @member value The amount of tokens that was paid, as a fixed point number.\\n @member decimals The number of decimals included in the value fixed point number.\\n @member currency The expected currency of the value.\\n**/\\nstruct JBTokenAmount {\\n address token;\\n uint256 value;\\n uint256 decimals;\\n uint256 currency;\\n}\\n\",\"keccak256\":\"0x4a778e779ba257ba5638c5469e07a4d21b55a3128d56db5a0fdfacb1f3301c51\",\"license\":\"MIT\"},\"prb-math/contracts/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivFixedPointOverflow(uint256 prod1);\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivOverflow(uint256 prod1, uint256 denominator);\\n\\n/// @notice Emitted when one of the inputs is type(int256).min.\\nerror PRBMath__MulDivSignedInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows int256.\\nerror PRBMath__MulDivSignedOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is MIN_SD59x18.\\nerror PRBMathSD59x18__AbsInputTooSmall();\\n\\n/// @notice Emitted when ceiling a number overflows SD59x18.\\nerror PRBMathSD59x18__CeilOverflow(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__DivInputTooSmall();\\n\\n/// @notice Emitted when one of the intermediary unsigned results overflows SD59x18.\\nerror PRBMathSD59x18__DivOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathSD59x18__ExpInputTooBig(int256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathSD59x18__Exp2InputTooBig(int256 x);\\n\\n/// @notice Emitted when flooring a number underflows SD59x18.\\nerror PRBMathSD59x18__FloorUnderflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format overflows SD59x18.\\nerror PRBMathSD59x18__FromIntOverflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format underflows SD59x18.\\nerror PRBMathSD59x18__FromIntUnderflow(int256 x);\\n\\n/// @notice Emitted when the product of the inputs is negative.\\nerror PRBMathSD59x18__GmNegativeProduct(int256 x, int256 y);\\n\\n/// @notice Emitted when multiplying the inputs overflows SD59x18.\\nerror PRBMathSD59x18__GmOverflow(int256 x, int256 y);\\n\\n/// @notice Emitted when the input is less than or equal to zero.\\nerror PRBMathSD59x18__LogInputTooSmall(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__MulInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__MulOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__PowuOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is negative.\\nerror PRBMathSD59x18__SqrtNegativeInput(int256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows SD59x18.\\nerror PRBMathSD59x18__SqrtOverflow(int256 x);\\n\\n/// @notice Emitted when addition overflows UD60x18.\\nerror PRBMathUD60x18__AddOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when ceiling a number overflows UD60x18.\\nerror PRBMathUD60x18__CeilOverflow(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathUD60x18__ExpInputTooBig(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathUD60x18__Exp2InputTooBig(uint256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format format overflows UD60x18.\\nerror PRBMathUD60x18__FromUintOverflow(uint256 x);\\n\\n/// @notice Emitted when multiplying the inputs overflows UD60x18.\\nerror PRBMathUD60x18__GmOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when the input is less than 1.\\nerror PRBMathUD60x18__LogInputTooSmall(uint256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows UD60x18.\\nerror PRBMathUD60x18__SqrtOverflow(uint256 x);\\n\\n/// @notice Emitted when subtraction underflows UD60x18.\\nerror PRBMathUD60x18__SubUnderflow(uint256 x, uint256 y);\\n\\n/// @dev Common mathematical functions used in both PRBMathSD59x18 and PRBMathUD60x18. Note that this shared library\\n/// does not always assume the signed 59.18-decimal fixed-point or the unsigned 60.18-decimal fixed-point\\n/// representation. When it does not, it is explicitly mentioned in the NatSpec documentation.\\nlibrary PRBMath {\\n /// STRUCTS ///\\n\\n struct SD59x18 {\\n int256 value;\\n }\\n\\n struct UD60x18 {\\n uint256 value;\\n }\\n\\n /// STORAGE ///\\n\\n /// @dev How many trailing decimals can be represented.\\n uint256 internal constant SCALE = 1e18;\\n\\n /// @dev Largest power of two divisor of SCALE.\\n uint256 internal constant SCALE_LPOTD = 262144;\\n\\n /// @dev SCALE inverted mod 2^256.\\n uint256 internal constant SCALE_INVERSE =\\n 78156646155174841979727994598816262306175212592076161876661_508869554232690281;\\n\\n /// FUNCTIONS ///\\n\\n /// @notice Calculates the binary exponent of x using the binary fraction method.\\n /// @dev Has to use 192.64-bit fixed-point numbers.\\n /// See https://ethereum.stackexchange.com/a/96594/24693.\\n /// @param x The exponent as an unsigned 192.64-bit fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp2(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n // Start from 0.5 in the 192.64-bit fixed-point format.\\n result = 0x800000000000000000000000000000000000000000000000;\\n\\n // Multiply the result by root(2, 2^-i) when the bit at position i is 1. None of the intermediary results overflows\\n // because the initial result is 2^191 and all magic factors are less than 2^65.\\n if (x & 0x8000000000000000 > 0) {\\n result = (result * 0x16A09E667F3BCC909) >> 64;\\n }\\n if (x & 0x4000000000000000 > 0) {\\n result = (result * 0x1306FE0A31B7152DF) >> 64;\\n }\\n if (x & 0x2000000000000000 > 0) {\\n result = (result * 0x1172B83C7D517ADCE) >> 64;\\n }\\n if (x & 0x1000000000000000 > 0) {\\n result = (result * 0x10B5586CF9890F62A) >> 64;\\n }\\n if (x & 0x800000000000000 > 0) {\\n result = (result * 0x1059B0D31585743AE) >> 64;\\n }\\n if (x & 0x400000000000000 > 0) {\\n result = (result * 0x102C9A3E778060EE7) >> 64;\\n }\\n if (x & 0x200000000000000 > 0) {\\n result = (result * 0x10163DA9FB33356D8) >> 64;\\n }\\n if (x & 0x100000000000000 > 0) {\\n result = (result * 0x100B1AFA5ABCBED61) >> 64;\\n }\\n if (x & 0x80000000000000 > 0) {\\n result = (result * 0x10058C86DA1C09EA2) >> 64;\\n }\\n if (x & 0x40000000000000 > 0) {\\n result = (result * 0x1002C605E2E8CEC50) >> 64;\\n }\\n if (x & 0x20000000000000 > 0) {\\n result = (result * 0x100162F3904051FA1) >> 64;\\n }\\n if (x & 0x10000000000000 > 0) {\\n result = (result * 0x1000B175EFFDC76BA) >> 64;\\n }\\n if (x & 0x8000000000000 > 0) {\\n result = (result * 0x100058BA01FB9F96D) >> 64;\\n }\\n if (x & 0x4000000000000 > 0) {\\n result = (result * 0x10002C5CC37DA9492) >> 64;\\n }\\n if (x & 0x2000000000000 > 0) {\\n result = (result * 0x1000162E525EE0547) >> 64;\\n }\\n if (x & 0x1000000000000 > 0) {\\n result = (result * 0x10000B17255775C04) >> 64;\\n }\\n if (x & 0x800000000000 > 0) {\\n result = (result * 0x1000058B91B5BC9AE) >> 64;\\n }\\n if (x & 0x400000000000 > 0) {\\n result = (result * 0x100002C5C89D5EC6D) >> 64;\\n }\\n if (x & 0x200000000000 > 0) {\\n result = (result * 0x10000162E43F4F831) >> 64;\\n }\\n if (x & 0x100000000000 > 0) {\\n result = (result * 0x100000B1721BCFC9A) >> 64;\\n }\\n if (x & 0x80000000000 > 0) {\\n result = (result * 0x10000058B90CF1E6E) >> 64;\\n }\\n if (x & 0x40000000000 > 0) {\\n result = (result * 0x1000002C5C863B73F) >> 64;\\n }\\n if (x & 0x20000000000 > 0) {\\n result = (result * 0x100000162E430E5A2) >> 64;\\n }\\n if (x & 0x10000000000 > 0) {\\n result = (result * 0x1000000B172183551) >> 64;\\n }\\n if (x & 0x8000000000 > 0) {\\n result = (result * 0x100000058B90C0B49) >> 64;\\n }\\n if (x & 0x4000000000 > 0) {\\n result = (result * 0x10000002C5C8601CC) >> 64;\\n }\\n if (x & 0x2000000000 > 0) {\\n result = (result * 0x1000000162E42FFF0) >> 64;\\n }\\n if (x & 0x1000000000 > 0) {\\n result = (result * 0x10000000B17217FBB) >> 64;\\n }\\n if (x & 0x800000000 > 0) {\\n result = (result * 0x1000000058B90BFCE) >> 64;\\n }\\n if (x & 0x400000000 > 0) {\\n result = (result * 0x100000002C5C85FE3) >> 64;\\n }\\n if (x & 0x200000000 > 0) {\\n result = (result * 0x10000000162E42FF1) >> 64;\\n }\\n if (x & 0x100000000 > 0) {\\n result = (result * 0x100000000B17217F8) >> 64;\\n }\\n if (x & 0x80000000 > 0) {\\n result = (result * 0x10000000058B90BFC) >> 64;\\n }\\n if (x & 0x40000000 > 0) {\\n result = (result * 0x1000000002C5C85FE) >> 64;\\n }\\n if (x & 0x20000000 > 0) {\\n result = (result * 0x100000000162E42FF) >> 64;\\n }\\n if (x & 0x10000000 > 0) {\\n result = (result * 0x1000000000B17217F) >> 64;\\n }\\n if (x & 0x8000000 > 0) {\\n result = (result * 0x100000000058B90C0) >> 64;\\n }\\n if (x & 0x4000000 > 0) {\\n result = (result * 0x10000000002C5C860) >> 64;\\n }\\n if (x & 0x2000000 > 0) {\\n result = (result * 0x1000000000162E430) >> 64;\\n }\\n if (x & 0x1000000 > 0) {\\n result = (result * 0x10000000000B17218) >> 64;\\n }\\n if (x & 0x800000 > 0) {\\n result = (result * 0x1000000000058B90C) >> 64;\\n }\\n if (x & 0x400000 > 0) {\\n result = (result * 0x100000000002C5C86) >> 64;\\n }\\n if (x & 0x200000 > 0) {\\n result = (result * 0x10000000000162E43) >> 64;\\n }\\n if (x & 0x100000 > 0) {\\n result = (result * 0x100000000000B1721) >> 64;\\n }\\n if (x & 0x80000 > 0) {\\n result = (result * 0x10000000000058B91) >> 64;\\n }\\n if (x & 0x40000 > 0) {\\n result = (result * 0x1000000000002C5C8) >> 64;\\n }\\n if (x & 0x20000 > 0) {\\n result = (result * 0x100000000000162E4) >> 64;\\n }\\n if (x & 0x10000 > 0) {\\n result = (result * 0x1000000000000B172) >> 64;\\n }\\n if (x & 0x8000 > 0) {\\n result = (result * 0x100000000000058B9) >> 64;\\n }\\n if (x & 0x4000 > 0) {\\n result = (result * 0x10000000000002C5D) >> 64;\\n }\\n if (x & 0x2000 > 0) {\\n result = (result * 0x1000000000000162E) >> 64;\\n }\\n if (x & 0x1000 > 0) {\\n result = (result * 0x10000000000000B17) >> 64;\\n }\\n if (x & 0x800 > 0) {\\n result = (result * 0x1000000000000058C) >> 64;\\n }\\n if (x & 0x400 > 0) {\\n result = (result * 0x100000000000002C6) >> 64;\\n }\\n if (x & 0x200 > 0) {\\n result = (result * 0x10000000000000163) >> 64;\\n }\\n if (x & 0x100 > 0) {\\n result = (result * 0x100000000000000B1) >> 64;\\n }\\n if (x & 0x80 > 0) {\\n result = (result * 0x10000000000000059) >> 64;\\n }\\n if (x & 0x40 > 0) {\\n result = (result * 0x1000000000000002C) >> 64;\\n }\\n if (x & 0x20 > 0) {\\n result = (result * 0x10000000000000016) >> 64;\\n }\\n if (x & 0x10 > 0) {\\n result = (result * 0x1000000000000000B) >> 64;\\n }\\n if (x & 0x8 > 0) {\\n result = (result * 0x10000000000000006) >> 64;\\n }\\n if (x & 0x4 > 0) {\\n result = (result * 0x10000000000000003) >> 64;\\n }\\n if (x & 0x2 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n if (x & 0x1 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n\\n // We're doing two things at the same time:\\n //\\n // 1. Multiply the result by 2^n + 1, where \\\"2^n\\\" is the integer part and the one is added to account for\\n // the fact that we initially set the result to 0.5. This is accomplished by subtracting from 191\\n // rather than 192.\\n // 2. Convert the result to the unsigned 60.18-decimal fixed-point format.\\n //\\n // This works because 2^(191-ip) = 2^ip / 2^191, where \\\"ip\\\" is the integer part \\\"2^n\\\".\\n result *= SCALE;\\n result >>= (191 - (x >> 64));\\n }\\n }\\n\\n /// @notice Finds the zero-based index of the first one in the binary representation of x.\\n /// @dev See the note on msb in the \\\"Find First Set\\\" Wikipedia article https://en.wikipedia.org/wiki/Find_first_set\\n /// @param x The uint256 number for which to find the index of the most significant bit.\\n /// @return msb The index of the most significant bit as an uint256.\\n function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\\n if (x >= 2**128) {\\n x >>= 128;\\n msb += 128;\\n }\\n if (x >= 2**64) {\\n x >>= 64;\\n msb += 64;\\n }\\n if (x >= 2**32) {\\n x >>= 32;\\n msb += 32;\\n }\\n if (x >= 2**16) {\\n x >>= 16;\\n msb += 16;\\n }\\n if (x >= 2**8) {\\n x >>= 8;\\n msb += 8;\\n }\\n if (x >= 2**4) {\\n x >>= 4;\\n msb += 4;\\n }\\n if (x >= 2**2) {\\n x >>= 2;\\n msb += 2;\\n }\\n if (x >= 2**1) {\\n // No need to shift x any more.\\n msb += 1;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.\\n ///\\n /// Requirements:\\n /// - The denominator cannot be zero.\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The multiplicand as an uint256.\\n /// @param y The multiplier as an uint256.\\n /// @param denominator The divisor as an uint256.\\n /// @return result The result as an uint256.\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n unchecked {\\n result = prod0 / denominator;\\n }\\n return result;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n if (prod1 >= denominator) {\\n revert PRBMath__MulDivOverflow(prod1, denominator);\\n }\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n unchecked {\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 lpotdod = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by lpotdod.\\n denominator := div(denominator, lpotdod)\\n\\n // Divide [prod1 prod0] by lpotdod.\\n prod0 := div(prod0, lpotdod)\\n\\n // Flip lpotdod such that it is 2^256 / lpotdod. If lpotdod is zero, then it becomes one.\\n lpotdod := add(div(sub(0, lpotdod), lpotdod), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * lpotdod;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f71e18) with full precision.\\n ///\\n /// @dev Variant of \\\"mulDiv\\\" with constant folding, i.e. in which the denominator is always 1e18. Before returning the\\n /// final result, we add 1 if (x * y) % SCALE >= HALF_SCALE. Without this, 6.6e-19 would be truncated to 0 instead of\\n /// being rounded to 1e-18. See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717.\\n ///\\n /// Requirements:\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - The body is purposely left uncommented; see the NatSpec comments in \\\"PRBMath.mulDiv\\\" to understand how this works.\\n /// - It is assumed that the result can never be type(uint256).max when x and y solve the following two equations:\\n /// 1. x * y = type(uint256).max * SCALE\\n /// 2. (x * y) % SCALE >= SCALE / 2\\n ///\\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function mulDivFixedPoint(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n uint256 prod0;\\n uint256 prod1;\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n if (prod1 >= SCALE) {\\n revert PRBMath__MulDivFixedPointOverflow(prod1);\\n }\\n\\n uint256 remainder;\\n uint256 roundUpUnit;\\n assembly {\\n remainder := mulmod(x, y, SCALE)\\n roundUpUnit := gt(remainder, 499999999999999999)\\n }\\n\\n if (prod1 == 0) {\\n unchecked {\\n result = (prod0 / SCALE) + roundUpUnit;\\n return result;\\n }\\n }\\n\\n assembly {\\n result := add(\\n mul(\\n or(\\n div(sub(prod0, remainder), SCALE_LPOTD),\\n mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, SCALE_LPOTD), SCALE_LPOTD), 1))\\n ),\\n SCALE_INVERSE\\n ),\\n roundUpUnit\\n )\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev An extension of \\\"mulDiv\\\" for signed numbers. Works by computing the signs and the absolute values separately.\\n ///\\n /// Requirements:\\n /// - None of the inputs can be type(int256).min.\\n /// - The result must fit within int256.\\n ///\\n /// @param x The multiplicand as an int256.\\n /// @param y The multiplier as an int256.\\n /// @param denominator The divisor as an int256.\\n /// @return result The result as an int256.\\n function mulDivSigned(\\n int256 x,\\n int256 y,\\n int256 denominator\\n ) internal pure returns (int256 result) {\\n if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {\\n revert PRBMath__MulDivSignedInputTooSmall();\\n }\\n\\n // Get hold of the absolute values of x, y and the denominator.\\n uint256 ax;\\n uint256 ay;\\n uint256 ad;\\n unchecked {\\n ax = x < 0 ? uint256(-x) : uint256(x);\\n ay = y < 0 ? uint256(-y) : uint256(y);\\n ad = denominator < 0 ? uint256(-denominator) : uint256(denominator);\\n }\\n\\n // Compute the absolute value of (x*y)\\u00f7denominator. The result must fit within int256.\\n uint256 rAbs = mulDiv(ax, ay, ad);\\n if (rAbs > uint256(type(int256).max)) {\\n revert PRBMath__MulDivSignedOverflow(rAbs);\\n }\\n\\n // Get the signs of x, y and the denominator.\\n uint256 sx;\\n uint256 sy;\\n uint256 sd;\\n assembly {\\n sx := sgt(x, sub(0, 1))\\n sy := sgt(y, sub(0, 1))\\n sd := sgt(denominator, sub(0, 1))\\n }\\n\\n // XOR over sx, sy and sd. This is checking whether there are one or three negative signs in the inputs.\\n // If yes, the result should be negative.\\n result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs);\\n }\\n\\n /// @notice Calculates the square root of x, rounding down.\\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The uint256 number for which to calculate the square root.\\n /// @return result The result as an uint256.\\n function sqrt(uint256 x) internal pure returns (uint256 result) {\\n if (x == 0) {\\n return 0;\\n }\\n\\n // Set the initial guess to the closest power of two that is higher than x.\\n uint256 xAux = uint256(x);\\n result = 1;\\n if (xAux >= 0x100000000000000000000000000000000) {\\n xAux >>= 128;\\n result <<= 64;\\n }\\n if (xAux >= 0x10000000000000000) {\\n xAux >>= 64;\\n result <<= 32;\\n }\\n if (xAux >= 0x100000000) {\\n xAux >>= 32;\\n result <<= 16;\\n }\\n if (xAux >= 0x10000) {\\n xAux >>= 16;\\n result <<= 8;\\n }\\n if (xAux >= 0x100) {\\n xAux >>= 8;\\n result <<= 4;\\n }\\n if (xAux >= 0x10) {\\n xAux >>= 4;\\n result <<= 2;\\n }\\n if (xAux >= 0x8) {\\n result <<= 1;\\n }\\n\\n // The operations can never overflow because the result is max 2^127 when it enters this block.\\n unchecked {\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1; // Seven iterations should be enough\\n uint256 roundedDownResult = x / result;\\n return result >= roundedDownResult ? roundedDownResult : result;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x62cbabae4910e168e99b9c2c3e3b5c9c7ad5e7abd961dcc63b7ea3d83d8ea87e\",\"license\":\"Unlicense\"}},\"version\":1}", + "metadata": "{\"compiler\":{\"version\":\"0.8.16+commit.07a7930e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_baseWeightCurrency\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBOperatorStore\",\"name\":\"_operatorStore\",\"type\":\"address\"},{\"internalType\":\"contract IJBProjects\",\"name\":\"_projects\",\"type\":\"address\"},{\"internalType\":\"contract IJBDirectory\",\"name\":\"_directory\",\"type\":\"address\"},{\"internalType\":\"contract IJBSplitsStore\",\"name\":\"_splitsStore\",\"type\":\"address\"},{\"internalType\":\"contract IJBPrices\",\"name\":\"_prices\",\"type\":\"address\"},{\"internalType\":\"contract IJBSingleTokenPaymentTerminalStore\",\"name\":\"_store\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"FEE_TOO_HIGH\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INADEQUATE_DISTRIBUTION_AMOUNT\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INADEQUATE_RECLAIM_AMOUNT\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INADEQUATE_TOKEN_COUNT\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NO_MSG_VALUE_ALLOWED\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PAY_TO_ZERO_ADDRESS\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"prod1\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"denominator\",\"type\":\"uint256\"}],\"name\":\"PRBMath__MulDivOverflow\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PROJECT_TERMINAL_MISMATCH\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"REDEEM_TO_ZERO_ADDRESS\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TERMINAL_IN_SPLIT_ZERO_ADDRESS\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TERMINAL_TOKENS_INCOMPATIBLE\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UNAUTHORIZED\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"refundedFees\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AddToBalance\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IJBPayDelegate\",\"name\":\"delegate\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"currentFundingCycleConfiguration\",\"type\":\"uint256\"},{\"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\"},{\"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\":\"forwardedAmount\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"projectTokenCount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"preferClaimedTokens\",\"type\":\"bool\"},{\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"struct JBDidPayData\",\"name\":\"data\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"delegatedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"DelegateDidPay\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IJBRedemptionDelegate\",\"name\":\"delegate\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"currentFundingCycleConfiguration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"projectTokenCount\",\"type\":\"uint256\"},{\"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\":\"reclaimedAmount\",\"type\":\"tuple\"},{\"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\":\"forwardedAmount\",\"type\":\"tuple\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"struct JBDidRedeemData\",\"name\":\"data\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"delegatedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"DelegateDidRedeem\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleConfiguration\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleNumber\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"distributedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"beneficiaryDistributionAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"DistributePayouts\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"domain\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"group\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"preferClaimed\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"preferAddToBalance\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"percent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"lockedUntil\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBSplitAllocator\",\"name\":\"allocator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"struct JBSplit\",\"name\":\"split\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"DistributeToPayoutSplit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"feeDiscount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"HoldFee\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"contract IJBPaymentTerminal\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Migrate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleConfiguration\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleNumber\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"beneficiaryTokenCount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Pay\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"wasHeld\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"ProcessFee\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleConfiguration\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleNumber\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenCount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"reclaimedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"RedeemTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"refundedFees\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"leftoverAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"RefundHeldFees\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"SetFee\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IJBFeeGauge\",\"name\":\"feeGauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"SetFeeGauge\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"addrs\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"flag\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"SetFeelessAddress\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleConfiguration\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleNumber\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"distributedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"netDistributedamount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"UseAllowance\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"}],\"name\":\"acceptsToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"addToBalanceOf\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"baseWeightCurrency\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currency\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"currencyForToken\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"}],\"name\":\"currentEthOverflowOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"decimalsForToken\",\"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\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_currency\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_minReturnedTokens\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"}],\"name\":\"distributePayoutsOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"netLeftoverDistributionAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"feeGauge\",\"outputs\":[{\"internalType\":\"contract IJBFeeGauge\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"}],\"name\":\"heldFeesOf\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"fee\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"feeDiscount\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"internalType\":\"struct JBFee[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isFeelessAddress\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBPaymentTerminal\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"migrate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"operatorStore\",\"outputs\":[{\"internalType\":\"contract IJBOperatorStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_minReturnedTokens\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"_preferClaimedTokens\",\"type\":\"bool\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"pay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"payoutSplitsGroup\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"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\"}],\"name\":\"processFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"projects\",\"outputs\":[{\"internalType\":\"contract IJBProjects\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_holder\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_tokenCount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_minReturnedTokens\",\"type\":\"uint256\"},{\"internalType\":\"address payable\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"redeemTokensOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"reclaimAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_fee\",\"type\":\"uint256\"}],\"name\":\"setFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IJBFeeGauge\",\"name\":\"_feeGauge\",\"type\":\"address\"}],\"name\":\"setFeeGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_flag\",\"type\":\"bool\"}],\"name\":\"setFeelessAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"splitsStore\",\"outputs\":[{\"internalType\":\"contract IJBSplitsStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"store\",\"outputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminalStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_currency\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_minReturnedTokens\",\"type\":\"uint256\"},{\"internalType\":\"address payable\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"}],\"name\":\"useAllowanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"netDistributedAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Inherits from - JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\",\"kind\":\"dev\",\"methods\":{\"acceptsToken(address,uint256)\":{\"params\":{\"_projectId\":\"The project ID to check for token acceptance.\",\"_token\":\"The token to check if this terminal accepts or not.\"},\"returns\":{\"_0\":\"The flag.\"}},\"addToBalanceOf(uint256,uint256,address,string,bytes)\":{\"params\":{\"_amount\":\"The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\",\"_memo\":\"A memo to pass along to the emitted event.\",\"_metadata\":\"Extra data to pass along to the emitted event.\",\"_projectId\":\"The ID of the project to which the funds received belong.\",\"_token\":\"The token being paid. This terminal ignores this property since it only manages one currency. \"}},\"constructor\":{\"params\":{\"_baseWeightCurrency\":\"The currency to base token issuance on.\",\"_directory\":\"A contract storing directories of terminals and controllers for each project.\",\"_operatorStore\":\"A contract storing operator assignments.\",\"_owner\":\"The address that will own this contract.\",\"_prices\":\"A contract that exposes price feeds.\",\"_projects\":\"A contract which mints ERC-721's that represent project ownership and transfers.\",\"_splitsStore\":\"A contract that stores splits for each project.\",\"_store\":\"A contract that stores the terminal's data.\"}},\"currencyForToken(address)\":{\"params\":{\"_token\":\"The token to check for the currency of.\"},\"returns\":{\"_0\":\"The currency index.\"}},\"currentEthOverflowOf(uint256)\":{\"details\":\"The current overflow is represented as a fixed point number with 18 decimals.\",\"params\":{\"_projectId\":\"The ID of the project to get overflow for.\"},\"returns\":{\"_0\":\"The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\"}},\"decimalsForToken(address)\":{\"params\":{\"_token\":\"The token to check for the decimals of.\"},\"returns\":{\"_0\":\"The number of decimals for the token.\"}},\"distributePayoutsOf(uint256,uint256,uint256,address,uint256,string)\":{\"details\":\"Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\",\"params\":{\"_amount\":\"The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\",\"_currency\":\"The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\",\"_memo\":\"A memo to pass along to the emitted event.\",\"_minReturnedTokens\":\"The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\",\"_projectId\":\"The ID of the project having its payouts distributed.\",\"_token\":\"The token being distributed. This terminal ignores this property since it only manages one token. \"},\"returns\":{\"netLeftoverDistributionAmount\":\"The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\"}},\"heldFeesOf(uint256)\":{\"params\":{\"_projectId\":\"The ID of the project for which fees are being held.\"},\"returns\":{\"_0\":\"An array of fees that are being held.\"}},\"migrate(uint256,address)\":{\"details\":\"Only a project's owner or a designated operator can migrate it.\",\"params\":{\"_projectId\":\"The ID of the project being migrated.\",\"_to\":\"The terminal contract that will gain the project's funds.\"},\"returns\":{\"balance\":\"The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pay(uint256,uint256,address,address,uint256,bool,string,bytes)\":{\"params\":{\"_amount\":\"The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\",\"_beneficiary\":\"The address to mint tokens for and pass along to the funding cycle's data source and delegate.\",\"_memo\":\"A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\",\"_metadata\":\"Bytes to send along to the data source, delegate, and emitted event, if provided.\",\"_minReturnedTokens\":\"The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\",\"_preferClaimedTokens\":\"A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\",\"_projectId\":\"The ID of the project being paid.\",\"_token\":\"The token being paid. This terminal ignores this property since it only manages one token. \"},\"returns\":{\"_0\":\"The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\"}},\"processFees(uint256)\":{\"details\":\"Only a project owner, an operator, or the contract's owner can process held fees.\",\"params\":{\"_projectId\":\"The ID of the project whos held fees should be processed.\"}},\"redeemTokensOf(address,uint256,uint256,address,uint256,address,string,bytes)\":{\"details\":\"Only a token holder or a designated operator can redeem its tokens.\",\"params\":{\"_beneficiary\":\"The address to send the terminal tokens to.\",\"_holder\":\"The account to redeem tokens for.\",\"_memo\":\"A memo to pass along to the emitted event.\",\"_metadata\":\"Bytes to send along to the data source, delegate, and emitted event, if provided.\",\"_minReturnedTokens\":\"The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\",\"_projectId\":\"The ID of the project to which the tokens being redeemed belong.\",\"_token\":\"The token being reclaimed. This terminal ignores this property since it only manages one token. \",\"_tokenCount\":\"The number of project tokens to redeem, as a fixed point number with 18 decimals.\"},\"returns\":{\"reclaimAmount\":\"The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"setFee(uint256)\":{\"details\":\"Only the owner of this contract can change the fee.\",\"params\":{\"_fee\":\"The new fee, out of MAX_FEE.\"}},\"setFeeGauge(address)\":{\"details\":\"Only the owner of this contract can change the fee gauge.\",\"params\":{\"_feeGauge\":\"The new fee gauge.\"}},\"setFeelessAddress(address,bool)\":{\"details\":\"Only the owner of this contract can set addresses as feeless.\",\"params\":{\"_address\":\"The address that can be paid towards while still bypassing fees.\",\"_flag\":\"A flag indicating whether the terminal should be feeless or not.\"}},\"supportsInterface(bytes4)\":{\"details\":\" See {IERC165-supportsInterface}.\",\"params\":{\"_interfaceId\":\"The ID of the interface to check for adherance to.\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"useAllowanceOf(uint256,uint256,uint256,address,uint256,address,string)\":{\"details\":\"Only a project's owner or a designated operator can use its allowance.Incurs the protocol fee.\",\"params\":{\"_amount\":\"The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\",\"_beneficiary\":\"The address to send the funds to.\",\"_currency\":\"The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\",\"_memo\":\"A memo to pass along to the emitted event.\",\"_minReturnedTokens\":\"The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\",\"_projectId\":\"The ID of the project to use the allowance of.\",\"_token\":\"The token being distributed. This terminal ignores this property since it only manages one token. \"},\"returns\":{\"netDistributedAmount\":\"The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\"}}},\"version\":1},\"userdoc\":{\"errors\":{\"PRBMath__MulDivOverflow(uint256,uint256)\":[{\"notice\":\"Emitted when the result overflows uint256.\"}]},\"kind\":\"user\",\"methods\":{\"acceptsToken(address,uint256)\":{\"notice\":\"A flag indicating if this terminal accepts the specified token.\"},\"addToBalanceOf(uint256,uint256,address,string,bytes)\":{\"notice\":\"Receives funds belonging to the specified project.\"},\"baseWeightCurrency()\":{\"notice\":\"The currency to base token issuance on.\"},\"currency()\":{\"notice\":\"The currency to use when resolving price feeds for this terminal.\"},\"currencyForToken(address)\":{\"notice\":\"The currency that should be used for the specified token.\"},\"currentEthOverflowOf(uint256)\":{\"notice\":\"Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\"},\"decimals()\":{\"notice\":\"The number of decimals the token fixed point amounts are expected to have.\"},\"decimalsForToken(address)\":{\"notice\":\"The decimals that should be used in fixed number accounting for the specified token.\"},\"directory()\":{\"notice\":\"The directory of terminals and controllers for projects.\"},\"distributePayoutsOf(uint256,uint256,uint256,address,uint256,string)\":{\"notice\":\"Distributes payouts for a project with the distribution limit of its current funding cycle.\"},\"fee()\":{\"notice\":\"The platform fee percent.\"},\"feeGauge()\":{\"notice\":\"The data source that returns a discount to apply to a project's fee.\"},\"heldFeesOf(uint256)\":{\"notice\":\"The fees that are currently being held to be processed later for each project.\"},\"isFeelessAddress(address)\":{\"notice\":\"Addresses that can be paid towards from this terminal without incurring a fee.\"},\"migrate(uint256,address)\":{\"notice\":\"Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\"},\"operatorStore()\":{\"notice\":\" A contract storing operator assignments.\"},\"pay(uint256,uint256,address,address,uint256,bool,string,bytes)\":{\"notice\":\"Contribute tokens to a project.\"},\"payoutSplitsGroup()\":{\"notice\":\"The group that payout splits coming from this terminal are identified by.\"},\"prices()\":{\"notice\":\"The contract that exposes price feeds.\"},\"processFees(uint256)\":{\"notice\":\"Process any fees that are being held for the project.\"},\"projects()\":{\"notice\":\"Mints ERC-721's that represent project ownership and transfers.\"},\"redeemTokensOf(address,uint256,uint256,address,uint256,address,string,bytes)\":{\"notice\":\"Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\"},\"setFee(uint256)\":{\"notice\":\"Allows the fee to be updated.\"},\"setFeeGauge(address)\":{\"notice\":\"Allows the fee gauge to be updated.\"},\"setFeelessAddress(address,bool)\":{\"notice\":\"Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\"},\"splitsStore()\":{\"notice\":\"The contract that stores splits for each project.\"},\"store()\":{\"notice\":\"The contract that stores and manages the terminal's data.\"},\"supportsInterface(bytes4)\":{\"notice\":\"Indicates if this contract adheres to the specified interface.\"},\"token()\":{\"notice\":\"The token that this terminal accepts.\"},\"useAllowanceOf(uint256,uint256,uint256,address,uint256,address,string)\":{\"notice\":\"Allows a project to send funds from its overflow up to the preconfigured allowance.\"}},\"notice\":\"Manages all inflows and outflows of ETH funds into the protocol ecosystem.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/JBETHPaymentTerminal.sol\":\"JBETHPaymentTerminal\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0x24e0364e503a9bbde94c715d26573a76f14cd2a202d45f96f52134ab806b67b9\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool _approved) external;\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x516a22876c1fab47f49b1bc22b4614491cd05338af8bd2e7b382da090a079990\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3777e696b62134e6177440dbe6e6601c0c156a443f57167194b67e75527439de\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"@paulrberg/contracts/math/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\nimport \\\"prb-math/contracts/PRBMath.sol\\\";\\n\",\"keccak256\":\"0x42821345981bc0434a90ba2268a2f5278dfe9e38166981d72fc7f3b776a29495\",\"license\":\"Unlicense\"},\"contracts/JBETHPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport '@openzeppelin/contracts/utils/Address.sol';\\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\\nimport './libraries/JBSplitsGroups.sol';\\n\\n/**\\n @notice\\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\\n\\n @dev\\n Inherits from -\\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\\n*/\\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\\n //*********************************************************************//\\n // -------------------------- internal views ------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Checks the balance of tokens in this contract.\\n\\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\\n */\\n function _balance() internal view override returns (uint256) {\\n return address(this).balance;\\n }\\n\\n //*********************************************************************//\\n // -------------------------- constructor ---------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @param _baseWeightCurrency The currency to base token issuance on.\\n @param _operatorStore A contract storing operator assignments.\\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\\n @param _directory A contract storing directories of terminals and controllers for each project.\\n @param _splitsStore A contract that stores splits for each project.\\n @param _prices A contract that exposes price feeds.\\n @param _store A contract that stores the terminal's data.\\n @param _owner The address that will own this contract.\\n */\\n constructor(\\n uint256 _baseWeightCurrency,\\n IJBOperatorStore _operatorStore,\\n IJBProjects _projects,\\n IJBDirectory _directory,\\n IJBSplitsStore _splitsStore,\\n IJBPrices _prices,\\n IJBSingleTokenPaymentTerminalStore _store,\\n address _owner\\n )\\n JBPayoutRedemptionPaymentTerminal(\\n JBTokens.GAS_TOKEN,\\n 18, // 18 decimals.\\n JBCurrencies.GAS_CURRENCY,\\n _baseWeightCurrency,\\n JBSplitsGroups.ETH_PAYOUT,\\n _operatorStore,\\n _projects,\\n _directory,\\n _splitsStore,\\n _prices,\\n _store,\\n _owner\\n )\\n // solhint-disable-next-line no-empty-blocks\\n {\\n\\n }\\n\\n //*********************************************************************//\\n // ---------------------- internal transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Transfers tokens.\\n\\n @param _from The address from which the transfer should originate.\\n @param _to The address to which the transfer should go.\\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\\n */\\n function _transferFrom(\\n address _from,\\n address payable _to,\\n uint256 _amount\\n ) internal override {\\n _from; // Prevents unused var compiler and natspec complaints.\\n\\n Address.sendValue(_to, _amount);\\n }\\n}\\n\",\"keccak256\":\"0x6afb443f7efddb2ecd7023237f6e1684c4281a1fad43e4e1b34fa0d50b407384\",\"license\":\"MIT\"},\"contracts/abstract/JBOperatable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport './../interfaces/IJBOperatable.sol';\\n\\n/** \\n @notice\\n Modifiers to allow access to functions based on the message sender's operator status.\\n\\n @dev\\n Adheres to -\\n IJBOperatable: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n*/\\nabstract contract JBOperatable is IJBOperatable {\\n //*********************************************************************//\\n // --------------------------- custom errors -------------------------- //\\n //*********************************************************************//\\n error UNAUTHORIZED();\\n\\n //*********************************************************************//\\n // ---------------------------- modifiers ---------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Only allows the speficied account or an operator of the account to proceed. \\n\\n @param _account The account to check for.\\n @param _domain The domain namespace to look for an operator within. \\n @param _permissionIndex The index of the permission to check for. \\n */\\n modifier requirePermission(\\n address _account,\\n uint256 _domain,\\n uint256 _permissionIndex\\n ) {\\n _requirePermission(_account, _domain, _permissionIndex);\\n _;\\n }\\n\\n /** \\n @notice\\n Only allows the speficied account, an operator of the account to proceed, or a truthy override flag. \\n\\n @param _account The account to check for.\\n @param _domain The domain namespace to look for an operator within. \\n @param _permissionIndex The index of the permission to check for. \\n @param _override A condition to force allowance for.\\n */\\n modifier requirePermissionAllowingOverride(\\n address _account,\\n uint256 _domain,\\n uint256 _permissionIndex,\\n bool _override\\n ) {\\n _requirePermissionAllowingOverride(_account, _domain, _permissionIndex, _override);\\n _;\\n }\\n\\n //*********************************************************************//\\n // ---------------- public immutable stored properties --------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n A contract storing operator assignments.\\n */\\n IJBOperatorStore public immutable override operatorStore;\\n\\n //*********************************************************************//\\n // -------------------------- constructor ---------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @param _operatorStore A contract storing operator assignments.\\n */\\n constructor(IJBOperatorStore _operatorStore) {\\n operatorStore = _operatorStore;\\n }\\n\\n //*********************************************************************//\\n // -------------------------- internal views ------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Require the message sender is either the account or has the specified permission.\\n\\n @param _account The account to allow.\\n @param _domain The domain namespace within which the permission index will be checked.\\n @param _permissionIndex The permission index that an operator must have within the specified domain to be allowed.\\n */\\n function _requirePermission(\\n address _account,\\n uint256 _domain,\\n uint256 _permissionIndex\\n ) internal view {\\n if (\\n msg.sender != _account &&\\n !operatorStore.hasPermission(msg.sender, _account, _domain, _permissionIndex) &&\\n !operatorStore.hasPermission(msg.sender, _account, 0, _permissionIndex)\\n ) revert UNAUTHORIZED();\\n }\\n\\n /** \\n @notice\\n Require the message sender is either the account, has the specified permission, or the override condition is true.\\n\\n @param _account The account to allow.\\n @param _domain The domain namespace within which the permission index will be checked.\\n @param _domain The permission index that an operator must have within the specified domain to be allowed.\\n @param _override The override condition to allow.\\n */\\n function _requirePermissionAllowingOverride(\\n address _account,\\n uint256 _domain,\\n uint256 _permissionIndex,\\n bool _override\\n ) internal view {\\n if (\\n !_override &&\\n msg.sender != _account &&\\n !operatorStore.hasPermission(msg.sender, _account, _domain, _permissionIndex) &&\\n !operatorStore.hasPermission(msg.sender, _account, 0, _permissionIndex)\\n ) revert UNAUTHORIZED();\\n }\\n}\\n\",\"keccak256\":\"0x9e62cac5c464eb973f881cf6c373b95aab31d2ddbeb048ee7ad82b5c9ab28add\",\"license\":\"MIT\"},\"contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport '@openzeppelin/contracts/access/Ownable.sol';\\nimport '@paulrberg/contracts/math/PRBMath.sol';\\nimport './../interfaces/IJBController.sol';\\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal.sol';\\nimport './../libraries/JBConstants.sol';\\nimport './../libraries/JBCurrencies.sol';\\nimport './../libraries/JBFixedPointNumber.sol';\\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\\nimport './../libraries/JBOperations.sol';\\nimport './../libraries/JBTokens.sol';\\nimport './../structs/JBPayDelegateAllocation.sol';\\nimport './../structs/JBTokenAmount.sol';\\nimport './JBOperatable.sol';\\nimport './JBSingleTokenPaymentTerminal.sol';\\n\\n/**\\n @notice\\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\\n\\n @dev\\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\\n\\n @dev\\n Adheres to -\\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n\\n @dev\\n Inherits from -\\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\\n*/\\nabstract contract JBPayoutRedemptionPaymentTerminal is\\n JBSingleTokenPaymentTerminal,\\n JBOperatable,\\n Ownable,\\n IJBPayoutRedemptionPaymentTerminal\\n{\\n // A library that parses the packed funding cycle metadata into a friendlier format.\\n using JBFundingCycleMetadataResolver for JBFundingCycle;\\n\\n //*********************************************************************//\\n // --------------------------- custom errors ------------------------- //\\n //*********************************************************************//\\n error FEE_TOO_HIGH();\\n error INADEQUATE_DISTRIBUTION_AMOUNT();\\n error INADEQUATE_RECLAIM_AMOUNT();\\n error INADEQUATE_TOKEN_COUNT();\\n error NO_MSG_VALUE_ALLOWED();\\n error PAY_TO_ZERO_ADDRESS();\\n error PROJECT_TERMINAL_MISMATCH();\\n error REDEEM_TO_ZERO_ADDRESS();\\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\\n error TERMINAL_TOKENS_INCOMPATIBLE();\\n\\n //*********************************************************************//\\n // ---------------------------- modifiers ---------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n A modifier that verifies this terminal is a terminal of provided project ID.\\n */\\n modifier isTerminalOf(uint256 _projectId) {\\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\\n _;\\n }\\n\\n //*********************************************************************//\\n // --------------------- internal stored constants ------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Maximum fee that can be set for a funding cycle configuration.\\n\\n @dev\\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\\n */\\n uint256 internal constant _FEE_CAP = 50_000_000;\\n\\n /**\\n @notice\\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\\n */\\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\\n\\n //*********************************************************************//\\n // --------------------- internal stored properties ------------------ //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Fees that are being held to be processed later.\\n\\n _projectId The ID of the project for which fees are being held.\\n */\\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\\n\\n //*********************************************************************//\\n // ---------------- public immutable stored properties --------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Mints ERC-721's that represent project ownership and transfers.\\n */\\n IJBProjects public immutable override projects;\\n\\n /**\\n @notice\\n The directory of terminals and controllers for projects.\\n */\\n IJBDirectory public immutable override directory;\\n\\n /**\\n @notice\\n The contract that stores splits for each project.\\n */\\n IJBSplitsStore public immutable override splitsStore;\\n\\n /**\\n @notice\\n The contract that exposes price feeds.\\n */\\n IJBPrices public immutable override prices;\\n\\n /**\\n @notice\\n The contract that stores and manages the terminal's data.\\n */\\n IJBSingleTokenPaymentTerminalStore public immutable override store;\\n\\n /**\\n @notice\\n The currency to base token issuance on.\\n\\n @dev\\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\\n */\\n uint256 public immutable override baseWeightCurrency;\\n\\n /**\\n @notice\\n The group that payout splits coming from this terminal are identified by.\\n */\\n uint256 public immutable override payoutSplitsGroup;\\n\\n //*********************************************************************//\\n // --------------------- public stored properties -------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The platform fee percent.\\n\\n @dev\\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\\n */\\n uint256 public override fee = 25_000_000; // 2.5%\\n\\n /**\\n @notice\\n The data source that returns a discount to apply to a project's fee.\\n */\\n IJBFeeGauge public override feeGauge;\\n\\n /**\\n @notice\\n Addresses that can be paid towards from this terminal without incurring a fee.\\n\\n @dev\\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\\n\\n _address The address that can be paid toward.\\n */\\n mapping(address => bool) public override isFeelessAddress;\\n\\n //*********************************************************************//\\n // ------------------------- external views -------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\\n\\n @dev\\n The current overflow is represented as a fixed point number with 18 decimals.\\n\\n @param _projectId The ID of the project to get overflow for.\\n\\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\\n */\\n function currentEthOverflowOf(uint256 _projectId)\\n external\\n view\\n virtual\\n override\\n returns (uint256)\\n {\\n // Get this terminal's current overflow.\\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\\n\\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\\n uint256 _adjustedOverflow = (decimals == 18)\\n ? _overflow\\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\\n\\n // Return the amount converted to ETH.\\n return\\n (currency == JBCurrencies.GAS_CURRENCY)\\n ? _adjustedOverflow\\n : PRBMath.mulDiv(\\n _adjustedOverflow,\\n 10**decimals,\\n prices.priceFor(currency, JBCurrencies.GAS_CURRENCY, decimals)\\n );\\n }\\n\\n /**\\n @notice\\n The fees that are currently being held to be processed later for each project.\\n\\n @param _projectId The ID of the project for which fees are being held.\\n\\n @return An array of fees that are being held.\\n */\\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\\n return _heldFeesOf[_projectId];\\n }\\n\\n //*********************************************************************//\\n // -------------------------- public views --------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Indicates if this contract adheres to the specified interface.\\n\\n @dev \\n See {IERC165-supportsInterface}.\\n\\n @param _interfaceId The ID of the interface to check for adherance to.\\n */\\n function supportsInterface(bytes4 _interfaceId)\\n public\\n view\\n virtual\\n override(JBSingleTokenPaymentTerminal, IERC165)\\n returns (bool)\\n {\\n return\\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\\n _interfaceId == type(IJBOperatable).interfaceId ||\\n super.supportsInterface(_interfaceId);\\n }\\n\\n //*********************************************************************//\\n // -------------------------- internal views ------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Checks the balance of tokens in this contract.\\n\\n @return The contract's balance.\\n */\\n function _balance() internal view virtual returns (uint256);\\n\\n //*********************************************************************//\\n // -------------------------- constructor ---------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @param _token The token that this terminal manages.\\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\\n @param _currency The currency that this terminal's token adheres to for price feeds.\\n @param _baseWeightCurrency The currency to base token issuance on.\\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\\n @param _operatorStore A contract storing operator assignments.\\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\\n @param _directory A contract storing directories of terminals and controllers for each project.\\n @param _splitsStore A contract that stores splits for each project.\\n @param _prices A contract that exposes price feeds.\\n @param _store A contract that stores the terminal's data.\\n @param _owner The address that will own this contract.\\n */\\n constructor(\\n // payable constructor save the gas used to check msg.value==0\\n address _token,\\n uint256 _decimals,\\n uint256 _currency,\\n uint256 _baseWeightCurrency,\\n uint256 _payoutSplitsGroup,\\n IJBOperatorStore _operatorStore,\\n IJBProjects _projects,\\n IJBDirectory _directory,\\n IJBSplitsStore _splitsStore,\\n IJBPrices _prices,\\n IJBSingleTokenPaymentTerminalStore _store,\\n address _owner\\n )\\n payable\\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\\n JBOperatable(_operatorStore)\\n {\\n baseWeightCurrency = _baseWeightCurrency;\\n payoutSplitsGroup = _payoutSplitsGroup;\\n projects = _projects;\\n directory = _directory;\\n splitsStore = _splitsStore;\\n prices = _prices;\\n store = _store;\\n\\n transferOwnership(_owner);\\n }\\n\\n //*********************************************************************//\\n // ---------------------- external transactions ---------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Contribute tokens to a project.\\n\\n @param _projectId The ID of the project being paid.\\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\\n\\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\\n */\\n function pay(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n // ETH shouldn't be sent if this terminal's token isn't ETH.\\n if (token != JBTokens.GAS_TOKEN) {\\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\\n\\n // Get a reference to the balance before receiving tokens.\\n uint256 _balanceBefore = _balance();\\n\\n // Transfer tokens to this terminal from the msg sender.\\n _transferFrom(msg.sender, payable(address(this)), _amount);\\n\\n // The amount should reflect the change in balance.\\n _amount = _balance() - _balanceBefore;\\n }\\n // If this terminal's token is ETH, override _amount with msg.value.\\n else _amount = msg.value;\\n\\n return\\n _pay(\\n _amount,\\n msg.sender,\\n _projectId,\\n _beneficiary,\\n _minReturnedTokens,\\n _preferClaimedTokens,\\n _memo,\\n _metadata\\n );\\n }\\n\\n /**\\n @notice\\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\\n\\n @dev\\n Only a token holder or a designated operator can redeem its tokens.\\n\\n @param _holder The account to redeem tokens for.\\n @param _projectId The ID of the project to which the tokens being redeemed belong.\\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\\n @param _beneficiary The address to send the terminal tokens to.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\\n\\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\\n */\\n function redeemTokensOf(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n address _token,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string memory _memo,\\n bytes memory _metadata\\n )\\n external\\n virtual\\n override\\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\\n returns (uint256 reclaimAmount)\\n {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n return\\n _redeemTokensOf(\\n _holder,\\n _projectId,\\n _tokenCount,\\n _minReturnedTokens,\\n _beneficiary,\\n _memo,\\n _metadata\\n );\\n }\\n\\n /**\\n @notice\\n Distributes payouts for a project with the distribution limit of its current funding cycle.\\n\\n @dev\\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\\n\\n @dev\\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\\n\\n @dev\\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\\n\\n @param _projectId The ID of the project having its payouts distributed.\\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\\n @param _memo A memo to pass along to the emitted event.\\n\\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\\n */\\n function distributePayoutsOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n address _token,\\n uint256 _minReturnedTokens,\\n string calldata _memo\\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\\n }\\n\\n /**\\n @notice\\n Allows a project to send funds from its overflow up to the preconfigured allowance.\\n\\n @dev\\n Only a project's owner or a designated operator can use its allowance.\\n\\n @dev\\n Incurs the protocol fee.\\n\\n @param _projectId The ID of the project to use the allowance of.\\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\\n @param _beneficiary The address to send the funds to.\\n @param _memo A memo to pass along to the emitted event.\\n\\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\\n */\\n function useAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n address _token,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string memory _memo\\n )\\n external\\n virtual\\n override\\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\\n returns (uint256 netDistributedAmount)\\n {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\\n }\\n\\n /**\\n @notice\\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\\n\\n @dev\\n Only a project's owner or a designated operator can migrate it.\\n\\n @param _projectId The ID of the project being migrated.\\n @param _to The terminal contract that will gain the project's funds.\\n\\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\\n */\\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\\n external\\n virtual\\n override\\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\\n returns (uint256 balance)\\n {\\n // The terminal being migrated to must accept the same token as this terminal.\\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\\n\\n // Record the migration in the store.\\n balance = store.recordMigration(_projectId);\\n\\n // Transfer the balance if needed.\\n if (balance > 0) {\\n // Trigger any inherited pre-transfer logic.\\n _beforeTransferTo(address(_to), balance);\\n\\n // If this terminal's token is ETH, send it in msg.value.\\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? balance : 0;\\n\\n // Withdraw the balance to transfer to the new terminal;\\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\\n }\\n\\n emit Migrate(_projectId, _to, balance, msg.sender);\\n }\\n\\n /**\\n @notice\\n Receives funds belonging to the specified project.\\n\\n @param _projectId The ID of the project to which the funds received belong.\\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Extra data to pass along to the emitted event.\\n */\\n function addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable virtual override isTerminalOf(_projectId) {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\\n if (token != JBTokens.GAS_TOKEN) {\\n // Amount must be greater than 0.\\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\\n\\n // Get a reference to the balance before receiving tokens.\\n uint256 _balanceBefore = _balance();\\n\\n // Transfer tokens to this terminal from the msg sender.\\n _transferFrom(msg.sender, payable(address(this)), _amount);\\n\\n // The amount should reflect the change in balance.\\n _amount = _balance() - _balanceBefore;\\n }\\n // If the terminal's token is ETH, override `_amount` with msg.value.\\n else _amount = msg.value;\\n\\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\\n }\\n\\n /**\\n @notice\\n Process any fees that are being held for the project.\\n\\n @dev\\n Only a project owner, an operator, or the contract's owner can process held fees.\\n\\n @param _projectId The ID of the project whos held fees should be processed.\\n */\\n function processFees(uint256 _projectId)\\n external\\n virtual\\n override\\n requirePermissionAllowingOverride(\\n projects.ownerOf(_projectId),\\n _projectId,\\n JBOperations.PROCESS_FEES,\\n msg.sender == owner()\\n )\\n {\\n // Get a reference to the project's held fees.\\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\\n\\n // Delete the held fees.\\n delete _heldFeesOf[_projectId];\\n\\n // Push array length in stack\\n uint256 _heldFeeLength = _heldFees.length;\\n\\n // Process each fee.\\n for (uint256 _i; _i < _heldFeeLength; ) {\\n // Get the fee amount.\\n uint256 _amount = _feeAmount(\\n _heldFees[_i].amount,\\n _heldFees[_i].fee,\\n _heldFees[_i].feeDiscount\\n );\\n\\n // Process the fee.\\n _processFee(_amount, _heldFees[_i].beneficiary);\\n\\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n\\n /**\\n @notice\\n Allows the fee to be updated.\\n\\n @dev\\n Only the owner of this contract can change the fee.\\n\\n @param _fee The new fee, out of MAX_FEE.\\n */\\n function setFee(uint256 _fee) external virtual override onlyOwner {\\n // The provided fee must be within the max.\\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\\n\\n // Store the new fee.\\n fee = _fee;\\n\\n emit SetFee(_fee, msg.sender);\\n }\\n\\n /**\\n @notice\\n Allows the fee gauge to be updated.\\n\\n @dev\\n Only the owner of this contract can change the fee gauge.\\n\\n @param _feeGauge The new fee gauge.\\n */\\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\\n // Store the new fee gauge.\\n feeGauge = _feeGauge;\\n\\n emit SetFeeGauge(_feeGauge, msg.sender);\\n }\\n\\n /**\\n @notice\\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\\n\\n @dev\\n Only the owner of this contract can set addresses as feeless.\\n\\n @param _address The address that can be paid towards while still bypassing fees.\\n @param _flag A flag indicating whether the terminal should be feeless or not.\\n */\\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\\n // Set the flag value.\\n isFeelessAddress[_address] = _flag;\\n\\n emit SetFeelessAddress(_address, _flag, msg.sender);\\n }\\n\\n //*********************************************************************//\\n // ---------------------- internal transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Transfers tokens.\\n\\n @param _from The address from which the transfer should originate.\\n @param _to The address to which the transfer should go.\\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\\n */\\n function _transferFrom(\\n address _from,\\n address payable _to,\\n uint256 _amount\\n ) internal virtual {\\n _from; // Prevents unused var compiler and natspec complaints.\\n _to; // Prevents unused var compiler and natspec complaints.\\n _amount; // Prevents unused var compiler and natspec complaints.\\n }\\n\\n /** \\n @notice\\n Logic to be triggered before transferring tokens from this terminal.\\n\\n @param _to The address to which the transfer is going.\\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\\n */\\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\\n _to; // Prevents unused var compiler and natspec complaints.\\n _amount; // Prevents unused var compiler and natspec complaints.\\n }\\n\\n /**\\n @notice\\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\\n\\n @dev\\n Only a token holder or a designated operator can redeem its tokens.\\n\\n @param _holder The account to redeem tokens for.\\n @param _projectId The ID of the project to which the tokens being redeemed belong.\\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\\n @param _beneficiary The address to send the terminal tokens to.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\\n\\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\\n */\\n function _redeemTokensOf(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string memory _memo,\\n bytes memory _metadata\\n ) internal returns (uint256 reclaimAmount) {\\n // Can't send reclaimed funds to the zero address.\\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\\n\\n // Define variables that will be needed outside the scoped section below.\\n // Keep a reference to the funding cycle during which the redemption is being made.\\n JBFundingCycle memory _fundingCycle;\\n\\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\\n {\\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\\n\\n // Record the redemption.\\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\\n _holder,\\n _projectId,\\n _tokenCount,\\n _memo,\\n _metadata\\n );\\n\\n // The amount being reclaimed must be at least as much as was expected.\\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\\n\\n // Burn the project tokens.\\n if (_tokenCount > 0)\\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\\n _holder,\\n _projectId,\\n _tokenCount,\\n '',\\n false\\n );\\n\\n // If delegate allocations were specified by the data source, fulfill them.\\n if (_delegateAllocations.length != 0) {\\n // Keep a reference to the token amount being forwarded to the delegate.\\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\\n\\n JBDidRedeemData memory _data = JBDidRedeemData(\\n _holder,\\n _projectId,\\n _fundingCycle.configuration,\\n _tokenCount,\\n JBTokenAmount(token, reclaimAmount, decimals, currency),\\n _forwardedAmount,\\n _beneficiary,\\n _memo,\\n _metadata\\n );\\n\\n uint256 _numDelegates = _delegateAllocations.length;\\n\\n for (uint256 _i; _i < _numDelegates; ) {\\n // Get a reference to the delegate being iterated on.\\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\\n\\n // Trigger any inherited pre-transfer logic.\\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\\n\\n // Keep track of the msg.value to use in the delegate call\\n uint256 _payableValue;\\n\\n // If this terminal's token is ETH, send it in msg.value.\\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\\n\\n // Pass the correct token forwardedAmount to the delegate\\n _data.forwardedAmount.value = _delegateAllocation.amount;\\n\\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\\n\\n emit DelegateDidRedeem(\\n _delegateAllocation.delegate,\\n _data,\\n _delegateAllocation.amount,\\n msg.sender\\n );\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n }\\n\\n // Send the reclaimed funds to the beneficiary.\\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\\n\\n emit RedeemTokens(\\n _fundingCycle.configuration,\\n _fundingCycle.number,\\n _projectId,\\n _holder,\\n _beneficiary,\\n _tokenCount,\\n reclaimAmount,\\n _memo,\\n _metadata,\\n msg.sender\\n );\\n }\\n\\n /**\\n @notice\\n Distributes payouts for a project with the distribution limit of its current funding cycle.\\n\\n @dev\\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\\n\\n @dev\\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\\n\\n @dev\\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\\n\\n @param _projectId The ID of the project having its payouts distributed.\\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\\n @param _memo A memo to pass along to the emitted event.\\n\\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\\n */\\n function _distributePayoutsOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n uint256 _minReturnedTokens,\\n string calldata _memo\\n ) internal returns (uint256 netLeftoverDistributionAmount) {\\n // Record the distribution.\\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\\n _projectId,\\n _amount,\\n _currency\\n );\\n\\n // The amount being distributed must be at least as much as was expected.\\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\\n\\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\\n // and receive any extra distributable funds not allocated to payout splits.\\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\\n\\n // Define variables that will be needed outside the scoped section below.\\n // Keep a reference to the fee amount that was paid.\\n uint256 _fee;\\n\\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\\n {\\n // Get the amount of discount that should be applied to any fees taken.\\n // If the fee is zero, set the discount to 100% for convenience.\\n uint256 _feeDiscount = fee == 0\\n ? JBConstants.MAX_FEE_DISCOUNT\\n : _currentFeeDiscount(_projectId);\\n\\n // The amount distributed that is eligible for incurring fees.\\n uint256 _feeEligibleDistributionAmount;\\n\\n // The amount leftover after distributing to the splits.\\n uint256 _leftoverDistributionAmount;\\n\\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\\n _projectId,\\n _fundingCycle.configuration,\\n payoutSplitsGroup,\\n _distributedAmount,\\n _feeDiscount\\n );\\n\\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\\n unchecked {\\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\\n }\\n }\\n\\n // Take the fee.\\n _fee = _feeEligibleDistributionAmount != 0\\n ? _takeFeeFrom(\\n _projectId,\\n _fundingCycle,\\n _feeEligibleDistributionAmount,\\n _projectOwner,\\n _feeDiscount\\n )\\n : 0;\\n\\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\\n if (_leftoverDistributionAmount != 0) {\\n // Subtract the fee from the net leftover amount.\\n netLeftoverDistributionAmount =\\n _leftoverDistributionAmount -\\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\\n\\n // Transfer the amount to the project owner.\\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\\n }\\n }\\n\\n emit DistributePayouts(\\n _fundingCycle.configuration,\\n _fundingCycle.number,\\n _projectId,\\n _projectOwner,\\n _amount,\\n _distributedAmount,\\n _fee,\\n netLeftoverDistributionAmount,\\n _memo,\\n msg.sender\\n );\\n }\\n\\n /**\\n @notice\\n Allows a project to send funds from its overflow up to the preconfigured allowance.\\n\\n @dev\\n Only a project's owner or a designated operator can use its allowance.\\n\\n @dev\\n Incurs the protocol fee.\\n\\n @param _projectId The ID of the project to use the allowance of.\\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\\n @param _beneficiary The address to send the funds to.\\n @param _memo A memo to pass along to the emitted event.\\n\\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\\n */\\n function _useAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string memory _memo\\n ) internal returns (uint256 netDistributedAmount) {\\n // Record the use of the allowance.\\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\\n _projectId,\\n _amount,\\n _currency\\n );\\n\\n // The amount being withdrawn must be at least as much as was expected.\\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\\n\\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\\n {\\n // Keep a reference to the fee amount that was paid.\\n uint256 _fee;\\n\\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\\n address _projectOwner = projects.ownerOf(_projectId);\\n\\n // Get the amount of discount that should be applied to any fees taken.\\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\\n ? JBConstants.MAX_FEE_DISCOUNT\\n : _currentFeeDiscount(_projectId);\\n\\n // Take a fee from the `_distributedAmount`, if needed.\\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\\n ? 0\\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\\n\\n unchecked {\\n // The net amount is the withdrawn amount without the fee.\\n netDistributedAmount = _distributedAmount - _fee;\\n }\\n\\n // Transfer any remaining balance to the beneficiary.\\n if (netDistributedAmount > 0)\\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\\n }\\n\\n emit UseAllowance(\\n _fundingCycle.configuration,\\n _fundingCycle.number,\\n _projectId,\\n _beneficiary,\\n _amount,\\n _distributedAmount,\\n netDistributedAmount,\\n _memo,\\n msg.sender\\n );\\n }\\n\\n /**\\n @notice\\n Pays out splits for a project's funding cycle configuration.\\n\\n @param _projectId The ID of the project for which payout splits are being distributed.\\n @param _domain The domain of the splits to distribute the payout between.\\n @param _group The group of the splits to distribute the payout between.\\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\\n\\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\\n */\\n function _distributeToPayoutSplitsOf(\\n uint256 _projectId,\\n uint256 _domain,\\n uint256 _group,\\n uint256 _amount,\\n uint256 _feeDiscount\\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\\n // Set the leftover amount to the initial amount.\\n leftoverAmount = _amount;\\n // The total percentage available to split\\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\\n\\n // Get a reference to the project's payout splits.\\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\\n\\n // Transfer between all splits.\\n for (uint256 _i; _i < _splits.length; ) {\\n // Get a reference to the split being iterated on.\\n JBSplit memory _split = _splits[_i];\\n\\n // The amount to send towards the split.\\n uint256 _payoutAmount = _split.percent == leftoverPercentage\\n ? leftoverAmount\\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\\n\\n // Decrement the leftover percentage.\\n leftoverPercentage -= _split.percent;\\n\\n // The payout amount substracting any applicable incurred fees.\\n uint256 _netPayoutAmount;\\n\\n if (_payoutAmount > 0) {\\n // Transfer tokens to the split.\\n // If there's an allocator set, transfer to its `allocate` function.\\n if (_split.allocator != IJBSplitAllocator(address(0))) {\\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\\n if (\\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\\n isFeelessAddress[address(_split.allocator)]\\n )\\n _netPayoutAmount = _payoutAmount;\\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\\n else {\\n unchecked {\\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\\n }\\n\\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\\n feeEligibleDistributionAmount += _payoutAmount;\\n }\\n\\n // Trigger any inherited pre-transfer logic.\\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\\n\\n // Create the data to send to the allocator.\\n JBSplitAllocationData memory _data = JBSplitAllocationData(\\n token,\\n _netPayoutAmount,\\n decimals,\\n _projectId,\\n _group,\\n _split\\n );\\n\\n // Trigger the allocator's `allocate` function.\\n // If this terminal's token is ETH, send it in msg.value.\\n _split.allocator.allocate{value: token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0}(_data);\\n\\n // Otherwise, if a project is specified, make a payment to it.\\n } else if (_split.projectId != 0) {\\n // Get a reference to the Juicebox terminal being used.\\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\\n\\n // The project must have a terminal to send funds to.\\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\\n\\n // Save gas if this contract is being used as the terminal.\\n if (_terminal == this) {\\n // This distribution does not incur a fee.\\n _netPayoutAmount = _payoutAmount;\\n\\n // Send the projectId in the metadata.\\n bytes memory _projectMetadata = new bytes(32);\\n _projectMetadata = bytes(abi.encodePacked(_projectId));\\n\\n // Add to balance if prefered.\\n if (_split.preferAddToBalance)\\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\\n else\\n _pay(\\n _netPayoutAmount,\\n address(this),\\n _split.projectId,\\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\\n 0,\\n _split.preferClaimed,\\n '',\\n _projectMetadata\\n );\\n } else {\\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\\n if (\\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_terminal)]\\n )\\n _netPayoutAmount = _payoutAmount;\\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\\n else {\\n unchecked {\\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\\n }\\n\\n feeEligibleDistributionAmount += _payoutAmount;\\n }\\n\\n // Trigger any inherited pre-transfer logic.\\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\\n\\n // If this terminal's token is ETH, send it in msg.value.\\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0;\\n\\n // Send the projectId in the metadata.\\n bytes memory _projectMetadata = new bytes(32);\\n _projectMetadata = bytes(abi.encodePacked(_projectId));\\n\\n // Add to balance if prefered.\\n if (_split.preferAddToBalance)\\n _terminal.addToBalanceOf{value: _payableValue}(\\n _split.projectId,\\n _netPayoutAmount,\\n token,\\n '',\\n _projectMetadata\\n );\\n else\\n _terminal.pay{value: _payableValue}(\\n _split.projectId,\\n _netPayoutAmount,\\n token,\\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\\n 0,\\n _split.preferClaimed,\\n '',\\n _projectMetadata\\n );\\n }\\n } else {\\n // Keep a reference to the beneficiary.\\n address payable _beneficiary = _split.beneficiary != address(0)\\n ? _split.beneficiary\\n : payable(msg.sender);\\n\\n // If there's a full discount, this distribution is not eligible for a fee.\\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\\n _netPayoutAmount = _payoutAmount;\\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\\n else {\\n unchecked {\\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\\n }\\n\\n feeEligibleDistributionAmount += _payoutAmount;\\n }\\n\\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\\n _transferFrom(address(this), _beneficiary, _netPayoutAmount);\\n }\\n\\n // Subtract from the amount to be sent to the beneficiary.\\n unchecked {\\n leftoverAmount = leftoverAmount - _payoutAmount;\\n }\\n }\\n\\n emit DistributeToPayoutSplit(\\n _projectId,\\n _domain,\\n _group,\\n _split,\\n _netPayoutAmount,\\n msg.sender\\n );\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n\\n /**\\n @notice\\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\\n\\n @param _projectId The ID of the project having fees taken from.\\n @param _fundingCycle The funding cycle during which the fee is being taken.\\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\\n @param _beneficiary The address to mint the platforms tokens for.\\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\\n\\n @return feeAmount The amount of the fee taken.\\n */\\n function _takeFeeFrom(\\n uint256 _projectId,\\n JBFundingCycle memory _fundingCycle,\\n uint256 _amount,\\n address _beneficiary,\\n uint256 _feeDiscount\\n ) internal returns (uint256 feeAmount) {\\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\\n\\n if (_fundingCycle.shouldHoldFees()) {\\n // Store the held fee.\\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\\n\\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\\n } else {\\n // Process the fee.\\n _processFee(feeAmount, _beneficiary); // Take the fee.\\n\\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\\n }\\n }\\n\\n /**\\n @notice\\n Process a fee of the specified amount.\\n\\n @param _amount The fee amount, as a floating point number with 18 decimals.\\n @param _beneficiary The address to mint the platform's tokens for.\\n */\\n function _processFee(uint256 _amount, address _beneficiary) internal {\\n // Get the terminal for the protocol project.\\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\\n\\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\\n if (_terminal == this)\\n _pay(\\n _amount,\\n address(this),\\n _FEE_BENEFICIARY_PROJECT_ID,\\n _beneficiary,\\n 0,\\n false,\\n '',\\n bytes('')\\n ); // Use the local pay call.\\n else {\\n // Trigger any inherited pre-transfer logic.\\n _beforeTransferTo(address(_terminal), _amount);\\n\\n // If this terminal's token is ETH, send it in msg.value.\\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _amount : 0;\\n\\n // Send the payment.\\n _terminal.pay{value: _payableValue}(\\n _FEE_BENEFICIARY_PROJECT_ID,\\n _amount,\\n token,\\n _beneficiary,\\n 0,\\n false,\\n '',\\n bytes('')\\n ); // Use the external pay call of the correct terminal.\\n }\\n }\\n\\n /**\\n @notice\\n Contribute tokens to a project.\\n\\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\\n @param _payer The address making the payment.\\n @param _projectId The ID of the project being paid.\\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\\n\\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\\n */\\n function _pay(\\n uint256 _amount,\\n address _payer,\\n uint256 _projectId,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string memory _memo,\\n bytes memory _metadata\\n ) internal returns (uint256 beneficiaryTokenCount) {\\n // Cant send tokens to the zero address.\\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\\n\\n // Define variables that will be needed outside the scoped section below.\\n // Keep a reference to the funding cycle during which the payment is being made.\\n JBFundingCycle memory _fundingCycle;\\n\\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\\n {\\n JBPayDelegateAllocation[] memory _delegateAllocations;\\n uint256 _tokenCount;\\n\\n // Bundle the amount info into a JBTokenAmount struct.\\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\\n\\n // Record the payment.\\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\\n _payer,\\n _bundledAmount,\\n _projectId,\\n baseWeightCurrency,\\n _beneficiary,\\n _memo,\\n _metadata\\n );\\n\\n // Mint the tokens if needed.\\n if (_tokenCount > 0)\\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\\n _projectId,\\n _tokenCount,\\n _beneficiary,\\n '',\\n _preferClaimedTokens,\\n true\\n );\\n\\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\\n\\n // If delegate allocations were specified by the data source, fulfill them.\\n if (_delegateAllocations.length != 0) {\\n // Keep a reference to the token amount being forwarded to the delegate.\\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\\n\\n JBDidPayData memory _data = JBDidPayData(\\n _payer,\\n _projectId,\\n _fundingCycle.configuration,\\n _bundledAmount,\\n _forwardedAmount,\\n beneficiaryTokenCount,\\n _beneficiary,\\n _preferClaimedTokens,\\n _memo,\\n _metadata\\n );\\n\\n // Get a reference to the number of delegates to allocate to.\\n uint256 _numDelegates = _delegateAllocations.length;\\n\\n for (uint256 _i; _i < _numDelegates; ) {\\n // Get a reference to the delegate being iterated on.\\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\\n\\n // Trigger any inherited pre-transfer logic.\\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\\n\\n // Keep track of the msg.value to use in the delegate call\\n uint256 _payableValue;\\n\\n // If this terminal's token is ETH, send it in msg.value.\\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\\n\\n // Pass the correct token forwardedAmount to the delegate\\n _data.forwardedAmount.value = _delegateAllocation.amount;\\n\\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\\n\\n emit DelegateDidPay(\\n _delegateAllocation.delegate,\\n _data,\\n _delegateAllocation.amount,\\n msg.sender\\n );\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n }\\n\\n emit Pay(\\n _fundingCycle.configuration,\\n _fundingCycle.number,\\n _projectId,\\n _payer,\\n _beneficiary,\\n _amount,\\n beneficiaryTokenCount,\\n _memo,\\n _metadata,\\n msg.sender\\n );\\n }\\n\\n /**\\n @notice\\n Receives funds belonging to the specified project.\\n\\n @param _projectId The ID of the project to which the funds received belong.\\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Extra data to pass along to the emitted event.\\n */\\n function _addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n bool _shouldRefundHeldFees,\\n string memory _memo,\\n bytes memory _metadata\\n ) internal {\\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\\n\\n // Record the added funds with any refunded fees.\\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\\n\\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\\n }\\n\\n /**\\n @notice\\n Refund fees based on the specified amount.\\n\\n @param _projectId The project for which fees are being refunded.\\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\\n\\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\\n */\\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\\n internal\\n returns (uint256 refundedFees)\\n {\\n // Get a reference to the project's held fees.\\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\\n\\n // Delete the current held fees.\\n delete _heldFeesOf[_projectId];\\n\\n // Get a reference to the leftover amount once all fees have been settled.\\n uint256 leftoverAmount = _amount;\\n\\n // Push length in stack\\n uint256 _heldFeesLength = _heldFees.length;\\n\\n // Process each fee.\\n for (uint256 _i; _i < _heldFeesLength; ) {\\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\\n else if (leftoverAmount >= _heldFees[_i].amount) {\\n unchecked {\\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\\n refundedFees += _feeAmount(\\n _heldFees[_i].amount,\\n _heldFees[_i].fee,\\n _heldFees[_i].feeDiscount\\n );\\n }\\n } else {\\n unchecked {\\n _heldFeesOf[_projectId].push(\\n JBFee(\\n _heldFees[_i].amount - leftoverAmount,\\n _heldFees[_i].fee,\\n _heldFees[_i].feeDiscount,\\n _heldFees[_i].beneficiary\\n )\\n );\\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\\n }\\n leftoverAmount = 0;\\n }\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n\\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\\n }\\n\\n /** \\n @notice \\n Returns the fee amount based on the provided amount for the specified project.\\n\\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\\n @param _fee The percentage of the fee, out of MAX_FEE. \\n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\\n\\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\\n */\\n function _feeAmount(\\n uint256 _amount,\\n uint256 _fee,\\n uint256 _feeDiscount\\n ) internal pure returns (uint256) {\\n // Calculate the discounted fee.\\n uint256 _discountedFee = _fee -\\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\\n\\n // The amount of tokens from the `_amount` to pay as a fee.\\n return\\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\\n }\\n\\n /** \\n @notice\\n Get the fee discount from the fee gauge for the specified project.\\n\\n @param _projectId The ID of the project to get a fee discount for.\\n \\n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\\n */\\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\\n if (\\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\\n IJBPaymentTerminal(address(0))\\n ) return JBConstants.MAX_FEE_DISCOUNT;\\n\\n // Get the fee discount.\\n if (feeGauge != IJBFeeGauge(address(0)))\\n // If the guage reverts, keep the discount at 0.\\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\\n // If the fee discount is greater than the max, we ignore the return value\\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\\n } catch {\\n return 0;\\n }\\n\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0xbd19927d16eca865a8c894bed895c2704fa17ef361b97f90310b5ff0d43d9036\",\"license\":\"MIT\"},\"contracts/abstract/JBSingleTokenPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\\nimport './../interfaces/IJBSingleTokenPaymentTerminal.sol';\\n\\n/**\\n @notice\\n Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\\n\\n @dev\\n Adheres to -\\n IJBSingleTokenPaymentTerminals: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n\\n @dev\\n Inherits from -\\n ERC165: Introspection on interface adherance. \\n*/\\nabstract contract JBSingleTokenPaymentTerminal is ERC165, IJBSingleTokenPaymentTerminal {\\n //*********************************************************************//\\n // ---------------- public immutable stored properties --------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The token that this terminal accepts.\\n */\\n address public immutable override token;\\n\\n /**\\n @notice\\n The number of decimals the token fixed point amounts are expected to have.\\n */\\n uint256 public immutable override decimals;\\n\\n /**\\n @notice\\n The currency to use when resolving price feeds for this terminal.\\n */\\n uint256 public immutable override currency;\\n\\n //*********************************************************************//\\n // ------------------------- external views -------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n A flag indicating if this terminal accepts the specified token.\\n\\n @param _token The token to check if this terminal accepts or not.\\n @param _projectId The project ID to check for token acceptance.\\n\\n @return The flag.\\n */\\n function acceptsToken(address _token, uint256 _projectId) external view override returns (bool) {\\n _projectId; // Prevents unused var compiler and natspec complaints.\\n\\n return _token == token;\\n }\\n\\n /** \\n @notice\\n The decimals that should be used in fixed number accounting for the specified token.\\n\\n @param _token The token to check for the decimals of.\\n\\n @return The number of decimals for the token.\\n */\\n function decimalsForToken(address _token) external view override returns (uint256) {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n return decimals;\\n }\\n\\n /** \\n @notice\\n The currency that should be used for the specified token.\\n\\n @param _token The token to check for the currency of.\\n\\n @return The currency index.\\n */\\n function currencyForToken(address _token) external view override returns (uint256) {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n return currency;\\n }\\n\\n //*********************************************************************//\\n // -------------------------- public views --------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Indicates if this contract adheres to the specified interface.\\n\\n @dev \\n See {IERC165-supportsInterface}.\\n\\n @param _interfaceId The ID of the interface to check for adherance to.\\n */\\n function supportsInterface(bytes4 _interfaceId)\\n public\\n view\\n virtual\\n override(ERC165, IERC165)\\n returns (bool)\\n {\\n return\\n _interfaceId == type(IJBPaymentTerminal).interfaceId ||\\n _interfaceId == type(IJBSingleTokenPaymentTerminal).interfaceId ||\\n super.supportsInterface(_interfaceId);\\n }\\n\\n //*********************************************************************//\\n // -------------------------- constructor ---------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @param _token The token that this terminal manages.\\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\\n @param _currency The currency that this terminal's token adheres to for price feeds.\\n */\\n constructor(\\n address _token,\\n uint256 _decimals,\\n uint256 _currency\\n ) {\\n token = _token;\\n decimals = _decimals;\\n currency = _currency;\\n }\\n}\\n\",\"keccak256\":\"0xdc82ad3e01b918d3d21ffea8c9f30950d81e225137c851599d028dcd22125f89\",\"license\":\"MIT\"},\"contracts/enums/JBBallotState.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nenum JBBallotState {\\n Active,\\n Approved,\\n Failed\\n}\\n\",\"keccak256\":\"0x891fcac63470398b3a11239da7feba6b07d640809fcefd2404303b823d7378f8\",\"license\":\"MIT\"},\"contracts/interfaces/IJBAllowanceTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBAllowanceTerminal {\\n function useAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n address _token,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string calldata _memo\\n ) external returns (uint256 netDistributedAmount);\\n}\\n\",\"keccak256\":\"0x139d7628da9fc8510f53482d592cd4074d21c0cb6d72510ff2743076f3b17533\",\"license\":\"MIT\"},\"contracts/interfaces/IJBController.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBFundAccessConstraints.sol';\\nimport './../structs/JBFundingCycleData.sol';\\nimport './../structs/JBFundingCycleMetadata.sol';\\nimport './../structs/JBGroupedSplits.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBMigratable.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBSplitsStore.sol';\\nimport './IJBTokenStore.sol';\\n\\ninterface IJBController is IERC165 {\\n event LaunchProject(uint256 configuration, uint256 projectId, string memo, address caller);\\n\\n event LaunchFundingCycles(uint256 configuration, uint256 projectId, string memo, address caller);\\n\\n event ReconfigureFundingCycles(\\n uint256 configuration,\\n uint256 projectId,\\n string memo,\\n address caller\\n );\\n\\n event SetFundAccessConstraints(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n JBFundAccessConstraints constraints,\\n address caller\\n );\\n\\n event DistributeReservedTokens(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address beneficiary,\\n uint256 tokenCount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n address caller\\n );\\n\\n event DistributeToReservedTokenSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n uint256 tokenCount,\\n address caller\\n );\\n\\n event MintTokens(\\n address indexed beneficiary,\\n uint256 indexed projectId,\\n uint256 tokenCount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n uint256 reservedRate,\\n address caller\\n );\\n\\n event BurnTokens(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 tokenCount,\\n string memo,\\n address caller\\n );\\n\\n event Migrate(uint256 indexed projectId, IJBMigratable to, address caller);\\n\\n event PrepMigration(uint256 indexed projectId, address from, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function tokenStore() external view returns (IJBTokenStore);\\n\\n function splitsStore() external view returns (IJBSplitsStore);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function reservedTokenBalanceOf(uint256 _projectId, uint256 _reservedRate)\\n external\\n view\\n returns (uint256);\\n\\n function distributionLimitOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n IJBPaymentTerminal _terminal,\\n address _token\\n ) external view returns (uint256 distributionLimit, uint256 distributionLimitCurrency);\\n\\n function overflowAllowanceOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n IJBPaymentTerminal _terminal,\\n address _token\\n ) external view returns (uint256 overflowAllowance, uint256 overflowAllowanceCurrency);\\n\\n function totalOutstandingTokensOf(uint256 _projectId, uint256 _reservedRate)\\n external\\n view\\n returns (uint256);\\n\\n function getFundingCycleOf(uint256 _projectId, uint256 _configuration)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function latestConfiguredFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (\\n JBFundingCycle memory,\\n JBFundingCycleMetadata memory metadata,\\n JBBallotState\\n );\\n\\n function currentFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function queuedFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function launchProjectFor(\\n address _owner,\\n JBProjectMetadata calldata _projectMetadata,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n IJBPaymentTerminal[] memory _terminals,\\n string calldata _memo\\n ) external returns (uint256 projectId);\\n\\n function launchFundingCyclesFor(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n IJBPaymentTerminal[] memory _terminals,\\n string calldata _memo\\n ) external returns (uint256 configuration);\\n\\n function reconfigureFundingCyclesOf(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n string calldata _memo\\n ) external returns (uint256);\\n\\n function mintTokensOf(\\n uint256 _projectId,\\n uint256 _tokenCount,\\n address _beneficiary,\\n string calldata _memo,\\n bool _preferClaimedTokens,\\n bool _useReservedRate\\n ) external returns (uint256 beneficiaryTokenCount);\\n\\n function burnTokensOf(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n string calldata _memo,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function distributeReservedTokensOf(uint256 _projectId, string memory _memo)\\n external\\n returns (uint256);\\n\\n function migrate(uint256 _projectId, IJBMigratable _to) external;\\n}\\n\",\"keccak256\":\"0xb1ee4b41f2a06f28f69c74cb729b8964f2e75f3c545a68f85bd9082b5575bc85\",\"license\":\"MIT\"},\"contracts/interfaces/IJBDirectory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBProjects.sol';\\n\\ninterface IJBDirectory {\\n event SetController(uint256 indexed projectId, address indexed controller, address caller);\\n\\n event AddTerminal(uint256 indexed projectId, IJBPaymentTerminal indexed terminal, address caller);\\n\\n event SetTerminals(uint256 indexed projectId, IJBPaymentTerminal[] terminals, address caller);\\n\\n event SetPrimaryTerminal(\\n uint256 indexed projectId,\\n address indexed token,\\n IJBPaymentTerminal indexed terminal,\\n address caller\\n );\\n\\n event SetIsAllowedToSetFirstController(address indexed addr, bool indexed flag, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function controllerOf(uint256 _projectId) external view returns (address);\\n\\n function isAllowedToSetFirstController(address _address) external view returns (bool);\\n\\n function terminalsOf(uint256 _projectId) external view returns (IJBPaymentTerminal[] memory);\\n\\n function isTerminalOf(uint256 _projectId, IJBPaymentTerminal _terminal)\\n external\\n view\\n returns (bool);\\n\\n function primaryTerminalOf(uint256 _projectId, address _token)\\n external\\n view\\n returns (IJBPaymentTerminal);\\n\\n function setControllerOf(uint256 _projectId, address _controller) external;\\n\\n function setTerminalsOf(uint256 _projectId, IJBPaymentTerminal[] calldata _terminals) external;\\n\\n function setPrimaryTerminalOf(\\n uint256 _projectId,\\n address _token,\\n IJBPaymentTerminal _terminal\\n ) external;\\n\\n function setIsAllowedToSetFirstController(address _address, bool _flag) external;\\n}\\n\",\"keccak256\":\"0x715321646db00514d1355ed43c40cd3f01e94959552fd07797b315d9c49cdb1d\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFeeGauge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBFeeGauge {\\n function currentDiscountFor(uint256 _projectId) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x8e19959617191320fe1210760860e668a57319258c0c74fcfabac829ae0222c0\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleBallot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../enums/JBBallotState.sol';\\n\\ninterface IJBFundingCycleBallot is IERC165 {\\n function duration() external view returns (uint256);\\n\\n function stateOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n uint256 _start\\n ) external view returns (JBBallotState);\\n}\\n\",\"keccak256\":\"0x49553a56209237846bc400cf27f260824a6bd06fd8094a7eb5abb9de75779598\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../enums/JBBallotState.sol';\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBFundingCycleData.sol';\\n\\ninterface IJBFundingCycleStore {\\n event Configure(\\n uint256 indexed configuration,\\n uint256 indexed projectId,\\n JBFundingCycleData data,\\n uint256 metadata,\\n uint256 mustStartAtOrAfter,\\n address caller\\n );\\n\\n event Init(uint256 indexed configuration, uint256 indexed projectId, uint256 indexed basedOn);\\n\\n function latestConfigurationOf(uint256 _projectId) external view returns (uint256);\\n\\n function get(uint256 _projectId, uint256 _configuration)\\n external\\n view\\n returns (JBFundingCycle memory);\\n\\n function latestConfiguredOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBBallotState ballotState);\\n\\n function queuedOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentBallotStateOf(uint256 _projectId) external view returns (JBBallotState);\\n\\n function configureFor(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n uint256 _metadata,\\n uint256 _mustStartAtOrAfter\\n ) external returns (JBFundingCycle memory fundingCycle);\\n}\\n\",\"keccak256\":\"0xaead823851433be0c2ddc8f8086813e6cd647de3a1bc0f7570a5d6b38c378b5a\",\"license\":\"MIT\"},\"contracts/interfaces/IJBMigratable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBMigratable {\\n function prepForMigrationOf(uint256 _projectId, address _from) external;\\n}\\n\",\"keccak256\":\"0xc81053e4b4754fc510aa04fecd3ab1460f01e3e27761e7a8c94f631a978ae127\",\"license\":\"MIT\"},\"contracts/interfaces/IJBOperatable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBOperatorStore.sol';\\n\\ninterface IJBOperatable {\\n function operatorStore() external view returns (IJBOperatorStore);\\n}\\n\",\"keccak256\":\"0x09a55a91c6ce3625379334271d236cfa47bf36522a91568b406bf06f7239407e\",\"license\":\"MIT\"},\"contracts/interfaces/IJBOperatorStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBOperatorData.sol';\\n\\ninterface IJBOperatorStore {\\n event SetOperator(\\n address indexed operator,\\n address indexed account,\\n uint256 indexed domain,\\n uint256[] permissionIndexes,\\n uint256 packed\\n );\\n\\n function permissionsOf(\\n address _operator,\\n address _account,\\n uint256 _domain\\n ) external view returns (uint256);\\n\\n function hasPermission(\\n address _operator,\\n address _account,\\n uint256 _domain,\\n uint256 _permissionIndex\\n ) external view returns (bool);\\n\\n function hasPermissions(\\n address _operator,\\n address _account,\\n uint256 _domain,\\n uint256[] calldata _permissionIndexes\\n ) external view returns (bool);\\n\\n function setOperator(JBOperatorData calldata _operatorData) external;\\n\\n function setOperators(JBOperatorData[] calldata _operatorData) external;\\n}\\n\",\"keccak256\":\"0x17f4929812a356984795fafed8cb2be816a025c9a0771d85595ac0b5ff3cffc5\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPayDelegate.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBDidPayData.sol';\\n\\n/**\\n @title\\n Pay delegate\\n\\n @notice\\n Delegate called after JBTerminal.pay(..) logic completion (if passed by the funding cycle datasource)\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n*/\\ninterface IJBPayDelegate is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.pay(..), after the execution of its logic\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control\\n \\n @param _data the data passed by the terminal, as a JBDidPayData struct:\\n address payer;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n JBTokenAmount amount;\\n JBTokenAmount forwardedAmount;\\n uint256 projectTokenCount;\\n address beneficiary;\\n bool preferClaimedTokens;\\n string memo;\\n bytes metadata;\\n */\\n function didPay(JBDidPayData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0xa797de18b69eceba117e1f0b3810cf3cc2d2791417d580a5bdc510d1b868ab26\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\n\\ninterface IJBPaymentTerminal is IERC165 {\\n function acceptsToken(address _token, uint256 _projectId) external view returns (bool);\\n\\n function currencyForToken(address _token) external view returns (uint256);\\n\\n function decimalsForToken(address _token) external view returns (uint256);\\n\\n // Return value must be a fixed point number with 18 decimals.\\n function currentEthOverflowOf(uint256 _projectId) external view returns (uint256);\\n\\n function pay(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable returns (uint256 beneficiaryTokenCount);\\n\\n function addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable;\\n}\\n\",\"keccak256\":\"0xb7826f5ed609359ce322c09e83236c47ba385df1c3cad3607e56fd0a2e00eee2\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPayoutRedemptionPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBFee.sol';\\nimport './IJBAllowanceTerminal.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFeeGauge.sol';\\nimport './IJBPayDelegate.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBPayoutTerminal.sol';\\nimport './IJBPrices.sol';\\nimport './IJBProjects.sol';\\nimport './IJBRedemptionDelegate.sol';\\nimport './IJBRedemptionTerminal.sol';\\nimport './IJBSingleTokenPaymentTerminalStore.sol';\\nimport './IJBSplitsStore.sol';\\n\\ninterface IJBPayoutRedemptionPaymentTerminal is\\n IJBPaymentTerminal,\\n IJBPayoutTerminal,\\n IJBAllowanceTerminal,\\n IJBRedemptionTerminal\\n{\\n event AddToBalance(\\n uint256 indexed projectId,\\n uint256 amount,\\n uint256 refundedFees,\\n string memo,\\n bytes metadata,\\n address caller\\n );\\n\\n event Migrate(\\n uint256 indexed projectId,\\n IJBPaymentTerminal indexed to,\\n uint256 amount,\\n address caller\\n );\\n\\n event DistributePayouts(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address beneficiary,\\n uint256 amount,\\n uint256 distributedAmount,\\n uint256 fee,\\n uint256 beneficiaryDistributionAmount,\\n string memo,\\n address caller\\n );\\n\\n event UseAllowance(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address beneficiary,\\n uint256 amount,\\n uint256 distributedAmount,\\n uint256 netDistributedamount,\\n string memo,\\n address caller\\n );\\n\\n event HoldFee(\\n uint256 indexed projectId,\\n uint256 indexed amount,\\n uint256 indexed fee,\\n uint256 feeDiscount,\\n address beneficiary,\\n address caller\\n );\\n\\n event ProcessFee(\\n uint256 indexed projectId,\\n uint256 indexed amount,\\n bool indexed wasHeld,\\n address beneficiary,\\n address caller\\n );\\n\\n event RefundHeldFees(\\n uint256 indexed projectId,\\n uint256 indexed amount,\\n uint256 indexed refundedFees,\\n uint256 leftoverAmount,\\n address caller\\n );\\n\\n event Pay(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address payer,\\n address beneficiary,\\n uint256 amount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n bytes metadata,\\n address caller\\n );\\n\\n event DelegateDidPay(\\n IJBPayDelegate indexed delegate,\\n JBDidPayData data,\\n uint256 delegatedAmount,\\n address caller\\n );\\n\\n event RedeemTokens(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address holder,\\n address beneficiary,\\n uint256 tokenCount,\\n uint256 reclaimedAmount,\\n string memo,\\n bytes metadata,\\n address caller\\n );\\n\\n event DelegateDidRedeem(\\n IJBRedemptionDelegate indexed delegate,\\n JBDidRedeemData data,\\n uint256 delegatedAmount,\\n address caller\\n );\\n\\n event DistributeToPayoutSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n uint256 amount,\\n address caller\\n );\\n\\n event SetFee(uint256 fee, address caller);\\n\\n event SetFeeGauge(IJBFeeGauge indexed feeGauge, address caller);\\n\\n event SetFeelessAddress(address indexed addrs, bool indexed flag, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function splitsStore() external view returns (IJBSplitsStore);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function prices() external view returns (IJBPrices);\\n\\n function store() external view returns (IJBSingleTokenPaymentTerminalStore);\\n\\n function baseWeightCurrency() external view returns (uint256);\\n\\n function payoutSplitsGroup() external view returns (uint256);\\n\\n function heldFeesOf(uint256 _projectId) external view returns (JBFee[] memory);\\n\\n function fee() external view returns (uint256);\\n\\n function feeGauge() external view returns (IJBFeeGauge);\\n\\n function isFeelessAddress(address _contract) external view returns (bool);\\n\\n function migrate(uint256 _projectId, IJBPaymentTerminal _to) external returns (uint256 balance);\\n\\n function processFees(uint256 _projectId) external;\\n\\n function setFee(uint256 _fee) external;\\n\\n function setFeeGauge(IJBFeeGauge _feeGauge) external;\\n\\n function setFeelessAddress(address _contract, bool _flag) external;\\n}\\n\",\"keccak256\":\"0x5cd280eda38ee2d6e50604576e9260a788bf89b55dd7801a3ed1e8f876920450\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPayoutTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBPayoutTerminal {\\n function distributePayoutsOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n address _token,\\n uint256 _minReturnedTokens,\\n string calldata _memo\\n ) external returns (uint256 netLeftoverDistributionAmount);\\n}\\n\",\"keccak256\":\"0xbb556a74e4f82e9d65c3d1c40120bc57487440844b7bcf8c66935748aeab2dbd\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPriceFeed.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBPriceFeed {\\n function currentPrice(uint256 _targetDecimals) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x57c71282fec1b34b00cf991ffed2e36031c393e35bfa7ca5d723eb6572fb7122\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPrices.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBPriceFeed.sol';\\n\\ninterface IJBPrices {\\n event AddFeed(uint256 indexed currency, uint256 indexed base, IJBPriceFeed feed);\\n\\n function feedFor(uint256 _currency, uint256 _base) external view returns (IJBPriceFeed);\\n\\n function priceFor(\\n uint256 _currency,\\n uint256 _base,\\n uint256 _decimals\\n ) external view returns (uint256);\\n\\n function addFeedFor(\\n uint256 _currency,\\n uint256 _base,\\n IJBPriceFeed _priceFeed\\n ) external;\\n}\\n\",\"keccak256\":\"0x82a175b1f4b95b506c98406576cd59cbe04615e3df24f9cf3587b61b8ee323b1\",\"license\":\"MIT\"},\"contracts/interfaces/IJBProjects.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBTokenUriResolver.sol';\\n\\ninterface IJBProjects is IERC721 {\\n event Create(\\n uint256 indexed projectId,\\n address indexed owner,\\n JBProjectMetadata metadata,\\n address caller\\n );\\n\\n event SetMetadata(uint256 indexed projectId, JBProjectMetadata metadata, address caller);\\n\\n event SetTokenUriResolver(IJBTokenUriResolver indexed resolver, address caller);\\n\\n function count() external view returns (uint256);\\n\\n function metadataContentOf(uint256 _projectId, uint256 _domain)\\n external\\n view\\n returns (string memory);\\n\\n function tokenUriResolver() external view returns (IJBTokenUriResolver);\\n\\n function createFor(address _owner, JBProjectMetadata calldata _metadata)\\n external\\n returns (uint256 projectId);\\n\\n function setMetadataOf(uint256 _projectId, JBProjectMetadata calldata _metadata) external;\\n\\n function setTokenUriResolver(IJBTokenUriResolver _newResolver) external;\\n}\\n\",\"keccak256\":\"0x7cfc021d0bd7e73b1ba8f4845d7d35e3419d6a14d3d25ca3a8010e7f91062fe4\",\"license\":\"MIT\"},\"contracts/interfaces/IJBRedemptionDelegate.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBDidRedeemData.sol';\\n\\n/**\\n @title\\n Redemption delegate\\n\\n @notice\\n Delegate called after JBTerminal.redeemTokensOf(..) logic completion (if passed by the funding cycle datasource)\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n*/\\ninterface IJBRedemptionDelegate is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.redeemTokensOf(..), after the execution of its logic\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control\\n \\n @param _data the data passed by the terminal, as a JBDidRedeemData struct:\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 projectTokenCount;\\n JBTokenAmount reclaimedAmount;\\n JBTokenAmount forwardedAmount;\\n address payable beneficiary;\\n string memo;\\n bytes metadata;\\n */\\n function didRedeem(JBDidRedeemData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0x172d2c0be65e72e54f71ae521907067f0fa30e8ca05c4f88826903208aa437e2\",\"license\":\"MIT\"},\"contracts/interfaces/IJBRedemptionTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBRedemptionTerminal {\\n function redeemTokensOf(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n address _token,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external returns (uint256 reclaimAmount);\\n}\\n\",\"keccak256\":\"0xe26a6a03468401b802ae5328b39a266f53b9331a1c077fcbf7719d10ba74ff44\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSingleTokenPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBPaymentTerminal.sol';\\n\\ninterface IJBSingleTokenPaymentTerminal is IJBPaymentTerminal {\\n function token() external view returns (address);\\n\\n function currency() external view returns (uint256);\\n\\n function decimals() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xf6e78323caa9af7bbf024f44b2032a83fed0394e0b3a242a6346e73c85b2e46f\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSingleTokenPaymentTerminalStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBPayDelegateAllocation.sol';\\nimport './../structs/JBRedemptionDelegateAllocation.sol';\\nimport './../structs/JBTokenAmount.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBPrices.sol';\\nimport './IJBSingleTokenPaymentTerminal.sol';\\n\\ninterface IJBSingleTokenPaymentTerminalStore {\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function prices() external view returns (IJBPrices);\\n\\n function balanceOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\\n external\\n view\\n returns (uint256);\\n\\n function usedDistributionLimitOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _fundingCycleNumber\\n ) external view returns (uint256);\\n\\n function usedOverflowAllowanceOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _fundingCycleConfiguration\\n ) external view returns (uint256);\\n\\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\\n external\\n view\\n returns (uint256);\\n\\n function currentTotalOverflowOf(\\n uint256 _projectId,\\n uint256 _decimals,\\n uint256 _currency\\n ) external view returns (uint256);\\n\\n function currentReclaimableOverflowOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n bool _useTotalOverflow\\n ) external view returns (uint256);\\n\\n function currentReclaimableOverflowOf(\\n uint256 _projectId,\\n uint256 _tokenCount,\\n uint256 _totalSupply,\\n uint256 _overflow\\n ) external view returns (uint256);\\n\\n function recordPaymentFrom(\\n address _payer,\\n JBTokenAmount memory _amount,\\n uint256 _projectId,\\n uint256 _baseWeightCurrency,\\n address _beneficiary,\\n string calldata _memo,\\n bytes calldata _metadata\\n )\\n external\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 tokenCount,\\n JBPayDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n );\\n\\n function recordRedemptionFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n string calldata _memo,\\n bytes calldata _metadata\\n )\\n external\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 reclaimAmount,\\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n );\\n\\n function recordDistributionFor(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n ) external returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount);\\n\\n function recordUsedAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n ) external returns (JBFundingCycle memory fundingCycle, uint256 withdrawnAmount);\\n\\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external;\\n\\n function recordMigration(uint256 _projectId) external returns (uint256 balance);\\n}\\n\",\"keccak256\":\"0xd78929c9371fd7895b829ef5e4ad4b3786523c3580ac3f6f5f25d2b5941c0dd3\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSplitAllocator.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport '../structs/JBSplitAllocationData.sol';\\n\\n/**\\n @title\\n Split allocator\\n\\n @notice\\n Provide a way to process a single split with extra logic\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n\\n @dev\\n The contract address should be set as an allocator in the adequate split\\n*/\\ninterface IJBSplitAllocator is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.distributePayoutOf(..), during the processing of the split including it\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control. The token and/or eth are optimistically transfered\\n to the allocator for its logic.\\n \\n @param _data the data passed by the terminal, as a JBSplitAllocationData struct:\\n address token;\\n uint256 amount;\\n uint256 decimals;\\n uint256 projectId;\\n uint256 group;\\n JBSplit split;\\n */\\n function allocate(JBSplitAllocationData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0x5efb6f51fc161f42ff58989386ad99028e4039a0ba897d66f358c3dfcf686105\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSplitsStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBGroupedSplits.sol';\\nimport './../structs/JBSplit.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBProjects.sol';\\n\\ninterface IJBSplitsStore {\\n event SetSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n address caller\\n );\\n\\n function projects() external view returns (IJBProjects);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function splitsOf(\\n uint256 _projectId,\\n uint256 _domain,\\n uint256 _group\\n ) external view returns (JBSplit[] memory);\\n\\n function set(\\n uint256 _projectId,\\n uint256 _domain,\\n JBGroupedSplits[] memory _groupedSplits\\n ) external;\\n}\\n\",\"keccak256\":\"0x66dab3dd394e318b850401ca92c2963b906cc0ad5562fa5d4f6f850175d1c77a\",\"license\":\"MIT\"},\"contracts/interfaces/IJBToken.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBToken {\\n function projectId() external view returns (uint256);\\n\\n function decimals() external view returns (uint8);\\n\\n function totalSupply(uint256 _projectId) external view returns (uint256);\\n\\n function balanceOf(address _account, uint256 _projectId) external view returns (uint256);\\n\\n function mint(\\n uint256 _projectId,\\n address _account,\\n uint256 _amount\\n ) external;\\n\\n function burn(\\n uint256 _projectId,\\n address _account,\\n uint256 _amount\\n ) external;\\n\\n function approve(\\n uint256,\\n address _spender,\\n uint256 _amount\\n ) external;\\n\\n function transfer(\\n uint256 _projectId,\\n address _to,\\n uint256 _amount\\n ) external;\\n\\n function transferFrom(\\n uint256 _projectId,\\n address _from,\\n address _to,\\n uint256 _amount\\n ) external;\\n}\\n\",\"keccak256\":\"0xe8969210417736c85d71101bf1c0bd8ebbf9d1e62a93e758148bd5709a6c7097\",\"license\":\"MIT\"},\"contracts/interfaces/IJBTokenStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBProjects.sol';\\nimport './IJBToken.sol';\\n\\ninterface IJBTokenStore {\\n event Issue(\\n uint256 indexed projectId,\\n IJBToken indexed token,\\n string name,\\n string symbol,\\n address caller\\n );\\n\\n event Mint(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 amount,\\n bool tokensWereClaimed,\\n bool preferClaimedTokens,\\n address caller\\n );\\n\\n event Burn(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 amount,\\n uint256 initialUnclaimedBalance,\\n uint256 initialClaimedBalance,\\n bool preferClaimedTokens,\\n address caller\\n );\\n\\n event Claim(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 initialUnclaimedBalance,\\n uint256 amount,\\n address caller\\n );\\n\\n event Set(uint256 indexed projectId, IJBToken indexed newToken, address caller);\\n\\n event Transfer(\\n address indexed holder,\\n uint256 indexed projectId,\\n address indexed recipient,\\n uint256 amount,\\n address caller\\n );\\n\\n function tokenOf(uint256 _projectId) external view returns (IJBToken);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function unclaimedBalanceOf(address _holder, uint256 _projectId) external view returns (uint256);\\n\\n function unclaimedTotalSupplyOf(uint256 _projectId) external view returns (uint256);\\n\\n function totalSupplyOf(uint256 _projectId) external view returns (uint256);\\n\\n function balanceOf(address _holder, uint256 _projectId) external view returns (uint256 _result);\\n\\n function issueFor(\\n uint256 _projectId,\\n string calldata _name,\\n string calldata _symbol\\n ) external returns (IJBToken token);\\n\\n function setFor(uint256 _projectId, IJBToken _token) external;\\n\\n function burnFrom(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function mintFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function claimFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount\\n ) external;\\n\\n function transferFrom(\\n address _holder,\\n uint256 _projectId,\\n address _recipient,\\n uint256 _amount\\n ) external;\\n}\\n\",\"keccak256\":\"0x98459e3af050d41dfeffdc97f1c93330207ba450f8ff3613224b49a89eeca9c6\",\"license\":\"MIT\"},\"contracts/interfaces/IJBTokenUriResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBTokenUriResolver {\\n function getUri(uint256 _projectId) external view returns (string memory tokenUri);\\n}\\n\",\"keccak256\":\"0xd267fd8ca7c21c2c71794acdb9a98314c33a35fc559e0bf0897a6686d196d174\",\"license\":\"MIT\"},\"contracts/libraries/JBConstants.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/**\\n @notice\\n Global constants used across Juicebox contracts.\\n*/\\nlibrary JBConstants {\\n uint256 public constant MAX_RESERVED_RATE = 10_000;\\n uint256 public constant MAX_REDEMPTION_RATE = 10_000;\\n uint256 public constant MAX_DISCOUNT_RATE = 1_000_000_000;\\n uint256 public constant SPLITS_TOTAL_PERCENT = 1_000_000_000;\\n uint256 public constant MAX_FEE = 1_000_000_000;\\n uint256 public constant MAX_FEE_DISCOUNT = 1_000_000_000;\\n}\\n\",\"keccak256\":\"0x34362846a1cd428a8bdedf4ab6857e11402f345cb87b994b2e7fb6d2474b808d\",\"license\":\"MIT\"},\"contracts/libraries/JBCurrencies.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBCurrencies {\\n uint256 public constant ETH = 1;\\n uint256 public constant USD = 2;\\n}\\n\",\"keccak256\":\"0x7e417ff25c173608ee4fe6d9fc3dcd5e1458c78c889af12bac47b1189a436076\",\"license\":\"MIT\"},\"contracts/libraries/JBFixedPointNumber.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nlibrary JBFixedPointNumber {\\n function adjustDecimals(\\n uint256 _value,\\n uint256 _decimals,\\n uint256 _targetDecimals\\n ) internal pure returns (uint256) {\\n // If decimals need adjusting, multiply or divide the price by the decimal adjuster to get the normalized result.\\n if (_targetDecimals == _decimals) return _value;\\n else if (_targetDecimals > _decimals) return _value * 10**(_targetDecimals - _decimals);\\n else return _value / 10**(_decimals - _targetDecimals);\\n }\\n}\\n\",\"keccak256\":\"0x18efac48269f3a3bd7e9a1c770776f950e0afa86769e6f8b128002c3b8c6742c\",\"license\":\"MIT\"},\"contracts/libraries/JBFundingCycleMetadataResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBFundingCycleMetadata.sol';\\nimport './../structs/JBGlobalFundingCycleMetadata.sol';\\nimport './JBConstants.sol';\\nimport './JBGlobalFundingCycleMetadataResolver.sol';\\n\\nlibrary JBFundingCycleMetadataResolver {\\n function global(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (JBGlobalFundingCycleMetadata memory)\\n {\\n return JBGlobalFundingCycleMetadataResolver.expandMetadata(uint8(_fundingCycle.metadata >> 8));\\n }\\n\\n function reservedRate(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n return uint256(uint16(_fundingCycle.metadata >> 24));\\n }\\n\\n function redemptionRate(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n // Redemption rate is a number 0-10000. It's inverse was stored so the most common case of 100% results in no storage needs.\\n return JBConstants.MAX_REDEMPTION_RATE - uint256(uint16(_fundingCycle.metadata >> 40));\\n }\\n\\n function ballotRedemptionRate(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (uint256)\\n {\\n // Redemption rate is a number 0-10000. It's inverse was stored so the most common case of 100% results in no storage needs.\\n return JBConstants.MAX_REDEMPTION_RATE - uint256(uint16(_fundingCycle.metadata >> 56));\\n }\\n\\n function payPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 72) & 1) == 1;\\n }\\n\\n function distributionsPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 73) & 1) == 1;\\n }\\n\\n function redeemPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 74) & 1) == 1;\\n }\\n\\n function burnPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 75) & 1) == 1;\\n }\\n\\n function mintingAllowed(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 76) & 1) == 1;\\n }\\n\\n function terminalMigrationAllowed(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 77) & 1) == 1;\\n }\\n\\n function controllerMigrationAllowed(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 78) & 1) == 1;\\n }\\n\\n function shouldHoldFees(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 79) & 1) == 1;\\n }\\n\\n function preferClaimedTokenOverride(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 80) & 1) == 1;\\n }\\n\\n function useTotalOverflowForRedemptions(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 81) & 1) == 1;\\n }\\n\\n function useDataSourceForPay(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return (_fundingCycle.metadata >> 82) & 1 == 1;\\n }\\n\\n function useDataSourceForRedeem(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return (_fundingCycle.metadata >> 83) & 1 == 1;\\n }\\n\\n function dataSource(JBFundingCycle memory _fundingCycle) internal pure returns (address) {\\n return address(uint160(_fundingCycle.metadata >> 84));\\n }\\n\\n function metadata(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n return uint256(uint8(_fundingCycle.metadata >> 244));\\n }\\n\\n /**\\n @notice\\n Pack the funding cycle metadata.\\n\\n @param _metadata The metadata to validate and pack.\\n\\n @return packed The packed uint256 of all metadata params. The first 8 bits specify the version.\\n */\\n function packFundingCycleMetadata(JBFundingCycleMetadata memory _metadata)\\n internal\\n pure\\n returns (uint256 packed)\\n {\\n // version 1 in the bits 0-7 (8 bits).\\n packed = 1;\\n // global metadta in bits 8-23 (16 bits).\\n packed |=\\n JBGlobalFundingCycleMetadataResolver.packFundingCycleGlobalMetadata(_metadata.global) <<\\n 8;\\n // reserved rate in bits 24-39 (16 bits).\\n packed |= _metadata.reservedRate << 24;\\n // redemption rate in bits 40-55 (16 bits).\\n // redemption rate is a number 0-10000. Store the reverse so the most common case of 100% results in no storage needs.\\n packed |= (JBConstants.MAX_REDEMPTION_RATE - _metadata.redemptionRate) << 40;\\n // ballot redemption rate rate in bits 56-71 (16 bits).\\n // ballot redemption rate is a number 0-10000. Store the reverse so the most common case of 100% results in no storage needs.\\n packed |= (JBConstants.MAX_REDEMPTION_RATE - _metadata.ballotRedemptionRate) << 56;\\n // pause pay in bit 72.\\n if (_metadata.pausePay) packed |= 1 << 72;\\n // pause tap in bit 73.\\n if (_metadata.pauseDistributions) packed |= 1 << 73;\\n // pause redeem in bit 74.\\n if (_metadata.pauseRedeem) packed |= 1 << 74;\\n // pause burn in bit 75.\\n if (_metadata.pauseBurn) packed |= 1 << 75;\\n // allow minting in bit 76.\\n if (_metadata.allowMinting) packed |= 1 << 76;\\n // allow terminal migration in bit 77.\\n if (_metadata.allowTerminalMigration) packed |= 1 << 77;\\n // allow controller migration in bit 78.\\n if (_metadata.allowControllerMigration) packed |= 1 << 78;\\n // hold fees in bit 79.\\n if (_metadata.holdFees) packed |= 1 << 79;\\n // prefer claimed token override in bit 80.\\n if (_metadata.preferClaimedTokenOverride) packed |= 1 << 80;\\n // useTotalOverflowForRedemptions in bit 81.\\n if (_metadata.useTotalOverflowForRedemptions) packed |= 1 << 81;\\n // use pay data source in bit 82.\\n if (_metadata.useDataSourceForPay) packed |= 1 << 82;\\n // use redeem data source in bit 83.\\n if (_metadata.useDataSourceForRedeem) packed |= 1 << 83;\\n // data source address in bits 84-243.\\n packed |= uint256(uint160(address(_metadata.dataSource))) << 84;\\n // metadata in bits 244-252 (8 bits).\\n packed |= _metadata.metadata << 244;\\n }\\n\\n /**\\n @notice\\n Expand the funding cycle metadata.\\n\\n @param _fundingCycle The funding cycle having its metadata expanded.\\n\\n @return metadata The metadata object.\\n */\\n function expandMetadata(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (JBFundingCycleMetadata memory)\\n {\\n return\\n JBFundingCycleMetadata(\\n global(_fundingCycle),\\n reservedRate(_fundingCycle),\\n redemptionRate(_fundingCycle),\\n ballotRedemptionRate(_fundingCycle),\\n payPaused(_fundingCycle),\\n distributionsPaused(_fundingCycle),\\n redeemPaused(_fundingCycle),\\n burnPaused(_fundingCycle),\\n mintingAllowed(_fundingCycle),\\n terminalMigrationAllowed(_fundingCycle),\\n controllerMigrationAllowed(_fundingCycle),\\n shouldHoldFees(_fundingCycle),\\n preferClaimedTokenOverride(_fundingCycle),\\n useTotalOverflowForRedemptions(_fundingCycle),\\n useDataSourceForPay(_fundingCycle),\\n useDataSourceForRedeem(_fundingCycle),\\n dataSource(_fundingCycle),\\n metadata(_fundingCycle)\\n );\\n }\\n}\\n\",\"keccak256\":\"0x3d045c38593102cfb6ac67f3ddf2232e1ff5518d6d021423ae2681387599fbd3\",\"license\":\"MIT\"},\"contracts/libraries/JBGlobalFundingCycleMetadataResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport './../structs/JBFundingCycleMetadata.sol';\\n\\nlibrary JBGlobalFundingCycleMetadataResolver {\\n function setTerminalsAllowed(uint8 _data) internal pure returns (bool) {\\n return (_data & 1) == 1;\\n }\\n\\n function setControllerAllowed(uint8 _data) internal pure returns (bool) {\\n return ((_data >> 1) & 1) == 1;\\n }\\n\\n function transfersPaused(uint8 _data) internal pure returns (bool) {\\n return ((_data >> 2) & 1) == 1;\\n }\\n\\n /**\\n @notice\\n Pack the global funding cycle metadata.\\n\\n @param _metadata The metadata to validate and pack.\\n\\n @return packed The packed uint256 of all global metadata params. The first 8 bits specify the version.\\n */\\n function packFundingCycleGlobalMetadata(JBGlobalFundingCycleMetadata memory _metadata)\\n internal\\n pure\\n returns (uint256 packed)\\n {\\n // allow set terminals in bit 0.\\n if (_metadata.allowSetTerminals) packed |= 1;\\n // allow set controller in bit 1.\\n if (_metadata.allowSetController) packed |= 1 << 1;\\n // pause transfers in bit 2.\\n if (_metadata.pauseTransfers) packed |= 1 << 2;\\n }\\n\\n /**\\n @notice\\n Expand the global funding cycle metadata.\\n\\n @param _packedMetadata The packed metadata to expand.\\n\\n @return metadata The global metadata object.\\n */\\n function expandMetadata(uint8 _packedMetadata)\\n internal\\n pure\\n returns (JBGlobalFundingCycleMetadata memory metadata)\\n {\\n return\\n JBGlobalFundingCycleMetadata(\\n setTerminalsAllowed(_packedMetadata),\\n setControllerAllowed(_packedMetadata),\\n transfersPaused(_packedMetadata)\\n );\\n }\\n}\\n\",\"keccak256\":\"0x0d998f938026edeb755987a79421267cf860801161b5f171206a200b60f1061f\",\"license\":\"MIT\"},\"contracts/libraries/JBOperations.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBOperations {\\n uint256 public constant RECONFIGURE = 1;\\n uint256 public constant REDEEM = 2;\\n uint256 public constant MIGRATE_CONTROLLER = 3;\\n uint256 public constant MIGRATE_TERMINAL = 4;\\n uint256 public constant PROCESS_FEES = 5;\\n uint256 public constant SET_METADATA = 6;\\n uint256 public constant ISSUE = 7;\\n uint256 public constant SET_TOKEN = 8;\\n uint256 public constant MINT = 9;\\n uint256 public constant BURN = 10;\\n uint256 public constant CLAIM = 11;\\n uint256 public constant TRANSFER = 12;\\n uint256 public constant REQUIRE_CLAIM = 13; // unused in v3\\n uint256 public constant SET_CONTROLLER = 14;\\n uint256 public constant SET_TERMINALS = 15;\\n uint256 public constant SET_PRIMARY_TERMINAL = 16;\\n uint256 public constant USE_ALLOWANCE = 17;\\n uint256 public constant SET_SPLITS = 18;\\n}\\n\",\"keccak256\":\"0x7f8e501e6890297f4015b1c27cebdb44fadbf21204bea1f3162f5388c060f690\",\"license\":\"MIT\"},\"contracts/libraries/JBSplitsGroups.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBSplitsGroups {\\n uint256 public constant ETH_PAYOUT = 1;\\n uint256 public constant RESERVED_TOKENS = 2;\\n}\\n\",\"keccak256\":\"0x4183db6087bd8db645fc3a0d3d8afb0d6356e003650793f63c301ebbbae47269\",\"license\":\"MIT\"},\"contracts/libraries/JBTokens.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBTokens {\\n /** \\n @notice \\n The ETH token address in Juicebox is represented by 0x000000000000000000000000000000000000EEEe.\\n */\\n address public constant ETH = address(0x000000000000000000000000000000000000EEEe);\\n}\\n\",\"keccak256\":\"0xecf82992f7b827766aa55f16872517a646521eef414d8cc9786617ea377e5463\",\"license\":\"MIT\"},\"contracts/structs/JBDidPayData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member payer The address from which the payment originated.\\n @member projectId The ID of the project for which the payment was made.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the payment is being made.\\n @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.\\n @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.\\n @member projectTokenCount The number of project tokens minted for the beneficiary.\\n @member beneficiary The address to which the tokens were minted.\\n @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.\\n @member memo The memo that is being emitted alongside the payment.\\n @member metadata Extra data to send to the delegate.\\n*/\\nstruct JBDidPayData {\\n address payer;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n JBTokenAmount amount;\\n JBTokenAmount forwardedAmount;\\n uint256 projectTokenCount;\\n address beneficiary;\\n bool preferClaimedTokens;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0xf3c664309b37790f16047ae97b0459889ae0242dfcde7fc8902c8d10c7f8e6b6\",\"license\":\"MIT\"},\"contracts/structs/JBDidRedeemData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member holder The holder of the tokens being redeemed.\\n @member projectId The ID of the project with which the redeemed tokens are associated.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the redemption is being made.\\n @member projectTokenCount The number of project tokens being redeemed.\\n @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.\\n @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.\\n @member beneficiary The address to which the reclaimed amount will be sent.\\n @member memo The memo that is being emitted alongside the redemption.\\n @member metadata Extra data to send to the delegate.\\n*/\\nstruct JBDidRedeemData {\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 projectTokenCount;\\n JBTokenAmount reclaimedAmount;\\n JBTokenAmount forwardedAmount;\\n address payable beneficiary;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0xe2c401f39723a7ce915b8bef328744c66daaf57460843964b941456c2258a412\",\"license\":\"MIT\"},\"contracts/structs/JBFee.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member amount The total amount the fee was taken from, as a fixed point number with the same number of decimals as the terminal in which this struct was created.\\n @member fee The percent of the fee, out of MAX_FEE.\\n @member feeDiscount The discount of the fee.\\n @member beneficiary The address that will receive the tokens that are minted as a result of the fee payment.\\n*/\\nstruct JBFee {\\n uint256 amount;\\n uint32 fee;\\n uint32 feeDiscount;\\n address beneficiary;\\n}\\n\",\"keccak256\":\"0xf4759ff41fe7f1db0fd1ccc7b2a326b239389fd8d69df9b9ed5e1d5926f6fe38\",\"license\":\"MIT\"},\"contracts/structs/JBFundAccessConstraints.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBPaymentTerminal.sol';\\n\\n/** \\n @member terminal The terminal within which the distribution limit and the overflow allowance applies.\\n @member token The token for which the fund access constraints apply.\\n @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.\\n @member distributionLimitCurrency The currency of the distribution limit.\\n @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.\\n @member overflowAllowanceCurrency The currency of the overflow allowance.\\n*/\\nstruct JBFundAccessConstraints {\\n IJBPaymentTerminal terminal;\\n address token;\\n uint256 distributionLimit;\\n uint256 distributionLimitCurrency;\\n uint256 overflowAllowance;\\n uint256 overflowAllowanceCurrency;\\n}\\n\",\"keccak256\":\"0x85ebaa57b788cbdedc7a3d0eec4892eda5d79db7c1a6103797f10d0d989775b2\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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.\\n @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.\\n @member basedOn The `configuration` of the funding cycle that was active when this cycle was created.\\n @member start The timestamp marking the moment from which the funding cycle is considered active. It is a unix timestamp measured in seconds.\\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n @member metadata Extra data that can be associated with a funding cycle.\\n*/\\nstruct JBFundingCycle {\\n uint256 number;\\n uint256 configuration;\\n uint256 basedOn;\\n uint256 start;\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n uint256 metadata;\\n}\\n\",\"keccak256\":\"0xcdd3ac9b6fa67e62ada88d09b73bc35ade1cd77d43db712289266a788928b4c2\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycleData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n*/\\nstruct JBFundingCycleData {\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n}\\n\",\"keccak256\":\"0x2aa6368bf4dfc5797e8b02a978293de0c777fae2658de2c825a103587240f3b0\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycleMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBGlobalFundingCycleMetadata.sol';\\n\\n/** \\n @member global Data used globally in non-migratable ecosystem contracts.\\n @member reservedRate The reserved rate of the funding cycle. This number is a percentage calculated out of `JBConstants.MAX_RESERVED_RATE`.\\n @member redemptionRate The redemption rate of the funding cycle. This number is a percentage calculated out of `JBConstants.MAX_REDEMPTION_RATE`.\\n @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`.\\n @member pausePay A flag indicating if the pay functionality should be paused during the funding cycle.\\n @member pauseDistributions A flag indicating if the distribute functionality should be paused during the funding cycle.\\n @member pauseRedeem A flag indicating if the redeem functionality should be paused during the funding cycle.\\n @member pauseBurn A flag indicating if the burn functionality should be paused during the funding cycle.\\n @member allowMinting A flag indicating if minting tokens should be allowed during this funding cycle.\\n @member allowTerminalMigration A flag indicating if migrating terminals should be allowed during this funding cycle.\\n @member allowControllerMigration A flag indicating if migrating controllers should be allowed during this funding cycle.\\n @member holdFees A flag indicating if fees should be held during this funding cycle.\\n @member preferClaimedTokenOverride A flag indicating if claimed tokens should always be prefered to unclaimed tokens when minting.\\n @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.\\n @member useDataSourceForPay A flag indicating if the data source should be used for pay transactions during this funding cycle.\\n @member useDataSourceForRedeem A flag indicating if the data source should be used for redeem transactions during this funding cycle.\\n @member dataSource The data source to use during this funding cycle.\\n @member metadata Metadata of the metadata, up to uint8 in size.\\n*/\\nstruct JBFundingCycleMetadata {\\n JBGlobalFundingCycleMetadata global;\\n uint256 reservedRate;\\n uint256 redemptionRate;\\n uint256 ballotRedemptionRate;\\n bool pausePay;\\n bool pauseDistributions;\\n bool pauseRedeem;\\n bool pauseBurn;\\n bool allowMinting;\\n bool allowTerminalMigration;\\n bool allowControllerMigration;\\n bool holdFees;\\n bool preferClaimedTokenOverride;\\n bool useTotalOverflowForRedemptions;\\n bool useDataSourceForPay;\\n bool useDataSourceForRedeem;\\n address dataSource;\\n uint256 metadata;\\n}\\n\",\"keccak256\":\"0x783604440cac8d176332eab28166f188ee5c230378c08cfc95fea4f7187dc77d\",\"license\":\"MIT\"},\"contracts/structs/JBGlobalFundingCycleMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member allowSetTerminals A flag indicating if setting terminals should be allowed during this funding cycle.\\n @member allowSetController A flag indicating if setting a new controller should be allowed during this funding cycle.\\n @member pauseTransfers A flag indicating if the project token transfer functionality should be paused during the funding cycle.\\n*/\\nstruct JBGlobalFundingCycleMetadata {\\n bool allowSetTerminals;\\n bool allowSetController;\\n bool pauseTransfers;\\n}\\n\",\"keccak256\":\"0x05d85530305fec6d6eca54cdbc2cd9110cbda0146598032b0203aa4b622944ff\",\"license\":\"MIT\"},\"contracts/structs/JBGroupedSplits.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBSplit.sol';\\n\\n/** \\n @member group The group indentifier.\\n @member splits The splits to associate with the group.\\n*/\\nstruct JBGroupedSplits {\\n uint256 group;\\n JBSplit[] splits;\\n}\\n\",\"keccak256\":\"0x80be1b220da4ac04851ea540ebb94c1ec2b0442ec5bd1e88fdf78a56becd8b5a\",\"license\":\"MIT\"},\"contracts/structs/JBOperatorData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member operator The address of the operator.\\n @member domain The domain within which the operator is being given permissions. A domain of 0 is a wildcard domain, which gives an operator access to all domains.\\n @member permissionIndexes The indexes of the permissions the operator is being given.\\n*/\\nstruct JBOperatorData {\\n address operator;\\n uint256 domain;\\n uint256[] permissionIndexes;\\n}\\n\",\"keccak256\":\"0x3b85be7b69515976ee10770776283911666aceca820b0cf4e201ea4dbffeb6f0\",\"license\":\"MIT\"},\"contracts/structs/JBPayDelegateAllocation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '../interfaces/IJBPayDelegate.sol';\\n\\n/** \\n @member delegate A delegate contract to use for subsequent calls.\\n @member amount The amount to send to the delegate.\\n*/\\nstruct JBPayDelegateAllocation {\\n IJBPayDelegate delegate;\\n uint256 amount;\\n}\\n\",\"keccak256\":\"0xb4e558dc62231d89e9b48998012577d22c3e52b58e23401f22d9096827f6ea0c\",\"license\":\"MIT\"},\"contracts/structs/JBProjectMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member content The metadata content.\\n @member domain The domain within which the metadata applies.\\n*/\\nstruct JBProjectMetadata {\\n string content;\\n uint256 domain;\\n}\\n\",\"keccak256\":\"0x90ad7b1014c0a9f945fe7a2efde9d5de41e40574fa27969070b1d2ff52033ea0\",\"license\":\"MIT\"},\"contracts/structs/JBRedemptionDelegateAllocation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '../interfaces/IJBRedemptionDelegate.sol';\\n\\n/** \\n @member delegate A delegate contract to use for subsequent calls.\\n @member amount The amount to send to the delegate.\\n*/\\nstruct JBRedemptionDelegateAllocation {\\n IJBRedemptionDelegate delegate;\\n uint256 amount;\\n}\\n\",\"keccak256\":\"0x10c29d33dd0d875a0d4692a2b9a9355c2ebf433cc06a9a60253d4366b60d4d31\",\"license\":\"MIT\"},\"contracts/structs/JBSplit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBSplitAllocator.sol';\\n\\n/** \\n @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.\\n @member preferAddToBalance A flag indicating if a distribution to a project should prefer triggering it's addToBalance function instead of its pay function.\\n @member percent The percent of the whole group that this split occupies. This number is out of `JBConstants.SPLITS_TOTAL_PERCENT`.\\n @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.\\n @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.\\n @member lockedUntil Specifies if the split should be unchangeable until the specified time, with the exception of extending the locked period.\\n @member allocator If an allocator is specified, funds will be sent to the allocator contract along with all properties of this split.\\n*/\\nstruct JBSplit {\\n bool preferClaimed;\\n bool preferAddToBalance;\\n uint256 percent;\\n uint256 projectId;\\n address payable beneficiary;\\n uint256 lockedUntil;\\n IJBSplitAllocator allocator;\\n}\\n\",\"keccak256\":\"0xc80a16606da8abf76d0f73abc38aee041e24f29342c1939018f70c286e89f105\",\"license\":\"MIT\"},\"contracts/structs/JBSplitAllocationData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBSplit.sol';\\n\\n/** \\n @member token The token being sent to the split allocator.\\n @member amount The amount being sent to the split allocator, as a fixed point number.\\n @member decimals The number of decimals in the amount.\\n @member projectId The project to which the split belongs.\\n @member group The group to which the split belongs.\\n @member split The split that caused the allocation.\\n*/\\nstruct JBSplitAllocationData {\\n address token;\\n uint256 amount;\\n uint256 decimals;\\n uint256 projectId;\\n uint256 group;\\n JBSplit split;\\n}\\n\",\"keccak256\":\"0x39f5c41bd31d36774744698ac94484b6cab62d7038df2f29d947668959782e63\",\"license\":\"MIT\"},\"contracts/structs/JBTokenAmount.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/* \\n @member token The token the payment was made in.\\n @member value The amount of tokens that was paid, as a fixed point number.\\n @member decimals The number of decimals included in the value fixed point number.\\n @member currency The expected currency of the value.\\n**/\\nstruct JBTokenAmount {\\n address token;\\n uint256 value;\\n uint256 decimals;\\n uint256 currency;\\n}\\n\",\"keccak256\":\"0x4a778e779ba257ba5638c5469e07a4d21b55a3128d56db5a0fdfacb1f3301c51\",\"license\":\"MIT\"},\"prb-math/contracts/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivFixedPointOverflow(uint256 prod1);\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivOverflow(uint256 prod1, uint256 denominator);\\n\\n/// @notice Emitted when one of the inputs is type(int256).min.\\nerror PRBMath__MulDivSignedInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows int256.\\nerror PRBMath__MulDivSignedOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is MIN_SD59x18.\\nerror PRBMathSD59x18__AbsInputTooSmall();\\n\\n/// @notice Emitted when ceiling a number overflows SD59x18.\\nerror PRBMathSD59x18__CeilOverflow(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__DivInputTooSmall();\\n\\n/// @notice Emitted when one of the intermediary unsigned results overflows SD59x18.\\nerror PRBMathSD59x18__DivOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathSD59x18__ExpInputTooBig(int256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathSD59x18__Exp2InputTooBig(int256 x);\\n\\n/// @notice Emitted when flooring a number underflows SD59x18.\\nerror PRBMathSD59x18__FloorUnderflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format overflows SD59x18.\\nerror PRBMathSD59x18__FromIntOverflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format underflows SD59x18.\\nerror PRBMathSD59x18__FromIntUnderflow(int256 x);\\n\\n/// @notice Emitted when the product of the inputs is negative.\\nerror PRBMathSD59x18__GmNegativeProduct(int256 x, int256 y);\\n\\n/// @notice Emitted when multiplying the inputs overflows SD59x18.\\nerror PRBMathSD59x18__GmOverflow(int256 x, int256 y);\\n\\n/// @notice Emitted when the input is less than or equal to zero.\\nerror PRBMathSD59x18__LogInputTooSmall(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__MulInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__MulOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__PowuOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is negative.\\nerror PRBMathSD59x18__SqrtNegativeInput(int256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows SD59x18.\\nerror PRBMathSD59x18__SqrtOverflow(int256 x);\\n\\n/// @notice Emitted when addition overflows UD60x18.\\nerror PRBMathUD60x18__AddOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when ceiling a number overflows UD60x18.\\nerror PRBMathUD60x18__CeilOverflow(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathUD60x18__ExpInputTooBig(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathUD60x18__Exp2InputTooBig(uint256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format format overflows UD60x18.\\nerror PRBMathUD60x18__FromUintOverflow(uint256 x);\\n\\n/// @notice Emitted when multiplying the inputs overflows UD60x18.\\nerror PRBMathUD60x18__GmOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when the input is less than 1.\\nerror PRBMathUD60x18__LogInputTooSmall(uint256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows UD60x18.\\nerror PRBMathUD60x18__SqrtOverflow(uint256 x);\\n\\n/// @notice Emitted when subtraction underflows UD60x18.\\nerror PRBMathUD60x18__SubUnderflow(uint256 x, uint256 y);\\n\\n/// @dev Common mathematical functions used in both PRBMathSD59x18 and PRBMathUD60x18. Note that this shared library\\n/// does not always assume the signed 59.18-decimal fixed-point or the unsigned 60.18-decimal fixed-point\\n/// representation. When it does not, it is explicitly mentioned in the NatSpec documentation.\\nlibrary PRBMath {\\n /// STRUCTS ///\\n\\n struct SD59x18 {\\n int256 value;\\n }\\n\\n struct UD60x18 {\\n uint256 value;\\n }\\n\\n /// STORAGE ///\\n\\n /// @dev How many trailing decimals can be represented.\\n uint256 internal constant SCALE = 1e18;\\n\\n /// @dev Largest power of two divisor of SCALE.\\n uint256 internal constant SCALE_LPOTD = 262144;\\n\\n /// @dev SCALE inverted mod 2^256.\\n uint256 internal constant SCALE_INVERSE =\\n 78156646155174841979727994598816262306175212592076161876661_508869554232690281;\\n\\n /// FUNCTIONS ///\\n\\n /// @notice Calculates the binary exponent of x using the binary fraction method.\\n /// @dev Has to use 192.64-bit fixed-point numbers.\\n /// See https://ethereum.stackexchange.com/a/96594/24693.\\n /// @param x The exponent as an unsigned 192.64-bit fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp2(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n // Start from 0.5 in the 192.64-bit fixed-point format.\\n result = 0x800000000000000000000000000000000000000000000000;\\n\\n // Multiply the result by root(2, 2^-i) when the bit at position i is 1. None of the intermediary results overflows\\n // because the initial result is 2^191 and all magic factors are less than 2^65.\\n if (x & 0x8000000000000000 > 0) {\\n result = (result * 0x16A09E667F3BCC909) >> 64;\\n }\\n if (x & 0x4000000000000000 > 0) {\\n result = (result * 0x1306FE0A31B7152DF) >> 64;\\n }\\n if (x & 0x2000000000000000 > 0) {\\n result = (result * 0x1172B83C7D517ADCE) >> 64;\\n }\\n if (x & 0x1000000000000000 > 0) {\\n result = (result * 0x10B5586CF9890F62A) >> 64;\\n }\\n if (x & 0x800000000000000 > 0) {\\n result = (result * 0x1059B0D31585743AE) >> 64;\\n }\\n if (x & 0x400000000000000 > 0) {\\n result = (result * 0x102C9A3E778060EE7) >> 64;\\n }\\n if (x & 0x200000000000000 > 0) {\\n result = (result * 0x10163DA9FB33356D8) >> 64;\\n }\\n if (x & 0x100000000000000 > 0) {\\n result = (result * 0x100B1AFA5ABCBED61) >> 64;\\n }\\n if (x & 0x80000000000000 > 0) {\\n result = (result * 0x10058C86DA1C09EA2) >> 64;\\n }\\n if (x & 0x40000000000000 > 0) {\\n result = (result * 0x1002C605E2E8CEC50) >> 64;\\n }\\n if (x & 0x20000000000000 > 0) {\\n result = (result * 0x100162F3904051FA1) >> 64;\\n }\\n if (x & 0x10000000000000 > 0) {\\n result = (result * 0x1000B175EFFDC76BA) >> 64;\\n }\\n if (x & 0x8000000000000 > 0) {\\n result = (result * 0x100058BA01FB9F96D) >> 64;\\n }\\n if (x & 0x4000000000000 > 0) {\\n result = (result * 0x10002C5CC37DA9492) >> 64;\\n }\\n if (x & 0x2000000000000 > 0) {\\n result = (result * 0x1000162E525EE0547) >> 64;\\n }\\n if (x & 0x1000000000000 > 0) {\\n result = (result * 0x10000B17255775C04) >> 64;\\n }\\n if (x & 0x800000000000 > 0) {\\n result = (result * 0x1000058B91B5BC9AE) >> 64;\\n }\\n if (x & 0x400000000000 > 0) {\\n result = (result * 0x100002C5C89D5EC6D) >> 64;\\n }\\n if (x & 0x200000000000 > 0) {\\n result = (result * 0x10000162E43F4F831) >> 64;\\n }\\n if (x & 0x100000000000 > 0) {\\n result = (result * 0x100000B1721BCFC9A) >> 64;\\n }\\n if (x & 0x80000000000 > 0) {\\n result = (result * 0x10000058B90CF1E6E) >> 64;\\n }\\n if (x & 0x40000000000 > 0) {\\n result = (result * 0x1000002C5C863B73F) >> 64;\\n }\\n if (x & 0x20000000000 > 0) {\\n result = (result * 0x100000162E430E5A2) >> 64;\\n }\\n if (x & 0x10000000000 > 0) {\\n result = (result * 0x1000000B172183551) >> 64;\\n }\\n if (x & 0x8000000000 > 0) {\\n result = (result * 0x100000058B90C0B49) >> 64;\\n }\\n if (x & 0x4000000000 > 0) {\\n result = (result * 0x10000002C5C8601CC) >> 64;\\n }\\n if (x & 0x2000000000 > 0) {\\n result = (result * 0x1000000162E42FFF0) >> 64;\\n }\\n if (x & 0x1000000000 > 0) {\\n result = (result * 0x10000000B17217FBB) >> 64;\\n }\\n if (x & 0x800000000 > 0) {\\n result = (result * 0x1000000058B90BFCE) >> 64;\\n }\\n if (x & 0x400000000 > 0) {\\n result = (result * 0x100000002C5C85FE3) >> 64;\\n }\\n if (x & 0x200000000 > 0) {\\n result = (result * 0x10000000162E42FF1) >> 64;\\n }\\n if (x & 0x100000000 > 0) {\\n result = (result * 0x100000000B17217F8) >> 64;\\n }\\n if (x & 0x80000000 > 0) {\\n result = (result * 0x10000000058B90BFC) >> 64;\\n }\\n if (x & 0x40000000 > 0) {\\n result = (result * 0x1000000002C5C85FE) >> 64;\\n }\\n if (x & 0x20000000 > 0) {\\n result = (result * 0x100000000162E42FF) >> 64;\\n }\\n if (x & 0x10000000 > 0) {\\n result = (result * 0x1000000000B17217F) >> 64;\\n }\\n if (x & 0x8000000 > 0) {\\n result = (result * 0x100000000058B90C0) >> 64;\\n }\\n if (x & 0x4000000 > 0) {\\n result = (result * 0x10000000002C5C860) >> 64;\\n }\\n if (x & 0x2000000 > 0) {\\n result = (result * 0x1000000000162E430) >> 64;\\n }\\n if (x & 0x1000000 > 0) {\\n result = (result * 0x10000000000B17218) >> 64;\\n }\\n if (x & 0x800000 > 0) {\\n result = (result * 0x1000000000058B90C) >> 64;\\n }\\n if (x & 0x400000 > 0) {\\n result = (result * 0x100000000002C5C86) >> 64;\\n }\\n if (x & 0x200000 > 0) {\\n result = (result * 0x10000000000162E43) >> 64;\\n }\\n if (x & 0x100000 > 0) {\\n result = (result * 0x100000000000B1721) >> 64;\\n }\\n if (x & 0x80000 > 0) {\\n result = (result * 0x10000000000058B91) >> 64;\\n }\\n if (x & 0x40000 > 0) {\\n result = (result * 0x1000000000002C5C8) >> 64;\\n }\\n if (x & 0x20000 > 0) {\\n result = (result * 0x100000000000162E4) >> 64;\\n }\\n if (x & 0x10000 > 0) {\\n result = (result * 0x1000000000000B172) >> 64;\\n }\\n if (x & 0x8000 > 0) {\\n result = (result * 0x100000000000058B9) >> 64;\\n }\\n if (x & 0x4000 > 0) {\\n result = (result * 0x10000000000002C5D) >> 64;\\n }\\n if (x & 0x2000 > 0) {\\n result = (result * 0x1000000000000162E) >> 64;\\n }\\n if (x & 0x1000 > 0) {\\n result = (result * 0x10000000000000B17) >> 64;\\n }\\n if (x & 0x800 > 0) {\\n result = (result * 0x1000000000000058C) >> 64;\\n }\\n if (x & 0x400 > 0) {\\n result = (result * 0x100000000000002C6) >> 64;\\n }\\n if (x & 0x200 > 0) {\\n result = (result * 0x10000000000000163) >> 64;\\n }\\n if (x & 0x100 > 0) {\\n result = (result * 0x100000000000000B1) >> 64;\\n }\\n if (x & 0x80 > 0) {\\n result = (result * 0x10000000000000059) >> 64;\\n }\\n if (x & 0x40 > 0) {\\n result = (result * 0x1000000000000002C) >> 64;\\n }\\n if (x & 0x20 > 0) {\\n result = (result * 0x10000000000000016) >> 64;\\n }\\n if (x & 0x10 > 0) {\\n result = (result * 0x1000000000000000B) >> 64;\\n }\\n if (x & 0x8 > 0) {\\n result = (result * 0x10000000000000006) >> 64;\\n }\\n if (x & 0x4 > 0) {\\n result = (result * 0x10000000000000003) >> 64;\\n }\\n if (x & 0x2 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n if (x & 0x1 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n\\n // We're doing two things at the same time:\\n //\\n // 1. Multiply the result by 2^n + 1, where \\\"2^n\\\" is the integer part and the one is added to account for\\n // the fact that we initially set the result to 0.5. This is accomplished by subtracting from 191\\n // rather than 192.\\n // 2. Convert the result to the unsigned 60.18-decimal fixed-point format.\\n //\\n // This works because 2^(191-ip) = 2^ip / 2^191, where \\\"ip\\\" is the integer part \\\"2^n\\\".\\n result *= SCALE;\\n result >>= (191 - (x >> 64));\\n }\\n }\\n\\n /// @notice Finds the zero-based index of the first one in the binary representation of x.\\n /// @dev See the note on msb in the \\\"Find First Set\\\" Wikipedia article https://en.wikipedia.org/wiki/Find_first_set\\n /// @param x The uint256 number for which to find the index of the most significant bit.\\n /// @return msb The index of the most significant bit as an uint256.\\n function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\\n if (x >= 2**128) {\\n x >>= 128;\\n msb += 128;\\n }\\n if (x >= 2**64) {\\n x >>= 64;\\n msb += 64;\\n }\\n if (x >= 2**32) {\\n x >>= 32;\\n msb += 32;\\n }\\n if (x >= 2**16) {\\n x >>= 16;\\n msb += 16;\\n }\\n if (x >= 2**8) {\\n x >>= 8;\\n msb += 8;\\n }\\n if (x >= 2**4) {\\n x >>= 4;\\n msb += 4;\\n }\\n if (x >= 2**2) {\\n x >>= 2;\\n msb += 2;\\n }\\n if (x >= 2**1) {\\n // No need to shift x any more.\\n msb += 1;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.\\n ///\\n /// Requirements:\\n /// - The denominator cannot be zero.\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The multiplicand as an uint256.\\n /// @param y The multiplier as an uint256.\\n /// @param denominator The divisor as an uint256.\\n /// @return result The result as an uint256.\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n unchecked {\\n result = prod0 / denominator;\\n }\\n return result;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n if (prod1 >= denominator) {\\n revert PRBMath__MulDivOverflow(prod1, denominator);\\n }\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n unchecked {\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 lpotdod = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by lpotdod.\\n denominator := div(denominator, lpotdod)\\n\\n // Divide [prod1 prod0] by lpotdod.\\n prod0 := div(prod0, lpotdod)\\n\\n // Flip lpotdod such that it is 2^256 / lpotdod. If lpotdod is zero, then it becomes one.\\n lpotdod := add(div(sub(0, lpotdod), lpotdod), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * lpotdod;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f71e18) with full precision.\\n ///\\n /// @dev Variant of \\\"mulDiv\\\" with constant folding, i.e. in which the denominator is always 1e18. Before returning the\\n /// final result, we add 1 if (x * y) % SCALE >= HALF_SCALE. Without this, 6.6e-19 would be truncated to 0 instead of\\n /// being rounded to 1e-18. See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717.\\n ///\\n /// Requirements:\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - The body is purposely left uncommented; see the NatSpec comments in \\\"PRBMath.mulDiv\\\" to understand how this works.\\n /// - It is assumed that the result can never be type(uint256).max when x and y solve the following two equations:\\n /// 1. x * y = type(uint256).max * SCALE\\n /// 2. (x * y) % SCALE >= SCALE / 2\\n ///\\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function mulDivFixedPoint(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n uint256 prod0;\\n uint256 prod1;\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n if (prod1 >= SCALE) {\\n revert PRBMath__MulDivFixedPointOverflow(prod1);\\n }\\n\\n uint256 remainder;\\n uint256 roundUpUnit;\\n assembly {\\n remainder := mulmod(x, y, SCALE)\\n roundUpUnit := gt(remainder, 499999999999999999)\\n }\\n\\n if (prod1 == 0) {\\n unchecked {\\n result = (prod0 / SCALE) + roundUpUnit;\\n return result;\\n }\\n }\\n\\n assembly {\\n result := add(\\n mul(\\n or(\\n div(sub(prod0, remainder), SCALE_LPOTD),\\n mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, SCALE_LPOTD), SCALE_LPOTD), 1))\\n ),\\n SCALE_INVERSE\\n ),\\n roundUpUnit\\n )\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev An extension of \\\"mulDiv\\\" for signed numbers. Works by computing the signs and the absolute values separately.\\n ///\\n /// Requirements:\\n /// - None of the inputs can be type(int256).min.\\n /// - The result must fit within int256.\\n ///\\n /// @param x The multiplicand as an int256.\\n /// @param y The multiplier as an int256.\\n /// @param denominator The divisor as an int256.\\n /// @return result The result as an int256.\\n function mulDivSigned(\\n int256 x,\\n int256 y,\\n int256 denominator\\n ) internal pure returns (int256 result) {\\n if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {\\n revert PRBMath__MulDivSignedInputTooSmall();\\n }\\n\\n // Get hold of the absolute values of x, y and the denominator.\\n uint256 ax;\\n uint256 ay;\\n uint256 ad;\\n unchecked {\\n ax = x < 0 ? uint256(-x) : uint256(x);\\n ay = y < 0 ? uint256(-y) : uint256(y);\\n ad = denominator < 0 ? uint256(-denominator) : uint256(denominator);\\n }\\n\\n // Compute the absolute value of (x*y)\\u00f7denominator. The result must fit within int256.\\n uint256 rAbs = mulDiv(ax, ay, ad);\\n if (rAbs > uint256(type(int256).max)) {\\n revert PRBMath__MulDivSignedOverflow(rAbs);\\n }\\n\\n // Get the signs of x, y and the denominator.\\n uint256 sx;\\n uint256 sy;\\n uint256 sd;\\n assembly {\\n sx := sgt(x, sub(0, 1))\\n sy := sgt(y, sub(0, 1))\\n sd := sgt(denominator, sub(0, 1))\\n }\\n\\n // XOR over sx, sy and sd. This is checking whether there are one or three negative signs in the inputs.\\n // If yes, the result should be negative.\\n result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs);\\n }\\n\\n /// @notice Calculates the square root of x, rounding down.\\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The uint256 number for which to calculate the square root.\\n /// @return result The result as an uint256.\\n function sqrt(uint256 x) internal pure returns (uint256 result) {\\n if (x == 0) {\\n return 0;\\n }\\n\\n // Set the initial guess to the closest power of two that is higher than x.\\n uint256 xAux = uint256(x);\\n result = 1;\\n if (xAux >= 0x100000000000000000000000000000000) {\\n xAux >>= 128;\\n result <<= 64;\\n }\\n if (xAux >= 0x10000000000000000) {\\n xAux >>= 64;\\n result <<= 32;\\n }\\n if (xAux >= 0x100000000) {\\n xAux >>= 32;\\n result <<= 16;\\n }\\n if (xAux >= 0x10000) {\\n xAux >>= 16;\\n result <<= 8;\\n }\\n if (xAux >= 0x100) {\\n xAux >>= 8;\\n result <<= 4;\\n }\\n if (xAux >= 0x10) {\\n xAux >>= 4;\\n result <<= 2;\\n }\\n if (xAux >= 0x8) {\\n result <<= 1;\\n }\\n\\n // The operations can never overflow because the result is max 2^127 when it enters this block.\\n unchecked {\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1; // Seven iterations should be enough\\n uint256 roundedDownResult = x / result;\\n return result >= roundedDownResult ? roundedDownResult : result;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x62cbabae4910e168e99b9c2c3e3b5c9c7ad5e7abd961dcc63b7ea3d83d8ea87e\",\"license\":\"Unlicense\"}},\"version\":1}", "bytecode": "0x6101e060405263017d78406002553480156200001a57600080fd5b5060405162006156380380620061568339810160408190526200003d916200020a565b61eeee6080819052601260a0819052600160c08190526001600160a01b038a1660e0528a818b8b8b8b8b8b8b6200007433620000cf565b6101a08990526101c08890526001600160a01b0380871661010052858116610120528481166101405283811661016052821661018052620000b5816200011f565b5050505050505050505050505050505050505050620002bf565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000546001600160a01b031633146200017f5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b6001600160a01b038116620001e65760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840162000176565b620001f181620000cf565b50565b6001600160a01b0381168114620001f157600080fd5b600080600080600080600080610100898b0312156200022857600080fd5b8851975060208901516200023c81620001f4565b60408a01519097506200024f81620001f4565b60608a01519096506200026281620001f4565b60808a01519095506200027581620001f4565b60a08a01519094506200028881620001f4565b60c08a01519093506200029b81620001f4565b60e08a0151909250620002ae81620001f4565b809150509295985092959890939650565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c051615c4262000514600039600081816103d401526125fd01526000818161032c0152611f3a0152600081816104fc01528181610f0a015281816117b401528181611cf501528181611f080152818161247901528181612eed01526131df01526000818161064801526119520152600081816102e00152613eac0152600081816106140152818161095901528181610b650152818161200401528181612b88015281816132dc01528181613d2801526142060152600081816104aa01528181610d7a0152818161143b01528181611a0b015281816125570152612fd50152600081816105500152818161274001528181612800015281816129760152612a3601526000818161026b0152818161070001528181611884015281816118ff01528181611ee2015281816121d70152818161345b015261351a015260008181610360015281816105c00152818161182501528181611851015281816118b10152818161192c01528181611ebc015281816121b101528181613435015281816134f401526140410152600081816106be0152818161075401528181610a0401528181610c0801528181610e2b01528181610f8b0152818161101701528181611e870152818161217c015281816122b401528181612b5d01528181612c3b01528181612cc9015281816133ff015281816134bf015281816135b901528181613cfb0152818161400c01528181614098015281816142330152818161442a015281816144fc01526145750152615c426000f3fe6080604052600436106101fe5760003560e01c80638b79543c1161011d578063c41c2f24116100b0578063df21a7dd1161007f578063f2fde38b11610064578063f2fde38b14610722578063fc0c546a14610742578063fe663f0f1461077657600080fd5b8063df21a7dd146106a0578063e5a6b10f146106ee57600080fd5b8063c41c2f2414610602578063d3419bf314610636578063d6dacc531461066a578063ddca3f431461068a57600080fd5b8063ad007d63116100ec578063ad007d631461053e578063b631b50014610572578063b7bad1b1146105a2578063bc8926e9146105e257600080fd5b80638b79543c146104985780638da5cb5b146104cc578063975057e7146104ea578063a32e1e961461051e57600080fd5b8063405b84fa11610195578063715018a611610164578063715018a6146104165780637258002c1461042b57806389701db51461044b5780638af560941461046b57600080fd5b8063405b84fa14610382578063637913ac146103a257806366248b86146103c257806369fe0e2d146103f657600080fd5b80632b267b4e116101d15780632b267b4e146102ae5780632bdfe004146102ce5780632d1a59031461031a578063313ce5671461034e57600080fd5b806301ffc9a7146102035780630cf8e858146102385780631982d6791461024d5780631ebc263f1461029b575b600080fd5b34801561020f57600080fd5b5061022361021e36600461492d565b610796565b60405190151581526020015b60405180910390f35b61024b6102463660046149cd565b610922565b005b34801561025957600080fd5b5061028d610268366004614a63565b507f000000000000000000000000000000000000000000000000000000000000000090565b60405190815260200161022f565b61028d6102a9366004614a8e565b610b23565b3480156102ba57600080fd5b5061028d6102c9366004614b56565b610d2c565b3480156102da57600080fd5b506103027f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161022f565b34801561032657600080fd5b5061028d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561035a57600080fd5b5061028d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561038e57600080fd5b5061028d61039d366004614bc0565b610d48565b3480156103ae57600080fd5b5061024b6103bd366004614a63565b6110c1565b3480156103ce57600080fd5b5061028d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561040257600080fd5b5061024b610411366004614bf0565b6111a6565b34801561042257600080fd5b5061024b611298565b34801561043757600080fd5b5061024b610446366004614c09565b611318565b34801561045757600080fd5b5061024b610466366004614bf0565b61140c565b34801561047757600080fd5b5061048b610486366004614bf0565b6116c0565b60405161022f9190614c37565b3480156104a457600080fd5b506103027f000000000000000000000000000000000000000000000000000000000000000081565b3480156104d857600080fd5b506000546001600160a01b0316610302565b3480156104f657600080fd5b506103027f000000000000000000000000000000000000000000000000000000000000000081565b34801561052a57600080fd5b5061028d610539366004614bf0565b611772565b34801561054a57600080fd5b506103027f000000000000000000000000000000000000000000000000000000000000000081565b34801561057e57600080fd5b5061022361058d366004614a63565b60046020526000908152604090205460ff1681565b3480156105ae57600080fd5b5061028d6105bd366004614a63565b507f000000000000000000000000000000000000000000000000000000000000000090565b3480156105ee57600080fd5b5061028d6105fd366004614dfb565b6119d9565b34801561060e57600080fd5b506103027f000000000000000000000000000000000000000000000000000000000000000081565b34801561064257600080fd5b506103027f000000000000000000000000000000000000000000000000000000000000000081565b34801561067657600080fd5b50600354610302906001600160a01b031681565b34801561069657600080fd5b5061028d60025481565b3480156106ac57600080fd5b506102236106bb366004614e84565b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161490565b3480156106fa57600080fd5b5061028d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561072e57600080fd5b5061024b61073d366004614a63565b611aa9565b34801561074e57600080fd5b506103027f000000000000000000000000000000000000000000000000000000000000000081565b34801561078257600080fd5b5061028d610791366004614eb0565b611bbf565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167fedb527eb00000000000000000000000000000000000000000000000000000000148061082957507fffffffff0000000000000000000000000000000000000000000000000000000082167f2b267b4e00000000000000000000000000000000000000000000000000000000145b8061087557507fffffffff0000000000000000000000000000000000000000000000000000000082167fbc8926e900000000000000000000000000000000000000000000000000000000145b806108c157507fffffffff0000000000000000000000000000000000000000000000000000000082167ffe663f0f00000000000000000000000000000000000000000000000000000000145b8061090d57507fffffffff0000000000000000000000000000000000000000000000000000000082167fad007d6300000000000000000000000000000000000000000000000000000000145b8061091c575061091c82611bdf565b92915050565b6040517f6e49181f0000000000000000000000000000000000000000000000000000000081526004810188905230602482015287907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636e49181f90604401602060405180830381865afa1580156109a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109cc9190614f69565b610a02576040517fd8ead2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661eeee14610a8a573415610a6c576040517fbcfd35be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b47610a7833308a611cc2565b610a828147614fb5565b975050610a8e565b3496505b33600090815260046020908152604091829020548251601f8801839004830281018301909352868352610b19928b928b9260ff161591908a908a908190840183828082843760009201919091525050604080516020601f8c018190048102820181019092528a815292508a9150899081908401838280828437600092019190915250611cd192505050565b5050505050505050565b6040517f6e49181f000000000000000000000000000000000000000000000000000000008152600481018b90523060248201526000908b906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636e49181f90604401602060405180830381865afa158015610bac573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bd09190614f69565b610c06576040517fd8ead2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661eeee14610c8e573415610c70576040517fbcfd35be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b47610c7c33308e611cc2565b610c868147614fb5565b9b5050610c92565b349a505b610d1c8b338e8c8c8c8c8c8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611ddb92505050565b9c9b505050505050505050505050565b6000610d3c88888887878761242d565b98975050505050505050565b6040517f6352211e000000000000000000000000000000000000000000000000000000008152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610dc9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ded9190614fc8565b836004610dfb8383836126e0565b6040517fdf21a7dd0000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301526024820188905286169063df21a7dd90604401602060405180830381865afa158015610e81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea59190614f69565b610edb576040517f581010ed00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f6bb6a5ad000000000000000000000000000000000000000000000000000000008152600481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636bb6a5ad906024016020604051808303816000875af1158015610f5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f7f9190614fe5565b935083156110735760007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661eeee14610fc2576000610fc4565b845b604080516020810182526000815290517f0cf8e8580000000000000000000000000000000000000000000000000000000081529192506001600160a01b03881691630cf8e85891849161103f918c918b917f00000000000000000000000000000000000000000000000000000000000000009160040161504e565b6000604051808303818588803b15801561105857600080fd5b505af115801561106c573d6000803e3d6000fd5b5050505050505b604080518581523360208201526001600160a01b0387169188917fa7519e5f94697b7f53e97c5eb46a0c730a296ab686ab8fd333835c5f735784eb910160405180910390a350505092915050565b6000546001600160a01b0316331461113a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b600380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040513381527f0a9a80fe9716605b3e52abb3d792d6a4e7816d6afc02a5a4ef023081feaf9f609060200160405180910390a250565b6000546001600160a01b0316331461121a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611131565b6302faf080811115611258576040517f45fbd9c100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002819055604080518281523360208201527fd7414e590e1cb532989ab2a34c8f4c2c17f7ab6f006efeeaef2e87cd5008c202910160405180910390a150565b6000546001600160a01b0316331461130c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611131565b61131660006128a4565b565b6000546001600160a01b0316331461138c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611131565b6001600160a01b03821660008181526004602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001685151590811790915591513381529192917fa2653e25a502c023a5830d0de847ef6f458387865b1f4f575d7594f9f2c0d71e910160405180910390a35050565b6040517f6352211e000000000000000000000000000000000000000000000000000000008152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa15801561148a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ae9190614fc8565b8160056114c36000546001600160a01b031690565b6001600160a01b0316336001600160a01b0316146114e38484848461290c565b600085815260016020908152604080832080548251818502810185019093528083529192909190849084015b8282101561158157600084815260209081902060408051608081018252600286029092018054835260019081015463ffffffff8082168587015264010000000082041692840192909252680100000000000000009091046001600160a01b03166060830152908352909201910161150f565b50505060008881526001602052604081209293506115a09291506148ce565b805160005b81811015610b1957600061161d8483815181106115c4576115c4615094565b6020026020010151600001518584815181106115e2576115e2615094565b60200260200101516020015163ffffffff1686858151811061160657611606615094565b60200260200101516040015163ffffffff16612ae0565b90506116468185848151811061163557611635615094565b602002602001015160600151612b26565b60011515818a7fcf0c92a2c6d7c42f488326b0cb900104b99984b6b218db81cd29371364a3525187868151811061167f5761167f615094565b602002602001015160600151336040516116af9291906001600160a01b0392831681529116602082015260400190565b60405180910390a4506001016115a5565b606060016000838152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b8282101561176757600084815260209081902060408051608081018252600286029092018054835260019081015463ffffffff8082168587015264010000000082041692840192909252680100000000000000009091046001600160a01b0316606083015290835290920191016116f5565b505050509050919050565b6040517fd49031c00000000000000000000000000000000000000000000000000000000081523060048201526024810182905260009081906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063d49031c090604401602060405180830381865afa1580156117fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061181f9190614fe5565b905060007f000000000000000000000000000000000000000000000000000000000000000060121461187c57611877827f00000000000000000000000000000000000000000000000000000000000000006012612d40565b61187e565b815b905060017f0000000000000000000000000000000000000000000000000000000000000000146119cf576119ca816118d77f0000000000000000000000000000000000000000000000000000000000000000600a6151e3565b6040517fa4d0caf20000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152600160248201527f000000000000000000000000000000000000000000000000000000000000000060448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a4d0caf290606401602060405180830381865afa1580156119a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119c59190614fe5565b612d9d565b6119d1565b805b949350505050565b6040517f6352211e000000000000000000000000000000000000000000000000000000008152600481018890526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015611a5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a7e9190614fc8565b886011611a8c8383836126e0565b611a9a8b8b8b8a8a8a612ea1565b9b9a5050505050505050505050565b6000546001600160a01b03163314611b1d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611131565b6001600160a01b038116611bb3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401611131565b611bbc816128a4565b50565b600088886002611bd08383836126e0565b610d1c8c8c8c8b8b8b8b613112565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167fc07370e4000000000000000000000000000000000000000000000000000000001480611c7257507fffffffff0000000000000000000000000000000000000000000000000000000082167f2896000200000000000000000000000000000000000000000000000000000000145b8061091c57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000083161461091c565b611ccc8282613740565b505050565b600083611cdf576000611ce9565b611ce9868661388d565b90506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663e7c8e3e387611d2584896151ef565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815260048101929092526024820152604401600060405180830381600087803b158015611d7b57600080fd5b505af1158015611d8f573d6000803e3d6000fd5b50505050857f9ecaf7fc3dfffd6867c175d6e684b1f1e3aef019398ba8db2c1ffab4a09db2538683868633604051611dcb959493929190615202565b60405180910390a2505050505050565b60006001600160a01b038616611e1d576040517fa762251300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611e756040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b606060008060405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020018e81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000000000000000000000000000000000000000000081525090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632fa1b3918d838e7f00000000000000000000000000000000000000000000000000000000000000008f8d8d6040518863ffffffff1660e01b8152600401611f7e979695949392919061524f565b6000604051808303816000875af1158015611f9d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611fc591908101906153dc565b99509195509093509150811561212c576040517f5dd8f6aa000000000000000000000000000000000000000000000000000000008152600481018c90527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635dd8f6aa90602401602060405180830381865afa158015612053573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120779190614fc8565b6040517f8ae9c07b000000000000000000000000000000000000000000000000000000008152600481018d9052602481018490526001600160a01b038c8116604483015260c06064830152600060c48301528a15156084830152600160a48301529190911690638ae9c07b9060e4016020604051808303816000875af1158015612105573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121299190614fe5565b94505b88851015612166576040517f7b94612600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8251156123cf57600060405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020018f81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f0000000000000000000000000000000000000000000000000000000000000000815250905060006040518061014001604052808f6001600160a01b031681526020018e8152602001876020015181526020018481526020018381526020018881526020018d6001600160a01b031681526020018b151581526020018a815260200189815250905060008551905060005b818110156123ca57600087828151811061228257612282615094565b6020908102919091010151905060007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11127f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316016122e8575060208101515b60208083015160808701519091015281516040517fda9ee8b70000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063da9ee8b79083906123419089906004016155d8565b6000604051808303818588803b15801561235a57600080fd5b505af115801561236e573d6000803e3d6000fd5b505050505081600001516001600160a01b03167f16112c26e14efc4be6c690149aa5a1ba75160de245f60d2273e28adb277b9e12868460200151336040516123b8939291906155eb565b60405180910390a25050600101612266565b505050505b50505087816000015182602001517f133161f1c9161488f777ab9a26aae91d47c0d9a3fafb398960f138db02c737978c8b8f888b8b33604051612418979695949392919061561d565b60405180910390a45098975050505050505050565b6040517fc6644597000000000000000000000000000000000000000000000000000000008152600481018790526024810186905260448101859052600090819081906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c664459790606401610140604051808303816000875af11580156124c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124e7919061567e565b9150915085811015612525576040517fb01493c100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f6352211e000000000000000000000000000000000000000000000000000000008152600481018a90526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa1580156125a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125ca9190614fc8565b90506000806002546000146125e7576125e28c613cc4565b6125ed565b633b9aca005b90506000806126238e88602001517f00000000000000000000000000000000000000000000000000000000000000008987613e62565b92509050633b9aca00831461263757908101905b81600003612646576000612653565b6126538e8884888761470f565b9350801561267f576126688160025485612ae0565b6126729082614fb5565b975061267f30868a611cc2565b5050508a846000015185602001517f24352f49df447b14e0e08a323625c663d865ce20c343c4638af12e1dc48aa760858e88878c8f8f336040516126ca9897969594939291906156ad565b60405180910390a4505050509695505050505050565b336001600160a01b038416148015906127ad57506040517fc161c93f0000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b03848116602483015260448201849052606482018390527f0000000000000000000000000000000000000000000000000000000000000000169063c161c93f90608401602060405180830381865afa158015612787573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127ab9190614f69565b155b801561286d57506040517fc161c93f0000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b03848116602483015260006044830152606482018390527f0000000000000000000000000000000000000000000000000000000000000000169063c161c93f90608401602060405180830381865afa158015612847573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061286b9190614f69565b155b15611ccc576040517f075fd2b100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b801580156129235750336001600160a01b03851614155b80156129e357506040517fc161c93f0000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b03858116602483015260448201859052606482018490527f0000000000000000000000000000000000000000000000000000000000000000169063c161c93f90608401602060405180830381865afa1580156129bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129e19190614f69565b155b8015612aa357506040517fc161c93f0000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b03858116602483015260006044830152606482018490527f0000000000000000000000000000000000000000000000000000000000000000169063c161c93f90608401602060405180830381865afa158015612a7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612aa19190614f69565b155b15612ada576040517f075fd2b100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b600080612af28484633b9aca00612d9d565b612afc9085614fb5565b9050612b1185633b9aca006119c581856151ef565b612b1b9086614fb5565b9150505b9392505050565b6040517f86202650000000000000000000000000000000000000000000000000000000008152600160048201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660248301526000917f000000000000000000000000000000000000000000000000000000000000000090911690638620265090604401602060405180830381865afa158015612bd1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bf59190614fc8565b9050306001600160a01b03821603612c3757612ada83306001856000806040518060200160405280600081525060405180602001604052806000815250611ddb565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661eeee14612c72576000612c74565b835b60408051602081018252600080825291517f1ebc263f0000000000000000000000000000000000000000000000000000000081529293506001600160a01b03851692631ebc263f928592612cf6926001928b927f0000000000000000000000000000000000000000000000000000000000000000928c92918291600401615711565b60206040518083038185885af1158015612d14573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612d399190614fe5565b5050505050565b6000828203612d50575082612b1f565b82821115612d7e57612d628383614fb5565b612d6d90600a6151e3565b612d779085615768565b9050612b1f565b612d888284614fb5565b612d9390600a6151e3565b612d7790856157d4565b600080807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff85870985870292508281108382030391505080600003612df557838281612deb57612deb6157a5565b0492505050612b1f565b838110612e38576040517f773cc18c0000000000000000000000000000000000000000000000000000000081526004810182905260248101859052604401611131565b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b6040517f25386715000000000000000000000000000000000000000000000000000000008152600481018790526024810186905260448101859052600090819081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632538671590606401610140604051808303816000875af1158015612f37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f5b919061567e565b9150915085811015612f99576040517fb01493c100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f6352211e000000000000000000000000000000000000000000000000000000008152600481018a905260009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa15801561301c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130409190614fc8565b905060006002546000148061306457503360009081526004602052604090205460ff165b613076576130718c613cc4565b61307c565b633b9aca005b9050633b9aca00811461309b576130968c8686858561470f565b61309e565b60005b808503965092508383146130b7576130b7308988611cc2565b50505088826000015183602001517f8657a0c05a68a912c23c1bd00124afaa8c669063b046bd9bfd22b21d573c5e6d888c86898b336040516130fe9695949392919061580f565b60405180910390a450509695505050505050565b60006001600160a01b038416613154576040517ff74a1b6600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6131ac6040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b6040517fa2df1f950000000000000000000000000000000000000000000000000000000081526060906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a2df1f959061321c908d908d908d908b908b9060040161585a565b6000604051808303816000875af115801561323b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613263919081019061589a565b97509094509092509050868310156132a7576040517ff896960b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87156133e9576040517f5dd8f6aa000000000000000000000000000000000000000000000000000000008152600481018a90527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635dd8f6aa90602401602060405180830381865afa15801561332b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061334f9190614fc8565b6040517f1665bc0f0000000000000000000000000000000000000000000000000000000081526001600160a01b038c81166004830152602482018c9052604482018b905260a06064830152600060a4830181905260848301529190911690631665bc0f9060c401600060405180830381600087803b1580156133d057600080fd5b505af11580156133e4573d6000803e3d6000fd5b505050505b8051156136d457600060405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602001600081526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f0000000000000000000000000000000000000000000000000000000000000000815250905060006040518061012001604052808d6001600160a01b031681526020018c8152602001856020015181526020018b815260200160405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020018881526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000008152508152602001838152602001896001600160a01b0316815260200188815260200187815250905060008351905060005b818110156136cf57600085828151811061358757613587615094565b6020908102919091010151905060007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11127f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316016135ed575060208101515b60208083015160a08701519091015281516040517f2b13c58f0000000000000000000000000000000000000000000000000000000081526001600160a01b0390911690632b13c58f908390613646908990600401615a5d565b6000604051808303818588803b15801561365f57600080fd5b505af1158015613673573d6000803e3d6000fd5b505050505081600001516001600160a01b03167f54b3744c489f40987dd2726ca12131243334e8292f567389f761c5a432d813e4868460200151336040516136bd93929190615a70565b60405180910390a2505060010161356b565b505050505b5081156136e6576136e6308684611cc2565b87816000015182602001517f2be10f2a0203c77d0fcaa9fd6484a8a1d6904de31cd820587f60c1c8c338c8148c898c888b8b3360405161372c979695949392919061561d565b60405180910390a450979650505050505050565b804710156137aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401611131565b6000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146137f7576040519150601f19603f3d011682016040523d82523d6000602084013e6137fc565b606091505b5050905080611ccc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401611131565b600082815260016020908152604080832080548251818502810185019093528083528493849084015b8282101561392857600084815260209081902060408051608081018252600286029092018054835260019081015463ffffffff8082168587015264010000000082041692840192909252680100000000000000009091046001600160a01b0316606083015290835290920191016138b6565b50505060008681526001602052604081209293506139479291506148ce565b8051839060005b81811015613c7c5782600003613a3e576000878152600160205260409020845185908390811061398057613980615094565b60209081029190910181015182546001818101855560009485529383902082516002909202019081559181015191909201805460408401516060909401516001600160a01b031668010000000000000000027fffffffff0000000000000000000000000000000000000000ffffffffffffffff63ffffffff958616640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000090931695909416949094171791909116919091179055613c74565b838181518110613a5057613a50615094565b6020026020010151600001518310613ae457838181518110613a7457613a74615094565b60200260200101516000015183039250613adb848281518110613a9957613a99615094565b602002602001015160000151858381518110613ab757613ab7615094565b60200260200101516020015163ffffffff1686848151811061160657611606615094565b85019450613c74565b60016000888152602001908152602001600020604051806080016040528085878581518110613b1557613b15615094565b602002602001015160000151038152602001868481518110613b3957613b39615094565b60200260200101516020015163ffffffff168152602001868481518110613b6257613b62615094565b60200260200101516040015163ffffffff168152602001868481518110613b8b57613b8b615094565b6020908102919091018101516060908101516001600160a01b039081169093528454600181810187556000968752958390208551600290920201908155918401519190940180546040850151949095015190921668010000000000000000027fffffffff0000000000000000000000000000000000000000ffffffffffffffff63ffffffff948516640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909616949092169390931793909317929092161790558351613c6b908490869084908110613ab757613ab7615094565b85019450600092505b60010161394e565b50604080518381523360208201528591879189917f59860d79d97c1fce2be7f987915c631471f4b08f671200463cc40a3380194ffb910160405180910390a450505092915050565b6040517f86202650000000000000000000000000000000000000000000000000000000008152600160048201526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116602483015260009182917f00000000000000000000000000000000000000000000000000000000000000001690638620265090604401602060405180830381865afa158015613d6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d939190614fc8565b6001600160a01b031603613dac5750633b9aca00919050565b6003546001600160a01b031615613e5a576003546040517f77695896000000000000000000000000000000000000000000000000000000008152600481018490526001600160a01b0390911690637769589690602401602060405180830381865afa925050508015613e3b575060408051601f3d908101601f19168201909252613e3891810190614fe5565b60015b613e4757506000919050565b633b9aca008111613e585792915050565b505b506000919050565b6040517f69e11cc50000000000000000000000000000000000000000000000000000000081526004810186905260248101859052604481018490528290600090633b9aca009082907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906369e11cc590606401600060405180830381865afa158015613efb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613f239190810190615a83565b905060005b8151811015614702576000828281518110613f4557613f45615094565b60200260200101519050600084826040015114613f7457613f6f898360400151633b9aca00612d9d565b613f76565b865b9050816040015185613f889190614fb5565b9450600081156146b65760c08301516001600160a01b0316156141c457633b9aca00891480613fd3575060c08301516001600160a01b031660009081526004602052604090205460ff165b15613fdf575080613ffd565b613fec826002548b612ae0565b82039050613ffa82886151ef565b96505b60006040518060c001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020018381526020017f000000000000000000000000000000000000000000000000000000000000000081526020018f81526020018d81526020018581525090508360c001516001600160a01b0316639d740bfa61eeee6001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316146140cc5760006140ce565b835b604080517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815285516001600160a01b039081166004830152602080880151602484015283880151604484015260608089015160648501526080808a0151608486015260a0808b01518051151560a488015293840151151560c48701529583015160e48601529082015161010485015281015182166101248401529283015161014483015260c090920151909116610164820152610184016000604051808303818588803b1580156141a557600080fd5b505af11580156141b9573d6000803e3d6000fd5b5050505050506146b0565b60608301511561464f5760608301516040517f862026500000000000000000000000000000000000000000000000000000000081526000916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163862026509161426d917f0000000000000000000000000000000000000000000000000000000000000000906004019182526001600160a01b0316602082015260400190565b602060405180830381865afa15801561428a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142ae9190614fc8565b90506001600160a01b0381166142f0576040517f6921234300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b306001600160a01b038216036143d1576040805160208082528183019092528493506000916020820181803683370190505090508e60405160200161433791815260200190565b60405160208183030381529060405290508460200151156143785761437385606001518460006040518060200160405280600081525085611cd1565b6143cb565b6143c98330876060015160006001600160a01b031689608001516001600160a01b0316036143a657336143ac565b88608001515b60008a600001516040518060200160405280600081525088611ddb565b505b50614649565b633b9aca008a14806143fb57506001600160a01b03811660009081526004602052604090205460ff165b1561440857829150614426565b614415836002548c612ae0565b8303915061442383896151ef565b97505b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661eeee14614461576000614463565b825b604080516020808252818301909252919250600091906020820181803683370190505090508f60405160200161449b91815260200190565b604051602081830303815290604052905085602001511561455d5760608601516040517f0cf8e8580000000000000000000000000000000000000000000000000000000081526001600160a01b03851691630cf8e8589185916145269189907f000000000000000000000000000000000000000000000000000000000000000090889060040161504e565b6000604051808303818588803b15801561453f57600080fd5b505af1158015614553573d6000803e3d6000fd5b5050505050614646565b826001600160a01b0316631ebc263f838860600151877f000000000000000000000000000000000000000000000000000000000000000060006001600160a01b03168c608001516001600160a01b0316036145b857336145be565b8b608001515b8c516040517fffffffff0000000000000000000000000000000000000000000000000000000060e089901b16815261460195949392916000918b90600401615711565b60206040518083038185885af115801561461f573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906146449190614fe5565b505b50505b506146b0565b60808301516000906001600160a01b031661466a5733614670565b83608001515b9050633b9aca008a03614685578291506146a3565b614692836002548c612ae0565b830391506146a083896151ef565b97505b6146ae308284611cc2565b505b81880397505b8a8c8e7f2a1f2df21da49f011c6165709ae4b279f8d6d7cffe9043c582352882d8c9698b8685336040516146ec93929190615b8d565b60405180910390a4836001019350505050613f28565b5050509550959350505050565b600061471e8460025484612ae0565b610100860151909150604f1c60019081160361487257600086815260016020818152604080842081516080810183528981526002805463ffffffff9081168387019081528a82168487019081526001600160a01b03808e16606087019081528754808c018955978c5298909a209451958402909401948555519390960180549251955190971668010000000000000000027fffffffff0000000000000000000000000000000000000000ffffffffffffffff958716640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909316939096169290921717929092169290921790925590549051859088907f77813be0661650ddc1a5193ff2837df4162b251cb432651e2c060c3fc39756be90614865908790899033909283526001600160a01b03918216602084015216604082015260600190565b60405180910390a46148c5565b61487c8184612b26565b604080516001600160a01b0385168152336020820152600091839189917fcf0c92a2c6d7c42f488326b0cb900104b99984b6b218db81cd29371364a35251910160405180910390a45b95945050505050565b5080546000825560020290600052602060002090810190611bbc91905b8082111561492957600081556001810180547fffffffff000000000000000000000000000000000000000000000000000000001690556002016148eb565b5090565b60006020828403121561493f57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114612b1f57600080fd5b6001600160a01b0381168114611bbc57600080fd5b60008083601f84011261499657600080fd5b50813567ffffffffffffffff8111156149ae57600080fd5b6020830191508360208285010111156149c657600080fd5b9250929050565b600080600080600080600060a0888a0312156149e857600080fd5b87359650602088013595506040880135614a018161496f565b9450606088013567ffffffffffffffff80821115614a1e57600080fd5b614a2a8b838c01614984565b909650945060808a0135915080821115614a4357600080fd5b50614a508a828b01614984565b989b979a50959850939692959293505050565b600060208284031215614a7557600080fd5b8135612b1f8161496f565b8015158114611bbc57600080fd5b6000806000806000806000806000806101008b8d031215614aae57600080fd5b8a35995060208b0135985060408b0135614ac78161496f565b975060608b0135614ad78161496f565b965060808b0135955060a08b0135614aee81614a80565b945060c08b013567ffffffffffffffff80821115614b0b57600080fd5b614b178e838f01614984565b909650945060e08d0135915080821115614b3057600080fd5b50614b3d8d828e01614984565b915080935050809150509295989b9194979a5092959850565b600080600080600080600060c0888a031215614b7157600080fd5b8735965060208801359550604088013594506060880135614b918161496f565b93506080880135925060a088013567ffffffffffffffff811115614bb457600080fd5b614a508a828b01614984565b60008060408385031215614bd357600080fd5b823591506020830135614be58161496f565b809150509250929050565b600060208284031215614c0257600080fd5b5035919050565b60008060408385031215614c1c57600080fd5b8235614c278161496f565b91506020830135614be581614a80565b602080825282518282018190526000919060409081850190868401855b82811015614ca0578151805185528681015163ffffffff908116888701528682015116868601526060908101516001600160a01b03169085015260809093019290850190600101614c54565b5091979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff81118282101715614d0057614d00614cad565b60405290565b6040805190810167ffffffffffffffff81118282101715614d0057614d00614cad565b60405160e0810167ffffffffffffffff81118282101715614d0057614d00614cad565b604051601f8201601f1916810167ffffffffffffffff81118282101715614d7557614d75614cad565b604052919050565b600067ffffffffffffffff821115614d9757614d97614cad565b50601f01601f191660200190565b600082601f830112614db657600080fd5b8135614dc9614dc482614d7d565b614d4c565b818152846020838601011115614dde57600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600080600060e0888a031215614e1657600080fd5b8735965060208801359550604088013594506060880135614e368161496f565b93506080880135925060a0880135614e4d8161496f565b915060c088013567ffffffffffffffff811115614e6957600080fd5b614e758a828b01614da5565b91505092959891949750929550565b60008060408385031215614e9757600080fd5b8235614ea28161496f565b946020939093013593505050565b600080600080600080600080610100898b031215614ecd57600080fd5b8835614ed88161496f565b975060208901359650604089013595506060890135614ef68161496f565b94506080890135935060a0890135614f0d8161496f565b925060c089013567ffffffffffffffff80821115614f2a57600080fd5b614f368c838d01614da5565b935060e08b0135915080821115614f4c57600080fd5b50614f598b828c01614da5565b9150509295985092959890939650565b600060208284031215614f7b57600080fd5b8151612b1f81614a80565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561091c5761091c614f86565b600060208284031215614fda57600080fd5b8151612b1f8161496f565b600060208284031215614ff757600080fd5b5051919050565b60005b83811015615019578181015183820152602001615001565b50506000910152565b6000815180845261503a816020860160208601614ffe565b601f01601f19169290920160200192915050565b8481528360208201526001600160a01b038316604082015260a06060820152600060a082015260c06080820152600061508a60c0830184615022565b9695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600181815b8085111561511c57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561510257615102614f86565b8085161561510f57918102915b93841c93908002906150c8565b509250929050565b6000826151335750600161091c565b816151405750600061091c565b816001811461515657600281146151605761517c565b600191505061091c565b60ff84111561517157615171614f86565b50506001821b61091c565b5060208310610133831016604e8410600b841016171561519f575081810a61091c565b6151a983836150c3565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156151db576151db614f86565b029392505050565b6000612b1f8383615124565b8082018082111561091c5761091c614f86565b85815284602082015260a06040820152600061522160a0830186615022565b82810360608401526152338186615022565b9150506001600160a01b03831660808301529695505050505050565b60006101406001600160a01b03808b168452615298602085018b6001600160a01b0381511682526020810151602083015260408101516040830152606081015160608301525050565b8860a08501528760c085015280871660e085015250806101008401526152c081840186615022565b90508281036101208401526152d58185615022565b9a9950505050505050505050565b80516152ee8161496f565b919050565b6000610120828403121561530657600080fd5b61530e614cdc565b9050815181526020820151602082015260408201516040820152606082015160608201526080820151608082015260a082015160a082015260c082015160c082015261535c60e083016152e3565b60e082015261010080830151818301525092915050565b600067ffffffffffffffff82111561538d5761538d614cad565b5060051b60200190565b600082601f8301126153a857600080fd5b81516153b6614dc482614d7d565b8181528460208386010111156153cb57600080fd5b6119d1826020830160208701614ffe565b60008060008061018085870312156153f357600080fd5b6153fd86866152f3565b9350610120850151925061014085015167ffffffffffffffff8082111561542357600080fd5b818701915087601f83011261543757600080fd5b81516020615447614dc483615373565b82815260069290921b8401810191818101908b84111561546657600080fd5b948201945b838610156154b2576040868d0312156154845760008081fd5b61548c614d06565b86516154978161496f565b8152868401518482015282526040909501949082019061546b565b6101608b01519097509450505050808211156154cd57600080fd5b506154da87828801615397565b91505092959194509250565b80516001600160a01b031682526000610200602083810151858201526040808501518187015260608086015180516001600160a01b0316828901529283015160808801529082015160a087015281015160c086015250608083015180516001600160a01b031660e08601526020810151610100860152604081015161012086015260608101516101408601525060a083015161016085015260c08301516001600160a01b0381166101808601525060e08301518015156101a086015250610100830151816101c08601526155bc82860182615022565b9150506101208301518482036101e08601526148c58282615022565b602081526000612b1f60208301846154e6565b6060815260006155fe60608301866154e6565b90508360208301526001600160a01b0383166040830152949350505050565b60006001600160a01b03808a168352808916602084015287604084015286606084015260e0608084015261565460e0840187615022565b83810360a08501526156668187615022565b92505080841660c08401525098975050505050505050565b600080610140838503121561569257600080fd5b61569c84846152f3565b915061012083015190509250929050565b60006001600160a01b03808b16835289602084015288604084015287606084015286608084015260e060a08401528460e08401526101008587828601376000848701820152931660c083015250601f909201601f1916909101019695505050505050565b60006101008983528860208401526001600160a01b03808916604085015280881660608501525085608084015284151560a08401528060c0840152600081840152506101208060e08401526152d581840185615022565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156157a0576157a0614f86565b500290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261580a577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60006001600160a01b03808916835287602084015286604084015285606084015260c0608084015261584460c0840186615022565b915080841660a084015250979650505050505050565b6001600160a01b038616815284602082015283604082015260a06060820152600061588860a0830185615022565b8281036080840152610d3c8185615022565b60008060008061018085870312156158b157600080fd5b6158bb86866152f3565b9350610120850151925061014085015167ffffffffffffffff808211156158e157600080fd5b818701915087601f8301126158f557600080fd5b81516020615905614dc483615373565b82815260069290921b8401810191818101908b84111561592457600080fd5b948201945b838610156154b2576040868d0312156159425760008081fd5b61594a614d06565b86516159558161496f565b81528684015184820152825260409095019490820190615929565b80516001600160a01b0316825260006101e060208301516020850152604083015160408501526060830151606085015260808301516159dc60808601826001600160a01b0381511682526020810151602083015260408101516040830152606081015160608301525050565b5060a083015180516001600160a01b03908116610100878101919091526020830151610120880152604083015161014088015260609092015161016087015260c08501511661018086015260e08401516101a0860183905290615a4183870183615022565b9250808501519150508482036101c08601526148c58282615022565b602081526000612b1f6020830184615970565b6060815260006155fe6060830186615970565b60006020808385031215615a9657600080fd5b825167ffffffffffffffff811115615aad57600080fd5b8301601f81018513615abe57600080fd5b8051615acc614dc482615373565b81815260e09182028301840191848201919088841115615aeb57600080fd5b938501935b83851015615b815780858a031215615b085760008081fd5b615b10614d29565b8551615b1b81614a80565b815285870151615b2a81614a80565b818801526040868101519082015260608087015190820152608080870151615b518161496f565b9082015260a0868101519082015260c080870151615b6e8161496f565b9082015283529384019391850191615af0565b50979650505050505050565b6101208101615bee8286805115158252602081015115156020830152604081015160408301526060810151606083015260808101516001600160a01b03808216608085015260a083015160a08501528060c08401511660c085015250505050565b8360e08301526001600160a01b03831661010083015294935050505056fea26469706673582212209a0821b8d0e0d584f8a3d44469c86fb05dc17e11fce0e25a17cf53905ee054f064736f6c63430008100033", "deployedBytecode": "0x6080604052600436106101fe5760003560e01c80638b79543c1161011d578063c41c2f24116100b0578063df21a7dd1161007f578063f2fde38b11610064578063f2fde38b14610722578063fc0c546a14610742578063fe663f0f1461077657600080fd5b8063df21a7dd146106a0578063e5a6b10f146106ee57600080fd5b8063c41c2f2414610602578063d3419bf314610636578063d6dacc531461066a578063ddca3f431461068a57600080fd5b8063ad007d63116100ec578063ad007d631461053e578063b631b50014610572578063b7bad1b1146105a2578063bc8926e9146105e257600080fd5b80638b79543c146104985780638da5cb5b146104cc578063975057e7146104ea578063a32e1e961461051e57600080fd5b8063405b84fa11610195578063715018a611610164578063715018a6146104165780637258002c1461042b57806389701db51461044b5780638af560941461046b57600080fd5b8063405b84fa14610382578063637913ac146103a257806366248b86146103c257806369fe0e2d146103f657600080fd5b80632b267b4e116101d15780632b267b4e146102ae5780632bdfe004146102ce5780632d1a59031461031a578063313ce5671461034e57600080fd5b806301ffc9a7146102035780630cf8e858146102385780631982d6791461024d5780631ebc263f1461029b575b600080fd5b34801561020f57600080fd5b5061022361021e36600461492d565b610796565b60405190151581526020015b60405180910390f35b61024b6102463660046149cd565b610922565b005b34801561025957600080fd5b5061028d610268366004614a63565b507f000000000000000000000000000000000000000000000000000000000000000090565b60405190815260200161022f565b61028d6102a9366004614a8e565b610b23565b3480156102ba57600080fd5b5061028d6102c9366004614b56565b610d2c565b3480156102da57600080fd5b506103027f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161022f565b34801561032657600080fd5b5061028d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561035a57600080fd5b5061028d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561038e57600080fd5b5061028d61039d366004614bc0565b610d48565b3480156103ae57600080fd5b5061024b6103bd366004614a63565b6110c1565b3480156103ce57600080fd5b5061028d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561040257600080fd5b5061024b610411366004614bf0565b6111a6565b34801561042257600080fd5b5061024b611298565b34801561043757600080fd5b5061024b610446366004614c09565b611318565b34801561045757600080fd5b5061024b610466366004614bf0565b61140c565b34801561047757600080fd5b5061048b610486366004614bf0565b6116c0565b60405161022f9190614c37565b3480156104a457600080fd5b506103027f000000000000000000000000000000000000000000000000000000000000000081565b3480156104d857600080fd5b506000546001600160a01b0316610302565b3480156104f657600080fd5b506103027f000000000000000000000000000000000000000000000000000000000000000081565b34801561052a57600080fd5b5061028d610539366004614bf0565b611772565b34801561054a57600080fd5b506103027f000000000000000000000000000000000000000000000000000000000000000081565b34801561057e57600080fd5b5061022361058d366004614a63565b60046020526000908152604090205460ff1681565b3480156105ae57600080fd5b5061028d6105bd366004614a63565b507f000000000000000000000000000000000000000000000000000000000000000090565b3480156105ee57600080fd5b5061028d6105fd366004614dfb565b6119d9565b34801561060e57600080fd5b506103027f000000000000000000000000000000000000000000000000000000000000000081565b34801561064257600080fd5b506103027f000000000000000000000000000000000000000000000000000000000000000081565b34801561067657600080fd5b50600354610302906001600160a01b031681565b34801561069657600080fd5b5061028d60025481565b3480156106ac57600080fd5b506102236106bb366004614e84565b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161490565b3480156106fa57600080fd5b5061028d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561072e57600080fd5b5061024b61073d366004614a63565b611aa9565b34801561074e57600080fd5b506103027f000000000000000000000000000000000000000000000000000000000000000081565b34801561078257600080fd5b5061028d610791366004614eb0565b611bbf565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167fedb527eb00000000000000000000000000000000000000000000000000000000148061082957507fffffffff0000000000000000000000000000000000000000000000000000000082167f2b267b4e00000000000000000000000000000000000000000000000000000000145b8061087557507fffffffff0000000000000000000000000000000000000000000000000000000082167fbc8926e900000000000000000000000000000000000000000000000000000000145b806108c157507fffffffff0000000000000000000000000000000000000000000000000000000082167ffe663f0f00000000000000000000000000000000000000000000000000000000145b8061090d57507fffffffff0000000000000000000000000000000000000000000000000000000082167fad007d6300000000000000000000000000000000000000000000000000000000145b8061091c575061091c82611bdf565b92915050565b6040517f6e49181f0000000000000000000000000000000000000000000000000000000081526004810188905230602482015287907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636e49181f90604401602060405180830381865afa1580156109a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109cc9190614f69565b610a02576040517fd8ead2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661eeee14610a8a573415610a6c576040517fbcfd35be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b47610a7833308a611cc2565b610a828147614fb5565b975050610a8e565b3496505b33600090815260046020908152604091829020548251601f8801839004830281018301909352868352610b19928b928b9260ff161591908a908a908190840183828082843760009201919091525050604080516020601f8c018190048102820181019092528a815292508a9150899081908401838280828437600092019190915250611cd192505050565b5050505050505050565b6040517f6e49181f000000000000000000000000000000000000000000000000000000008152600481018b90523060248201526000908b906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636e49181f90604401602060405180830381865afa158015610bac573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bd09190614f69565b610c06576040517fd8ead2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661eeee14610c8e573415610c70576040517fbcfd35be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b47610c7c33308e611cc2565b610c868147614fb5565b9b5050610c92565b349a505b610d1c8b338e8c8c8c8c8c8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611ddb92505050565b9c9b505050505050505050505050565b6000610d3c88888887878761242d565b98975050505050505050565b6040517f6352211e000000000000000000000000000000000000000000000000000000008152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610dc9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ded9190614fc8565b836004610dfb8383836126e0565b6040517fdf21a7dd0000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301526024820188905286169063df21a7dd90604401602060405180830381865afa158015610e81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea59190614f69565b610edb576040517f581010ed00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f6bb6a5ad000000000000000000000000000000000000000000000000000000008152600481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636bb6a5ad906024016020604051808303816000875af1158015610f5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f7f9190614fe5565b935083156110735760007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661eeee14610fc2576000610fc4565b845b604080516020810182526000815290517f0cf8e8580000000000000000000000000000000000000000000000000000000081529192506001600160a01b03881691630cf8e85891849161103f918c918b917f00000000000000000000000000000000000000000000000000000000000000009160040161504e565b6000604051808303818588803b15801561105857600080fd5b505af115801561106c573d6000803e3d6000fd5b5050505050505b604080518581523360208201526001600160a01b0387169188917fa7519e5f94697b7f53e97c5eb46a0c730a296ab686ab8fd333835c5f735784eb910160405180910390a350505092915050565b6000546001600160a01b0316331461113a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b600380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040513381527f0a9a80fe9716605b3e52abb3d792d6a4e7816d6afc02a5a4ef023081feaf9f609060200160405180910390a250565b6000546001600160a01b0316331461121a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611131565b6302faf080811115611258576040517f45fbd9c100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002819055604080518281523360208201527fd7414e590e1cb532989ab2a34c8f4c2c17f7ab6f006efeeaef2e87cd5008c202910160405180910390a150565b6000546001600160a01b0316331461130c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611131565b61131660006128a4565b565b6000546001600160a01b0316331461138c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611131565b6001600160a01b03821660008181526004602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001685151590811790915591513381529192917fa2653e25a502c023a5830d0de847ef6f458387865b1f4f575d7594f9f2c0d71e910160405180910390a35050565b6040517f6352211e000000000000000000000000000000000000000000000000000000008152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa15801561148a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ae9190614fc8565b8160056114c36000546001600160a01b031690565b6001600160a01b0316336001600160a01b0316146114e38484848461290c565b600085815260016020908152604080832080548251818502810185019093528083529192909190849084015b8282101561158157600084815260209081902060408051608081018252600286029092018054835260019081015463ffffffff8082168587015264010000000082041692840192909252680100000000000000009091046001600160a01b03166060830152908352909201910161150f565b50505060008881526001602052604081209293506115a09291506148ce565b805160005b81811015610b1957600061161d8483815181106115c4576115c4615094565b6020026020010151600001518584815181106115e2576115e2615094565b60200260200101516020015163ffffffff1686858151811061160657611606615094565b60200260200101516040015163ffffffff16612ae0565b90506116468185848151811061163557611635615094565b602002602001015160600151612b26565b60011515818a7fcf0c92a2c6d7c42f488326b0cb900104b99984b6b218db81cd29371364a3525187868151811061167f5761167f615094565b602002602001015160600151336040516116af9291906001600160a01b0392831681529116602082015260400190565b60405180910390a4506001016115a5565b606060016000838152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b8282101561176757600084815260209081902060408051608081018252600286029092018054835260019081015463ffffffff8082168587015264010000000082041692840192909252680100000000000000009091046001600160a01b0316606083015290835290920191016116f5565b505050509050919050565b6040517fd49031c00000000000000000000000000000000000000000000000000000000081523060048201526024810182905260009081906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063d49031c090604401602060405180830381865afa1580156117fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061181f9190614fe5565b905060007f000000000000000000000000000000000000000000000000000000000000000060121461187c57611877827f00000000000000000000000000000000000000000000000000000000000000006012612d40565b61187e565b815b905060017f0000000000000000000000000000000000000000000000000000000000000000146119cf576119ca816118d77f0000000000000000000000000000000000000000000000000000000000000000600a6151e3565b6040517fa4d0caf20000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152600160248201527f000000000000000000000000000000000000000000000000000000000000000060448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a4d0caf290606401602060405180830381865afa1580156119a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119c59190614fe5565b612d9d565b6119d1565b805b949350505050565b6040517f6352211e000000000000000000000000000000000000000000000000000000008152600481018890526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015611a5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a7e9190614fc8565b886011611a8c8383836126e0565b611a9a8b8b8b8a8a8a612ea1565b9b9a5050505050505050505050565b6000546001600160a01b03163314611b1d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611131565b6001600160a01b038116611bb3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401611131565b611bbc816128a4565b50565b600088886002611bd08383836126e0565b610d1c8c8c8c8b8b8b8b613112565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167fc07370e4000000000000000000000000000000000000000000000000000000001480611c7257507fffffffff0000000000000000000000000000000000000000000000000000000082167f2896000200000000000000000000000000000000000000000000000000000000145b8061091c57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000083161461091c565b611ccc8282613740565b505050565b600083611cdf576000611ce9565b611ce9868661388d565b90506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663e7c8e3e387611d2584896151ef565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815260048101929092526024820152604401600060405180830381600087803b158015611d7b57600080fd5b505af1158015611d8f573d6000803e3d6000fd5b50505050857f9ecaf7fc3dfffd6867c175d6e684b1f1e3aef019398ba8db2c1ffab4a09db2538683868633604051611dcb959493929190615202565b60405180910390a2505050505050565b60006001600160a01b038616611e1d576040517fa762251300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611e756040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b606060008060405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020018e81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000000000000000000000000000000000000000000081525090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632fa1b3918d838e7f00000000000000000000000000000000000000000000000000000000000000008f8d8d6040518863ffffffff1660e01b8152600401611f7e979695949392919061524f565b6000604051808303816000875af1158015611f9d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611fc591908101906153dc565b99509195509093509150811561212c576040517f5dd8f6aa000000000000000000000000000000000000000000000000000000008152600481018c90527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635dd8f6aa90602401602060405180830381865afa158015612053573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120779190614fc8565b6040517f8ae9c07b000000000000000000000000000000000000000000000000000000008152600481018d9052602481018490526001600160a01b038c8116604483015260c06064830152600060c48301528a15156084830152600160a48301529190911690638ae9c07b9060e4016020604051808303816000875af1158015612105573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121299190614fe5565b94505b88851015612166576040517f7b94612600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8251156123cf57600060405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020018f81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f0000000000000000000000000000000000000000000000000000000000000000815250905060006040518061014001604052808f6001600160a01b031681526020018e8152602001876020015181526020018481526020018381526020018881526020018d6001600160a01b031681526020018b151581526020018a815260200189815250905060008551905060005b818110156123ca57600087828151811061228257612282615094565b6020908102919091010151905060007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11127f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316016122e8575060208101515b60208083015160808701519091015281516040517fda9ee8b70000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063da9ee8b79083906123419089906004016155d8565b6000604051808303818588803b15801561235a57600080fd5b505af115801561236e573d6000803e3d6000fd5b505050505081600001516001600160a01b03167f16112c26e14efc4be6c690149aa5a1ba75160de245f60d2273e28adb277b9e12868460200151336040516123b8939291906155eb565b60405180910390a25050600101612266565b505050505b50505087816000015182602001517f133161f1c9161488f777ab9a26aae91d47c0d9a3fafb398960f138db02c737978c8b8f888b8b33604051612418979695949392919061561d565b60405180910390a45098975050505050505050565b6040517fc6644597000000000000000000000000000000000000000000000000000000008152600481018790526024810186905260448101859052600090819081906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c664459790606401610140604051808303816000875af11580156124c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124e7919061567e565b9150915085811015612525576040517fb01493c100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f6352211e000000000000000000000000000000000000000000000000000000008152600481018a90526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa1580156125a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125ca9190614fc8565b90506000806002546000146125e7576125e28c613cc4565b6125ed565b633b9aca005b90506000806126238e88602001517f00000000000000000000000000000000000000000000000000000000000000008987613e62565b92509050633b9aca00831461263757908101905b81600003612646576000612653565b6126538e8884888761470f565b9350801561267f576126688160025485612ae0565b6126729082614fb5565b975061267f30868a611cc2565b5050508a846000015185602001517f24352f49df447b14e0e08a323625c663d865ce20c343c4638af12e1dc48aa760858e88878c8f8f336040516126ca9897969594939291906156ad565b60405180910390a4505050509695505050505050565b336001600160a01b038416148015906127ad57506040517fc161c93f0000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b03848116602483015260448201849052606482018390527f0000000000000000000000000000000000000000000000000000000000000000169063c161c93f90608401602060405180830381865afa158015612787573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127ab9190614f69565b155b801561286d57506040517fc161c93f0000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b03848116602483015260006044830152606482018390527f0000000000000000000000000000000000000000000000000000000000000000169063c161c93f90608401602060405180830381865afa158015612847573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061286b9190614f69565b155b15611ccc576040517f075fd2b100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b801580156129235750336001600160a01b03851614155b80156129e357506040517fc161c93f0000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b03858116602483015260448201859052606482018490527f0000000000000000000000000000000000000000000000000000000000000000169063c161c93f90608401602060405180830381865afa1580156129bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129e19190614f69565b155b8015612aa357506040517fc161c93f0000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b03858116602483015260006044830152606482018490527f0000000000000000000000000000000000000000000000000000000000000000169063c161c93f90608401602060405180830381865afa158015612a7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612aa19190614f69565b155b15612ada576040517f075fd2b100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b600080612af28484633b9aca00612d9d565b612afc9085614fb5565b9050612b1185633b9aca006119c581856151ef565b612b1b9086614fb5565b9150505b9392505050565b6040517f86202650000000000000000000000000000000000000000000000000000000008152600160048201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660248301526000917f000000000000000000000000000000000000000000000000000000000000000090911690638620265090604401602060405180830381865afa158015612bd1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bf59190614fc8565b9050306001600160a01b03821603612c3757612ada83306001856000806040518060200160405280600081525060405180602001604052806000815250611ddb565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661eeee14612c72576000612c74565b835b60408051602081018252600080825291517f1ebc263f0000000000000000000000000000000000000000000000000000000081529293506001600160a01b03851692631ebc263f928592612cf6926001928b927f0000000000000000000000000000000000000000000000000000000000000000928c92918291600401615711565b60206040518083038185885af1158015612d14573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612d399190614fe5565b5050505050565b6000828203612d50575082612b1f565b82821115612d7e57612d628383614fb5565b612d6d90600a6151e3565b612d779085615768565b9050612b1f565b612d888284614fb5565b612d9390600a6151e3565b612d7790856157d4565b600080807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff85870985870292508281108382030391505080600003612df557838281612deb57612deb6157a5565b0492505050612b1f565b838110612e38576040517f773cc18c0000000000000000000000000000000000000000000000000000000081526004810182905260248101859052604401611131565b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b6040517f25386715000000000000000000000000000000000000000000000000000000008152600481018790526024810186905260448101859052600090819081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632538671590606401610140604051808303816000875af1158015612f37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f5b919061567e565b9150915085811015612f99576040517fb01493c100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f6352211e000000000000000000000000000000000000000000000000000000008152600481018a905260009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa15801561301c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130409190614fc8565b905060006002546000148061306457503360009081526004602052604090205460ff165b613076576130718c613cc4565b61307c565b633b9aca005b9050633b9aca00811461309b576130968c8686858561470f565b61309e565b60005b808503965092508383146130b7576130b7308988611cc2565b50505088826000015183602001517f8657a0c05a68a912c23c1bd00124afaa8c669063b046bd9bfd22b21d573c5e6d888c86898b336040516130fe9695949392919061580f565b60405180910390a450509695505050505050565b60006001600160a01b038416613154576040517ff74a1b6600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6131ac6040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b6040517fa2df1f950000000000000000000000000000000000000000000000000000000081526060906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a2df1f959061321c908d908d908d908b908b9060040161585a565b6000604051808303816000875af115801561323b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613263919081019061589a565b97509094509092509050868310156132a7576040517ff896960b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87156133e9576040517f5dd8f6aa000000000000000000000000000000000000000000000000000000008152600481018a90527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635dd8f6aa90602401602060405180830381865afa15801561332b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061334f9190614fc8565b6040517f1665bc0f0000000000000000000000000000000000000000000000000000000081526001600160a01b038c81166004830152602482018c9052604482018b905260a06064830152600060a4830181905260848301529190911690631665bc0f9060c401600060405180830381600087803b1580156133d057600080fd5b505af11580156133e4573d6000803e3d6000fd5b505050505b8051156136d457600060405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602001600081526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f0000000000000000000000000000000000000000000000000000000000000000815250905060006040518061012001604052808d6001600160a01b031681526020018c8152602001856020015181526020018b815260200160405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020018881526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000008152508152602001838152602001896001600160a01b0316815260200188815260200187815250905060008351905060005b818110156136cf57600085828151811061358757613587615094565b6020908102919091010151905060007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11127f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316016135ed575060208101515b60208083015160a08701519091015281516040517f2b13c58f0000000000000000000000000000000000000000000000000000000081526001600160a01b0390911690632b13c58f908390613646908990600401615a5d565b6000604051808303818588803b15801561365f57600080fd5b505af1158015613673573d6000803e3d6000fd5b505050505081600001516001600160a01b03167f54b3744c489f40987dd2726ca12131243334e8292f567389f761c5a432d813e4868460200151336040516136bd93929190615a70565b60405180910390a2505060010161356b565b505050505b5081156136e6576136e6308684611cc2565b87816000015182602001517f2be10f2a0203c77d0fcaa9fd6484a8a1d6904de31cd820587f60c1c8c338c8148c898c888b8b3360405161372c979695949392919061561d565b60405180910390a450979650505050505050565b804710156137aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401611131565b6000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146137f7576040519150601f19603f3d011682016040523d82523d6000602084013e6137fc565b606091505b5050905080611ccc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401611131565b600082815260016020908152604080832080548251818502810185019093528083528493849084015b8282101561392857600084815260209081902060408051608081018252600286029092018054835260019081015463ffffffff8082168587015264010000000082041692840192909252680100000000000000009091046001600160a01b0316606083015290835290920191016138b6565b50505060008681526001602052604081209293506139479291506148ce565b8051839060005b81811015613c7c5782600003613a3e576000878152600160205260409020845185908390811061398057613980615094565b60209081029190910181015182546001818101855560009485529383902082516002909202019081559181015191909201805460408401516060909401516001600160a01b031668010000000000000000027fffffffff0000000000000000000000000000000000000000ffffffffffffffff63ffffffff958616640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000090931695909416949094171791909116919091179055613c74565b838181518110613a5057613a50615094565b6020026020010151600001518310613ae457838181518110613a7457613a74615094565b60200260200101516000015183039250613adb848281518110613a9957613a99615094565b602002602001015160000151858381518110613ab757613ab7615094565b60200260200101516020015163ffffffff1686848151811061160657611606615094565b85019450613c74565b60016000888152602001908152602001600020604051806080016040528085878581518110613b1557613b15615094565b602002602001015160000151038152602001868481518110613b3957613b39615094565b60200260200101516020015163ffffffff168152602001868481518110613b6257613b62615094565b60200260200101516040015163ffffffff168152602001868481518110613b8b57613b8b615094565b6020908102919091018101516060908101516001600160a01b039081169093528454600181810187556000968752958390208551600290920201908155918401519190940180546040850151949095015190921668010000000000000000027fffffffff0000000000000000000000000000000000000000ffffffffffffffff63ffffffff948516640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909616949092169390931793909317929092161790558351613c6b908490869084908110613ab757613ab7615094565b85019450600092505b60010161394e565b50604080518381523360208201528591879189917f59860d79d97c1fce2be7f987915c631471f4b08f671200463cc40a3380194ffb910160405180910390a450505092915050565b6040517f86202650000000000000000000000000000000000000000000000000000000008152600160048201526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116602483015260009182917f00000000000000000000000000000000000000000000000000000000000000001690638620265090604401602060405180830381865afa158015613d6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d939190614fc8565b6001600160a01b031603613dac5750633b9aca00919050565b6003546001600160a01b031615613e5a576003546040517f77695896000000000000000000000000000000000000000000000000000000008152600481018490526001600160a01b0390911690637769589690602401602060405180830381865afa925050508015613e3b575060408051601f3d908101601f19168201909252613e3891810190614fe5565b60015b613e4757506000919050565b633b9aca008111613e585792915050565b505b506000919050565b6040517f69e11cc50000000000000000000000000000000000000000000000000000000081526004810186905260248101859052604481018490528290600090633b9aca009082907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906369e11cc590606401600060405180830381865afa158015613efb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613f239190810190615a83565b905060005b8151811015614702576000828281518110613f4557613f45615094565b60200260200101519050600084826040015114613f7457613f6f898360400151633b9aca00612d9d565b613f76565b865b9050816040015185613f889190614fb5565b9450600081156146b65760c08301516001600160a01b0316156141c457633b9aca00891480613fd3575060c08301516001600160a01b031660009081526004602052604090205460ff165b15613fdf575080613ffd565b613fec826002548b612ae0565b82039050613ffa82886151ef565b96505b60006040518060c001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020018381526020017f000000000000000000000000000000000000000000000000000000000000000081526020018f81526020018d81526020018581525090508360c001516001600160a01b0316639d740bfa61eeee6001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316146140cc5760006140ce565b835b604080517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815285516001600160a01b039081166004830152602080880151602484015283880151604484015260608089015160648501526080808a0151608486015260a0808b01518051151560a488015293840151151560c48701529583015160e48601529082015161010485015281015182166101248401529283015161014483015260c090920151909116610164820152610184016000604051808303818588803b1580156141a557600080fd5b505af11580156141b9573d6000803e3d6000fd5b5050505050506146b0565b60608301511561464f5760608301516040517f862026500000000000000000000000000000000000000000000000000000000081526000916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163862026509161426d917f0000000000000000000000000000000000000000000000000000000000000000906004019182526001600160a01b0316602082015260400190565b602060405180830381865afa15801561428a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142ae9190614fc8565b90506001600160a01b0381166142f0576040517f6921234300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b306001600160a01b038216036143d1576040805160208082528183019092528493506000916020820181803683370190505090508e60405160200161433791815260200190565b60405160208183030381529060405290508460200151156143785761437385606001518460006040518060200160405280600081525085611cd1565b6143cb565b6143c98330876060015160006001600160a01b031689608001516001600160a01b0316036143a657336143ac565b88608001515b60008a600001516040518060200160405280600081525088611ddb565b505b50614649565b633b9aca008a14806143fb57506001600160a01b03811660009081526004602052604090205460ff165b1561440857829150614426565b614415836002548c612ae0565b8303915061442383896151ef565b97505b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661eeee14614461576000614463565b825b604080516020808252818301909252919250600091906020820181803683370190505090508f60405160200161449b91815260200190565b604051602081830303815290604052905085602001511561455d5760608601516040517f0cf8e8580000000000000000000000000000000000000000000000000000000081526001600160a01b03851691630cf8e8589185916145269189907f000000000000000000000000000000000000000000000000000000000000000090889060040161504e565b6000604051808303818588803b15801561453f57600080fd5b505af1158015614553573d6000803e3d6000fd5b5050505050614646565b826001600160a01b0316631ebc263f838860600151877f000000000000000000000000000000000000000000000000000000000000000060006001600160a01b03168c608001516001600160a01b0316036145b857336145be565b8b608001515b8c516040517fffffffff0000000000000000000000000000000000000000000000000000000060e089901b16815261460195949392916000918b90600401615711565b60206040518083038185885af115801561461f573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906146449190614fe5565b505b50505b506146b0565b60808301516000906001600160a01b031661466a5733614670565b83608001515b9050633b9aca008a03614685578291506146a3565b614692836002548c612ae0565b830391506146a083896151ef565b97505b6146ae308284611cc2565b505b81880397505b8a8c8e7f2a1f2df21da49f011c6165709ae4b279f8d6d7cffe9043c582352882d8c9698b8685336040516146ec93929190615b8d565b60405180910390a4836001019350505050613f28565b5050509550959350505050565b600061471e8460025484612ae0565b610100860151909150604f1c60019081160361487257600086815260016020818152604080842081516080810183528981526002805463ffffffff9081168387019081528a82168487019081526001600160a01b03808e16606087019081528754808c018955978c5298909a209451958402909401948555519390960180549251955190971668010000000000000000027fffffffff0000000000000000000000000000000000000000ffffffffffffffff958716640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909316939096169290921717929092169290921790925590549051859088907f77813be0661650ddc1a5193ff2837df4162b251cb432651e2c060c3fc39756be90614865908790899033909283526001600160a01b03918216602084015216604082015260600190565b60405180910390a46148c5565b61487c8184612b26565b604080516001600160a01b0385168152336020820152600091839189917fcf0c92a2c6d7c42f488326b0cb900104b99984b6b218db81cd29371364a35251910160405180910390a45b95945050505050565b5080546000825560020290600052602060002090810190611bbc91905b8082111561492957600081556001810180547fffffffff000000000000000000000000000000000000000000000000000000001690556002016148eb565b5090565b60006020828403121561493f57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114612b1f57600080fd5b6001600160a01b0381168114611bbc57600080fd5b60008083601f84011261499657600080fd5b50813567ffffffffffffffff8111156149ae57600080fd5b6020830191508360208285010111156149c657600080fd5b9250929050565b600080600080600080600060a0888a0312156149e857600080fd5b87359650602088013595506040880135614a018161496f565b9450606088013567ffffffffffffffff80821115614a1e57600080fd5b614a2a8b838c01614984565b909650945060808a0135915080821115614a4357600080fd5b50614a508a828b01614984565b989b979a50959850939692959293505050565b600060208284031215614a7557600080fd5b8135612b1f8161496f565b8015158114611bbc57600080fd5b6000806000806000806000806000806101008b8d031215614aae57600080fd5b8a35995060208b0135985060408b0135614ac78161496f565b975060608b0135614ad78161496f565b965060808b0135955060a08b0135614aee81614a80565b945060c08b013567ffffffffffffffff80821115614b0b57600080fd5b614b178e838f01614984565b909650945060e08d0135915080821115614b3057600080fd5b50614b3d8d828e01614984565b915080935050809150509295989b9194979a5092959850565b600080600080600080600060c0888a031215614b7157600080fd5b8735965060208801359550604088013594506060880135614b918161496f565b93506080880135925060a088013567ffffffffffffffff811115614bb457600080fd5b614a508a828b01614984565b60008060408385031215614bd357600080fd5b823591506020830135614be58161496f565b809150509250929050565b600060208284031215614c0257600080fd5b5035919050565b60008060408385031215614c1c57600080fd5b8235614c278161496f565b91506020830135614be581614a80565b602080825282518282018190526000919060409081850190868401855b82811015614ca0578151805185528681015163ffffffff908116888701528682015116868601526060908101516001600160a01b03169085015260809093019290850190600101614c54565b5091979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff81118282101715614d0057614d00614cad565b60405290565b6040805190810167ffffffffffffffff81118282101715614d0057614d00614cad565b60405160e0810167ffffffffffffffff81118282101715614d0057614d00614cad565b604051601f8201601f1916810167ffffffffffffffff81118282101715614d7557614d75614cad565b604052919050565b600067ffffffffffffffff821115614d9757614d97614cad565b50601f01601f191660200190565b600082601f830112614db657600080fd5b8135614dc9614dc482614d7d565b614d4c565b818152846020838601011115614dde57600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600080600060e0888a031215614e1657600080fd5b8735965060208801359550604088013594506060880135614e368161496f565b93506080880135925060a0880135614e4d8161496f565b915060c088013567ffffffffffffffff811115614e6957600080fd5b614e758a828b01614da5565b91505092959891949750929550565b60008060408385031215614e9757600080fd5b8235614ea28161496f565b946020939093013593505050565b600080600080600080600080610100898b031215614ecd57600080fd5b8835614ed88161496f565b975060208901359650604089013595506060890135614ef68161496f565b94506080890135935060a0890135614f0d8161496f565b925060c089013567ffffffffffffffff80821115614f2a57600080fd5b614f368c838d01614da5565b935060e08b0135915080821115614f4c57600080fd5b50614f598b828c01614da5565b9150509295985092959890939650565b600060208284031215614f7b57600080fd5b8151612b1f81614a80565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561091c5761091c614f86565b600060208284031215614fda57600080fd5b8151612b1f8161496f565b600060208284031215614ff757600080fd5b5051919050565b60005b83811015615019578181015183820152602001615001565b50506000910152565b6000815180845261503a816020860160208601614ffe565b601f01601f19169290920160200192915050565b8481528360208201526001600160a01b038316604082015260a06060820152600060a082015260c06080820152600061508a60c0830184615022565b9695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600181815b8085111561511c57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561510257615102614f86565b8085161561510f57918102915b93841c93908002906150c8565b509250929050565b6000826151335750600161091c565b816151405750600061091c565b816001811461515657600281146151605761517c565b600191505061091c565b60ff84111561517157615171614f86565b50506001821b61091c565b5060208310610133831016604e8410600b841016171561519f575081810a61091c565b6151a983836150c3565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156151db576151db614f86565b029392505050565b6000612b1f8383615124565b8082018082111561091c5761091c614f86565b85815284602082015260a06040820152600061522160a0830186615022565b82810360608401526152338186615022565b9150506001600160a01b03831660808301529695505050505050565b60006101406001600160a01b03808b168452615298602085018b6001600160a01b0381511682526020810151602083015260408101516040830152606081015160608301525050565b8860a08501528760c085015280871660e085015250806101008401526152c081840186615022565b90508281036101208401526152d58185615022565b9a9950505050505050505050565b80516152ee8161496f565b919050565b6000610120828403121561530657600080fd5b61530e614cdc565b9050815181526020820151602082015260408201516040820152606082015160608201526080820151608082015260a082015160a082015260c082015160c082015261535c60e083016152e3565b60e082015261010080830151818301525092915050565b600067ffffffffffffffff82111561538d5761538d614cad565b5060051b60200190565b600082601f8301126153a857600080fd5b81516153b6614dc482614d7d565b8181528460208386010111156153cb57600080fd5b6119d1826020830160208701614ffe565b60008060008061018085870312156153f357600080fd5b6153fd86866152f3565b9350610120850151925061014085015167ffffffffffffffff8082111561542357600080fd5b818701915087601f83011261543757600080fd5b81516020615447614dc483615373565b82815260069290921b8401810191818101908b84111561546657600080fd5b948201945b838610156154b2576040868d0312156154845760008081fd5b61548c614d06565b86516154978161496f565b8152868401518482015282526040909501949082019061546b565b6101608b01519097509450505050808211156154cd57600080fd5b506154da87828801615397565b91505092959194509250565b80516001600160a01b031682526000610200602083810151858201526040808501518187015260608086015180516001600160a01b0316828901529283015160808801529082015160a087015281015160c086015250608083015180516001600160a01b031660e08601526020810151610100860152604081015161012086015260608101516101408601525060a083015161016085015260c08301516001600160a01b0381166101808601525060e08301518015156101a086015250610100830151816101c08601526155bc82860182615022565b9150506101208301518482036101e08601526148c58282615022565b602081526000612b1f60208301846154e6565b6060815260006155fe60608301866154e6565b90508360208301526001600160a01b0383166040830152949350505050565b60006001600160a01b03808a168352808916602084015287604084015286606084015260e0608084015261565460e0840187615022565b83810360a08501526156668187615022565b92505080841660c08401525098975050505050505050565b600080610140838503121561569257600080fd5b61569c84846152f3565b915061012083015190509250929050565b60006001600160a01b03808b16835289602084015288604084015287606084015286608084015260e060a08401528460e08401526101008587828601376000848701820152931660c083015250601f909201601f1916909101019695505050505050565b60006101008983528860208401526001600160a01b03808916604085015280881660608501525085608084015284151560a08401528060c0840152600081840152506101208060e08401526152d581840185615022565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156157a0576157a0614f86565b500290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261580a577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60006001600160a01b03808916835287602084015286604084015285606084015260c0608084015261584460c0840186615022565b915080841660a084015250979650505050505050565b6001600160a01b038616815284602082015283604082015260a06060820152600061588860a0830185615022565b8281036080840152610d3c8185615022565b60008060008061018085870312156158b157600080fd5b6158bb86866152f3565b9350610120850151925061014085015167ffffffffffffffff808211156158e157600080fd5b818701915087601f8301126158f557600080fd5b81516020615905614dc483615373565b82815260069290921b8401810191818101908b84111561592457600080fd5b948201945b838610156154b2576040868d0312156159425760008081fd5b61594a614d06565b86516159558161496f565b81528684015184820152825260409095019490820190615929565b80516001600160a01b0316825260006101e060208301516020850152604083015160408501526060830151606085015260808301516159dc60808601826001600160a01b0381511682526020810151602083015260408101516040830152606081015160608301525050565b5060a083015180516001600160a01b03908116610100878101919091526020830151610120880152604083015161014088015260609092015161016087015260c08501511661018086015260e08401516101a0860183905290615a4183870183615022565b9250808501519150508482036101c08601526148c58282615022565b602081526000612b1f6020830184615970565b6060815260006155fe6060830186615970565b60006020808385031215615a9657600080fd5b825167ffffffffffffffff811115615aad57600080fd5b8301601f81018513615abe57600080fd5b8051615acc614dc482615373565b81815260e09182028301840191848201919088841115615aeb57600080fd5b938501935b83851015615b815780858a031215615b085760008081fd5b615b10614d29565b8551615b1b81614a80565b815285870151615b2a81614a80565b818801526040868101519082015260608087015190820152608080870151615b518161496f565b9082015260a0868101519082015260c080870151615b6e8161496f565b9082015283529384019391850191615af0565b50979650505050505050565b6101208101615bee8286805115158252602081015115156020830152604081015160408301526060810151606083015260808101516001600160a01b03808216608085015260a083015160a08501528060c08401511660c085015250505050565b8360e08301526001600160a01b03831661010083015294935050505056fea26469706673582212209a0821b8d0e0d584f8a3d44469c86fb05dc17e11fce0e25a17cf53905ee054f064736f6c63430008100033", "devdoc": { diff --git a/deployments/goerli/JBETHPaymentTerminal3_1.json b/deployments/goerli/JBETHPaymentTerminal3_1.json index 232979d2c..52c56b899 100644 --- a/deployments/goerli/JBETHPaymentTerminal3_1.json +++ b/deployments/goerli/JBETHPaymentTerminal3_1.json @@ -1883,7 +1883,7 @@ ], "numDeployments": 1, "solcInputHash": "9d8f961b8d6848d1dd32ae08288e8c6a", - "metadata": "{\"compiler\":{\"version\":\"0.8.16+commit.07a7930e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_baseWeightCurrency\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBOperatorStore\",\"name\":\"_operatorStore\",\"type\":\"address\"},{\"internalType\":\"contract IJBProjects\",\"name\":\"_projects\",\"type\":\"address\"},{\"internalType\":\"contract IJBDirectory\",\"name\":\"_directory\",\"type\":\"address\"},{\"internalType\":\"contract IJBSplitsStore\",\"name\":\"_splitsStore\",\"type\":\"address\"},{\"internalType\":\"contract IJBPrices\",\"name\":\"_prices\",\"type\":\"address\"},{\"internalType\":\"contract IJBSingleTokenPaymentTerminalStore\",\"name\":\"_store\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"FEE_TOO_HIGH\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INADEQUATE_DISTRIBUTION_AMOUNT\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INADEQUATE_RECLAIM_AMOUNT\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INADEQUATE_TOKEN_COUNT\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NO_MSG_VALUE_ALLOWED\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PAY_TO_ZERO_ADDRESS\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"prod1\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"denominator\",\"type\":\"uint256\"}],\"name\":\"PRBMath__MulDivOverflow\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PROJECT_TERMINAL_MISMATCH\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"REDEEM_TO_ZERO_ADDRESS\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TERMINAL_IN_SPLIT_ZERO_ADDRESS\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TERMINAL_TOKENS_INCOMPATIBLE\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UNAUTHORIZED\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"refundedFees\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AddToBalance\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IJBPayDelegate\",\"name\":\"delegate\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"currentFundingCycleConfiguration\",\"type\":\"uint256\"},{\"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\"},{\"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\":\"forwardedAmount\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"projectTokenCount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"preferClaimedTokens\",\"type\":\"bool\"},{\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"struct JBDidPayData\",\"name\":\"data\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"delegatedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"DelegateDidPay\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IJBRedemptionDelegate\",\"name\":\"delegate\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"currentFundingCycleConfiguration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"projectTokenCount\",\"type\":\"uint256\"},{\"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\":\"reclaimedAmount\",\"type\":\"tuple\"},{\"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\":\"forwardedAmount\",\"type\":\"tuple\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"struct JBDidRedeemData\",\"name\":\"data\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"delegatedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"DelegateDidRedeem\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleConfiguration\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleNumber\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"distributedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"beneficiaryDistributionAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"DistributePayouts\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"domain\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"group\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"preferClaimed\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"preferAddToBalance\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"percent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"lockedUntil\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBSplitAllocator\",\"name\":\"allocator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"struct JBSplit\",\"name\":\"split\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"netAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"DistributeToPayoutSplit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"feeProjectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"reason\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"FeeReverted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"feeDiscount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"HoldFee\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"contract IJBPaymentTerminal\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Migrate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleConfiguration\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleNumber\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"beneficiaryTokenCount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Pay\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"preferClaimed\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"preferAddToBalance\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"percent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"lockedUntil\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBSplitAllocator\",\"name\":\"allocator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"struct JBSplit\",\"name\":\"split\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"reason\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"PayoutReverted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"wasHeld\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"ProcessFee\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleConfiguration\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleNumber\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenCount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"reclaimedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"RedeemTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"refundedFees\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"leftoverAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"RefundHeldFees\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"SetFee\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IJBFeeGauge\",\"name\":\"feeGauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"SetFeeGauge\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"addrs\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"flag\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"SetFeelessAddress\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleConfiguration\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleNumber\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"distributedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"netDistributedamount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"UseAllowance\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"}],\"name\":\"acceptsToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"addToBalanceOf\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_shouldRefundHeldFees\",\"type\":\"bool\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"addToBalanceOf\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"baseWeightCurrency\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currency\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"currencyForToken\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"}],\"name\":\"currentEthOverflowOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"decimalsForToken\",\"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\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_currency\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_minReturnedTokens\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"distributePayoutsOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"netLeftoverDistributionAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"feeGauge\",\"outputs\":[{\"internalType\":\"contract IJBFeeGauge\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"}],\"name\":\"heldFeesOf\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"fee\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"feeDiscount\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"internalType\":\"struct JBFee[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isFeelessAddress\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBPaymentTerminal\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"migrate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"operatorStore\",\"outputs\":[{\"internalType\":\"contract IJBOperatorStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_minReturnedTokens\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"_preferClaimedTokens\",\"type\":\"bool\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"pay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"payoutSplitsGroup\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"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\"}],\"name\":\"processFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"projects\",\"outputs\":[{\"internalType\":\"contract IJBProjects\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_holder\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_tokenCount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_minReturnedTokens\",\"type\":\"uint256\"},{\"internalType\":\"address payable\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"redeemTokensOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"reclaimAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_fee\",\"type\":\"uint256\"}],\"name\":\"setFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IJBFeeGauge\",\"name\":\"_feeGauge\",\"type\":\"address\"}],\"name\":\"setFeeGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_flag\",\"type\":\"bool\"}],\"name\":\"setFeelessAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"splitsStore\",\"outputs\":[{\"internalType\":\"contract IJBSplitsStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"store\",\"outputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminalStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_currency\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_minReturnedTokens\",\"type\":\"uint256\"},{\"internalType\":\"address payable\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"useAllowanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"netDistributedAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Inherits from - JBPayoutRedemptionPaymentTerminal3_1: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\",\"kind\":\"dev\",\"methods\":{\"acceptsToken(address,uint256)\":{\"params\":{\"_projectId\":\"The project ID to check for token acceptance.\",\"_token\":\"The token to check if this terminal accepts or not.\"},\"returns\":{\"_0\":\"The flag.\"}},\"addToBalanceOf(uint256,uint256,address,bool,string,bytes)\":{\"params\":{\"_amount\":\"The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\",\"_memo\":\"A memo to pass along to the emitted event.\",\"_metadata\":\"Extra data to pass along to the emitted event.\",\"_projectId\":\"The ID of the project to which the funds received belong.\",\"_shouldRefundHeldFees\":\"A flag indicating if held fees should be refunded based on the amount being added.\",\"_token\":\"The token being paid. This terminal ignores this property since it only manages one currency. \"}},\"addToBalanceOf(uint256,uint256,address,string,bytes)\":{\"params\":{\"_amount\":\"The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\",\"_memo\":\"A memo to pass along to the emitted event.\",\"_metadata\":\"Extra data to pass along to the emitted event.\",\"_projectId\":\"The ID of the project to which the funds received belong.\",\"_token\":\"The token being paid. This terminal ignores this property since it only manages one currency. \"}},\"constructor\":{\"params\":{\"_baseWeightCurrency\":\"The currency to base token issuance on.\",\"_directory\":\"A contract storing directories of terminals and controllers for each project.\",\"_operatorStore\":\"A contract storing operator assignments.\",\"_owner\":\"The address that will own this contract.\",\"_prices\":\"A contract that exposes price feeds.\",\"_projects\":\"A contract which mints ERC-721's that represent project ownership and transfers.\",\"_splitsStore\":\"A contract that stores splits for each project.\",\"_store\":\"A contract that stores the terminal's data.\"}},\"currencyForToken(address)\":{\"params\":{\"_token\":\"The token to check for the currency of.\"},\"returns\":{\"_0\":\"The currency index.\"}},\"currentEthOverflowOf(uint256)\":{\"details\":\"The current overflow is represented as a fixed point number with 18 decimals.\",\"params\":{\"_projectId\":\"The ID of the project to get overflow for.\"},\"returns\":{\"_0\":\"The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\"}},\"decimalsForToken(address)\":{\"params\":{\"_token\":\"The token to check for the decimals of.\"},\"returns\":{\"_0\":\"The number of decimals for the token.\"}},\"distributePayoutsOf(uint256,uint256,uint256,address,uint256,bytes)\":{\"details\":\"Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\",\"params\":{\"_amount\":\"The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\",\"_currency\":\"The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\",\"_metadata\":\"Bytes to send along to the emitted event, if provided.\",\"_minReturnedTokens\":\"The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\",\"_projectId\":\"The ID of the project having its payouts distributed.\",\"_token\":\"The token being distributed. This terminal ignores this property since it only manages one token. \"},\"returns\":{\"netLeftoverDistributionAmount\":\"The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\"}},\"heldFeesOf(uint256)\":{\"params\":{\"_projectId\":\"The ID of the project for which fees are being held.\"},\"returns\":{\"_0\":\"An array of fees that are being held.\"}},\"migrate(uint256,address)\":{\"details\":\"Only a project's owner or a designated operator can migrate it.\",\"params\":{\"_projectId\":\"The ID of the project being migrated.\",\"_to\":\"The terminal contract that will gain the project's funds.\"},\"returns\":{\"balance\":\"The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pay(uint256,uint256,address,address,uint256,bool,string,bytes)\":{\"params\":{\"_amount\":\"The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\",\"_beneficiary\":\"The address to mint tokens for and pass along to the funding cycle's data source and delegate.\",\"_memo\":\"A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\",\"_metadata\":\"Bytes to send along to the data source, delegate, and emitted event, if provided.\",\"_minReturnedTokens\":\"The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\",\"_preferClaimedTokens\":\"A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\",\"_projectId\":\"The ID of the project being paid.\",\"_token\":\"The token being paid. This terminal ignores this property since it only manages one token. \"},\"returns\":{\"_0\":\"The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\"}},\"processFees(uint256)\":{\"details\":\"Only a project owner, an operator, or the contract's owner can process held fees.\",\"params\":{\"_projectId\":\"The ID of the project whos held fees should be processed.\"}},\"redeemTokensOf(address,uint256,uint256,address,uint256,address,string,bytes)\":{\"details\":\"Only a token holder or a designated operator can redeem its tokens.\",\"params\":{\"_beneficiary\":\"The address to send the terminal tokens to.\",\"_holder\":\"The account to redeem tokens for.\",\"_memo\":\"A memo to pass along to the emitted event.\",\"_metadata\":\"Bytes to send along to the data source, delegate, and emitted event, if provided.\",\"_minReturnedTokens\":\"The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\",\"_projectId\":\"The ID of the project to which the tokens being redeemed belong.\",\"_token\":\"The token being reclaimed. This terminal ignores this property since it only manages one token. \",\"_tokenCount\":\"The number of project tokens to redeem, as a fixed point number with 18 decimals.\"},\"returns\":{\"reclaimAmount\":\"The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"setFee(uint256)\":{\"details\":\"Only the owner of this contract can change the fee.\",\"params\":{\"_fee\":\"The new fee, out of MAX_FEE.\"}},\"setFeeGauge(address)\":{\"details\":\"Only the owner of this contract can change the fee gauge.\",\"params\":{\"_feeGauge\":\"The new fee gauge.\"}},\"setFeelessAddress(address,bool)\":{\"details\":\"Only the owner of this contract can set addresses as feeless.\",\"params\":{\"_address\":\"The address that can be paid towards while still bypassing fees.\",\"_flag\":\"A flag indicating whether the terminal should be feeless or not.\"}},\"supportsInterface(bytes4)\":{\"details\":\" See {IERC165-supportsInterface}.\",\"params\":{\"_interfaceId\":\"The ID of the interface to check for adherance to.\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"useAllowanceOf(uint256,uint256,uint256,address,uint256,address,string,bytes)\":{\"details\":\"Only a project's owner or a designated operator can use its allowance.Incurs the protocol fee.\",\"params\":{\"_amount\":\"The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\",\"_beneficiary\":\"The address to send the funds to.\",\"_currency\":\"The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\",\"_memo\":\"A memo to pass along to the emitted event.\",\"_metadata\":\"Bytes to send along to the emitted event, if provided.\",\"_minReturnedTokens\":\"The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\",\"_projectId\":\"The ID of the project to use the allowance of.\",\"_token\":\"The token being distributed. This terminal ignores this property since it only manages one token. \"},\"returns\":{\"netDistributedAmount\":\"The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\"}}},\"version\":1},\"userdoc\":{\"errors\":{\"PRBMath__MulDivOverflow(uint256,uint256)\":[{\"notice\":\"Emitted when the result overflows uint256.\"}]},\"kind\":\"user\",\"methods\":{\"acceptsToken(address,uint256)\":{\"notice\":\"A flag indicating if this terminal accepts the specified token.\"},\"addToBalanceOf(uint256,uint256,address,bool,string,bytes)\":{\"notice\":\"Receives funds belonging to the specified project.\"},\"addToBalanceOf(uint256,uint256,address,string,bytes)\":{\"notice\":\"Receives funds belonging to the specified project.\"},\"baseWeightCurrency()\":{\"notice\":\"The currency to base token issuance on.\"},\"currency()\":{\"notice\":\"The currency to use when resolving price feeds for this terminal.\"},\"currencyForToken(address)\":{\"notice\":\"The currency that should be used for the specified token.\"},\"currentEthOverflowOf(uint256)\":{\"notice\":\"Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\"},\"decimals()\":{\"notice\":\"The number of decimals the token fixed point amounts are expected to have.\"},\"decimalsForToken(address)\":{\"notice\":\"The decimals that should be used in fixed number accounting for the specified token.\"},\"directory()\":{\"notice\":\"The directory of terminals and controllers for projects.\"},\"distributePayoutsOf(uint256,uint256,uint256,address,uint256,bytes)\":{\"notice\":\"Distributes payouts for a project with the distribution limit of its current funding cycle.\"},\"fee()\":{\"notice\":\"The platform fee percent.\"},\"feeGauge()\":{\"notice\":\"The data source that returns a discount to apply to a project's fee.\"},\"heldFeesOf(uint256)\":{\"notice\":\"The fees that are currently being held to be processed later for each project.\"},\"isFeelessAddress(address)\":{\"notice\":\"Addresses that can be paid towards from this terminal without incurring a fee.\"},\"migrate(uint256,address)\":{\"notice\":\"Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\"},\"operatorStore()\":{\"notice\":\" A contract storing operator assignments.\"},\"pay(uint256,uint256,address,address,uint256,bool,string,bytes)\":{\"notice\":\"Contribute tokens to a project.\"},\"payoutSplitsGroup()\":{\"notice\":\"The group that payout splits coming from this terminal are identified by.\"},\"prices()\":{\"notice\":\"The contract that exposes price feeds.\"},\"processFees(uint256)\":{\"notice\":\"Process any fees that are being held for the project.\"},\"projects()\":{\"notice\":\"Mints ERC-721's that represent project ownership and transfers.\"},\"redeemTokensOf(address,uint256,uint256,address,uint256,address,string,bytes)\":{\"notice\":\"Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\"},\"setFee(uint256)\":{\"notice\":\"Allows the fee to be updated.\"},\"setFeeGauge(address)\":{\"notice\":\"Allows the fee gauge to be updated.\"},\"setFeelessAddress(address,bool)\":{\"notice\":\"Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\"},\"splitsStore()\":{\"notice\":\"The contract that stores splits for each project.\"},\"store()\":{\"notice\":\"The contract that stores and manages the terminal's data.\"},\"supportsInterface(bytes4)\":{\"notice\":\"Indicates if this contract adheres to the specified interface.\"},\"token()\":{\"notice\":\"The token that this terminal accepts.\"},\"useAllowanceOf(uint256,uint256,uint256,address,uint256,address,string,bytes)\":{\"notice\":\"Allows a project to send funds from its overflow up to the preconfigured allowance.\"}},\"notice\":\"Manages all inflows and outflows of ETH funds into the protocol ecosystem.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/JBETHPaymentTerminal3_1.sol\":\"JBETHPaymentTerminal3_1\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0x24e0364e503a9bbde94c715d26573a76f14cd2a202d45f96f52134ab806b67b9\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool _approved) external;\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x516a22876c1fab47f49b1bc22b4614491cd05338af8bd2e7b382da090a079990\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3777e696b62134e6177440dbe6e6601c0c156a443f57167194b67e75527439de\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165Checker.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Library used to query support of an interface declared via {IERC165}.\\n *\\n * Note that these functions return the actual result of the query: they do not\\n * `revert` if an interface is not supported. It is up to the caller to decide\\n * what to do in these cases.\\n */\\nlibrary ERC165Checker {\\n // As per the EIP-165 spec, no interface should ever match 0xffffffff\\n bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;\\n\\n /**\\n * @dev Returns true if `account` supports the {IERC165} interface,\\n */\\n function supportsERC165(address account) internal view returns (bool) {\\n // Any contract that implements ERC165 must explicitly indicate support of\\n // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid\\n return\\n _supportsERC165Interface(account, type(IERC165).interfaceId) &&\\n !_supportsERC165Interface(account, _INTERFACE_ID_INVALID);\\n }\\n\\n /**\\n * @dev Returns true if `account` supports the interface defined by\\n * `interfaceId`. Support for {IERC165} itself is queried automatically.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {\\n // query support of both ERC165 as per the spec and support of _interfaceId\\n return supportsERC165(account) && _supportsERC165Interface(account, interfaceId);\\n }\\n\\n /**\\n * @dev Returns a boolean array where each value corresponds to the\\n * interfaces passed in and whether they're supported or not. This allows\\n * you to batch check interfaces for a contract where your expectation\\n * is that some interfaces may not be supported.\\n *\\n * See {IERC165-supportsInterface}.\\n *\\n * _Available since v3.4._\\n */\\n function getSupportedInterfaces(address account, bytes4[] memory interfaceIds)\\n internal\\n view\\n returns (bool[] memory)\\n {\\n // an array of booleans corresponding to interfaceIds and whether they're supported or not\\n bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);\\n\\n // query support of ERC165 itself\\n if (supportsERC165(account)) {\\n // query support of each interface in interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n interfaceIdsSupported[i] = _supportsERC165Interface(account, interfaceIds[i]);\\n }\\n }\\n\\n return interfaceIdsSupported;\\n }\\n\\n /**\\n * @dev Returns true if `account` supports all the interfaces defined in\\n * `interfaceIds`. Support for {IERC165} itself is queried automatically.\\n *\\n * Batch-querying can lead to gas savings by skipping repeated checks for\\n * {IERC165} support.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {\\n // query support of ERC165 itself\\n if (!supportsERC165(account)) {\\n return false;\\n }\\n\\n // query support of each interface in _interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n if (!_supportsERC165Interface(account, interfaceIds[i])) {\\n return false;\\n }\\n }\\n\\n // all interfaces supported\\n return true;\\n }\\n\\n /**\\n * @notice Query if a contract implements an interface, does not check ERC165 support\\n * @param account The address of the contract to query for support of an interface\\n * @param interfaceId The interface identifier, as specified in ERC-165\\n * @return true if the contract at account indicates support of the interface with\\n * identifier interfaceId, false otherwise\\n * @dev Assumes that account contains a contract that supports ERC165, otherwise\\n * the behavior of this method is undefined. This precondition can be checked\\n * with {supportsERC165}.\\n * Interface identification is specified in ERC-165.\\n */\\n function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) {\\n bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);\\n (bool success, bytes memory result) = account.staticcall{gas: 30000}(encodedParams);\\n if (result.length < 32) return false;\\n return success && abi.decode(result, (bool));\\n }\\n}\\n\",\"keccak256\":\"0xf7291d7213336b00ee7edbf7cd5034778dd7b0bda2a7489e664f1e5cacc6c24e\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"@paulrberg/contracts/math/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\nimport \\\"prb-math/contracts/PRBMath.sol\\\";\\n\",\"keccak256\":\"0x42821345981bc0434a90ba2268a2f5278dfe9e38166981d72fc7f3b776a29495\",\"license\":\"Unlicense\"},\"contracts/JBETHPaymentTerminal3_1.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport '@openzeppelin/contracts/utils/Address.sol';\\nimport './abstract/JBPayoutRedemptionPaymentTerminal3_1.sol';\\nimport './libraries/JBSplitsGroups.sol';\\n\\n/**\\n @notice\\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\\n\\n @dev\\n Inherits from -\\n JBPayoutRedemptionPaymentTerminal3_1: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\\n*/\\ncontract JBETHPaymentTerminal3_1 is JBPayoutRedemptionPaymentTerminal3_1 {\\n //*********************************************************************//\\n // -------------------------- internal views ------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Checks the balance of tokens in this contract.\\n\\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\\n */\\n function _balance() internal view override returns (uint256) {\\n return address(this).balance;\\n }\\n\\n //*********************************************************************//\\n // -------------------------- constructor ---------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @param _baseWeightCurrency The currency to base token issuance on.\\n @param _operatorStore A contract storing operator assignments.\\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\\n @param _directory A contract storing directories of terminals and controllers for each project.\\n @param _splitsStore A contract that stores splits for each project.\\n @param _prices A contract that exposes price feeds.\\n @param _store A contract that stores the terminal's data.\\n @param _owner The address that will own this contract.\\n */\\n constructor(\\n uint256 _baseWeightCurrency,\\n IJBOperatorStore _operatorStore,\\n IJBProjects _projects,\\n IJBDirectory _directory,\\n IJBSplitsStore _splitsStore,\\n IJBPrices _prices,\\n IJBSingleTokenPaymentTerminalStore _store,\\n address _owner\\n )\\n JBPayoutRedemptionPaymentTerminal3_1(\\n JBTokens.ETH,\\n 18, // 18 decimals.\\n JBCurrencies.ETH,\\n _baseWeightCurrency,\\n JBSplitsGroups.ETH_PAYOUT,\\n _operatorStore,\\n _projects,\\n _directory,\\n _splitsStore,\\n _prices,\\n _store,\\n _owner\\n )\\n // solhint-disable-next-line no-empty-blocks\\n {\\n\\n }\\n\\n //*********************************************************************//\\n // ---------------------- internal transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Transfers tokens.\\n\\n @param _from The address from which the transfer should originate.\\n @param _to The address to which the transfer should go.\\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\\n */\\n function _transferFrom(\\n address _from,\\n address payable _to,\\n uint256 _amount\\n ) internal override {\\n _from; // Prevents unused var compiler and natspec complaints.\\n\\n Address.sendValue(_to, _amount);\\n }\\n}\\n\",\"keccak256\":\"0x51cd7cb442d31c0cede341af67b5ed069d467a72cb812dad5c0763f51960bbe5\",\"license\":\"MIT\"},\"contracts/abstract/JBOperatable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport './../interfaces/IJBOperatable.sol';\\n\\n/** \\n @notice\\n Modifiers to allow access to functions based on the message sender's operator status.\\n\\n @dev\\n Adheres to -\\n IJBOperatable: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n*/\\nabstract contract JBOperatable is IJBOperatable {\\n //*********************************************************************//\\n // --------------------------- custom errors -------------------------- //\\n //*********************************************************************//\\n error UNAUTHORIZED();\\n\\n //*********************************************************************//\\n // ---------------------------- modifiers ---------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Only allows the speficied account or an operator of the account to proceed. \\n\\n @param _account The account to check for.\\n @param _domain The domain namespace to look for an operator within. \\n @param _permissionIndex The index of the permission to check for. \\n */\\n modifier requirePermission(\\n address _account,\\n uint256 _domain,\\n uint256 _permissionIndex\\n ) {\\n _requirePermission(_account, _domain, _permissionIndex);\\n _;\\n }\\n\\n /** \\n @notice\\n Only allows the speficied account, an operator of the account to proceed, or a truthy override flag. \\n\\n @param _account The account to check for.\\n @param _domain The domain namespace to look for an operator within. \\n @param _permissionIndex The index of the permission to check for. \\n @param _override A condition to force allowance for.\\n */\\n modifier requirePermissionAllowingOverride(\\n address _account,\\n uint256 _domain,\\n uint256 _permissionIndex,\\n bool _override\\n ) {\\n _requirePermissionAllowingOverride(_account, _domain, _permissionIndex, _override);\\n _;\\n }\\n\\n //*********************************************************************//\\n // ---------------- public immutable stored properties --------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n A contract storing operator assignments.\\n */\\n IJBOperatorStore public immutable override operatorStore;\\n\\n //*********************************************************************//\\n // -------------------------- constructor ---------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @param _operatorStore A contract storing operator assignments.\\n */\\n constructor(IJBOperatorStore _operatorStore) {\\n operatorStore = _operatorStore;\\n }\\n\\n //*********************************************************************//\\n // -------------------------- internal views ------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Require the message sender is either the account or has the specified permission.\\n\\n @param _account The account to allow.\\n @param _domain The domain namespace within which the permission index will be checked.\\n @param _permissionIndex The permission index that an operator must have within the specified domain to be allowed.\\n */\\n function _requirePermission(\\n address _account,\\n uint256 _domain,\\n uint256 _permissionIndex\\n ) internal view {\\n if (\\n msg.sender != _account &&\\n !operatorStore.hasPermission(msg.sender, _account, _domain, _permissionIndex) &&\\n !operatorStore.hasPermission(msg.sender, _account, 0, _permissionIndex)\\n ) revert UNAUTHORIZED();\\n }\\n\\n /** \\n @notice\\n Require the message sender is either the account, has the specified permission, or the override condition is true.\\n\\n @param _account The account to allow.\\n @param _domain The domain namespace within which the permission index will be checked.\\n @param _domain The permission index that an operator must have within the specified domain to be allowed.\\n @param _override The override condition to allow.\\n */\\n function _requirePermissionAllowingOverride(\\n address _account,\\n uint256 _domain,\\n uint256 _permissionIndex,\\n bool _override\\n ) internal view {\\n if (\\n !_override &&\\n msg.sender != _account &&\\n !operatorStore.hasPermission(msg.sender, _account, _domain, _permissionIndex) &&\\n !operatorStore.hasPermission(msg.sender, _account, 0, _permissionIndex)\\n ) revert UNAUTHORIZED();\\n }\\n}\\n\",\"keccak256\":\"0x9e62cac5c464eb973f881cf6c373b95aab31d2ddbeb048ee7ad82b5c9ab28add\",\"license\":\"MIT\"},\"contracts/abstract/JBPayoutRedemptionPaymentTerminal3_1.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport '@openzeppelin/contracts/access/Ownable.sol';\\nimport '@openzeppelin/contracts/utils/introspection/ERC165Checker.sol';\\nimport '@paulrberg/contracts/math/PRBMath.sol';\\nimport './../interfaces/IJBController.sol';\\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal3_1.sol';\\nimport './../libraries/JBConstants.sol';\\nimport './../libraries/JBCurrencies.sol';\\nimport './../libraries/JBFixedPointNumber.sol';\\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\\nimport './../libraries/JBOperations.sol';\\nimport './../libraries/JBTokens.sol';\\nimport './../structs/JBPayDelegateAllocation.sol';\\nimport './../structs/JBTokenAmount.sol';\\nimport './JBOperatable.sol';\\nimport './JBSingleTokenPaymentTerminal.sol';\\n\\n/**\\n @notice\\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\\n\\n @dev\\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\\n\\n @dev\\n Adheres to -\\n IJBPayoutRedemptionPaymentTerminal3_1: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n\\n @dev\\n Inherits from -\\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\\n*/\\nabstract contract JBPayoutRedemptionPaymentTerminal3_1 is\\n JBSingleTokenPaymentTerminal,\\n JBOperatable,\\n Ownable,\\n IJBPayoutRedemptionPaymentTerminal3_1\\n{\\n // A library that parses the packed funding cycle metadata into a friendlier format.\\n using JBFundingCycleMetadataResolver for JBFundingCycle;\\n\\n //*********************************************************************//\\n // --------------------------- custom errors ------------------------- //\\n //*********************************************************************//\\n error FEE_TOO_HIGH();\\n error INADEQUATE_DISTRIBUTION_AMOUNT();\\n error INADEQUATE_RECLAIM_AMOUNT();\\n error INADEQUATE_TOKEN_COUNT();\\n error NO_MSG_VALUE_ALLOWED();\\n error PAY_TO_ZERO_ADDRESS();\\n error PROJECT_TERMINAL_MISMATCH();\\n error REDEEM_TO_ZERO_ADDRESS();\\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\\n error TERMINAL_TOKENS_INCOMPATIBLE();\\n\\n //*********************************************************************//\\n // ---------------------------- modifiers ---------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n A modifier that verifies this terminal is a terminal of provided project ID.\\n */\\n modifier isTerminalOf(uint256 _projectId) {\\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\\n _;\\n }\\n\\n //*********************************************************************//\\n // --------------------- internal stored constants ------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Maximum fee that can be set for a funding cycle configuration.\\n\\n @dev\\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\\n */\\n uint256 internal constant _FEE_CAP = 50_000_000;\\n\\n /**\\n @notice\\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\\n */\\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\\n\\n //*********************************************************************//\\n // --------------------- internal stored properties ------------------ //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Fees that are being held to be processed later.\\n\\n _projectId The ID of the project for which fees are being held.\\n */\\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\\n\\n //*********************************************************************//\\n // ---------------- public immutable stored properties --------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Mints ERC-721's that represent project ownership and transfers.\\n */\\n IJBProjects public immutable override projects;\\n\\n /**\\n @notice\\n The directory of terminals and controllers for projects.\\n */\\n IJBDirectory public immutable override directory;\\n\\n /**\\n @notice\\n The contract that stores splits for each project.\\n */\\n IJBSplitsStore public immutable override splitsStore;\\n\\n /**\\n @notice\\n The contract that exposes price feeds.\\n */\\n IJBPrices public immutable override prices;\\n\\n /**\\n @notice\\n The contract that stores and manages the terminal's data.\\n */\\n IJBSingleTokenPaymentTerminalStore public immutable override store;\\n\\n /**\\n @notice\\n The currency to base token issuance on.\\n\\n @dev\\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\\n */\\n uint256 public immutable override baseWeightCurrency;\\n\\n /**\\n @notice\\n The group that payout splits coming from this terminal are identified by.\\n */\\n uint256 public immutable override payoutSplitsGroup;\\n\\n //*********************************************************************//\\n // --------------------- public stored properties -------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The platform fee percent.\\n\\n @dev\\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\\n */\\n uint256 public override fee = 25_000_000; // 2.5%\\n\\n /**\\n @notice\\n The data source that returns a discount to apply to a project's fee.\\n */\\n IJBFeeGauge public override feeGauge;\\n\\n /**\\n @notice\\n Addresses that can be paid towards from this terminal without incurring a fee.\\n\\n @dev\\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\\n\\n _address The address that can be paid toward.\\n */\\n mapping(address => bool) public override isFeelessAddress;\\n\\n //*********************************************************************//\\n // ------------------------- external views -------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\\n\\n @dev\\n The current overflow is represented as a fixed point number with 18 decimals.\\n\\n @param _projectId The ID of the project to get overflow for.\\n\\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\\n */\\n function currentEthOverflowOf(uint256 _projectId)\\n external\\n view\\n virtual\\n override\\n returns (uint256)\\n {\\n // Get this terminal's current overflow.\\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\\n\\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\\n uint256 _adjustedOverflow = (decimals == 18)\\n ? _overflow\\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\\n\\n // Return the amount converted to ETH.\\n return\\n (currency == JBCurrencies.ETH)\\n ? _adjustedOverflow\\n : PRBMath.mulDiv(\\n _adjustedOverflow,\\n 10**decimals,\\n prices.priceFor(currency, JBCurrencies.ETH, decimals)\\n );\\n }\\n\\n /**\\n @notice\\n The fees that are currently being held to be processed later for each project.\\n\\n @param _projectId The ID of the project for which fees are being held.\\n\\n @return An array of fees that are being held.\\n */\\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\\n return _heldFeesOf[_projectId];\\n }\\n\\n //*********************************************************************//\\n // -------------------------- public views --------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Indicates if this contract adheres to the specified interface.\\n\\n @dev \\n See {IERC165-supportsInterface}.\\n\\n @param _interfaceId The ID of the interface to check for adherance to.\\n */\\n function supportsInterface(bytes4 _interfaceId)\\n public\\n view\\n virtual\\n override(JBSingleTokenPaymentTerminal, IERC165)\\n returns (bool)\\n {\\n return\\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal3_1).interfaceId ||\\n _interfaceId == type(IJBPayoutTerminal3_1).interfaceId ||\\n _interfaceId == type(IJBAllowanceTerminal3_1).interfaceId ||\\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\\n _interfaceId == type(IJBOperatable).interfaceId ||\\n super.supportsInterface(_interfaceId);\\n }\\n\\n //*********************************************************************//\\n // -------------------------- internal views ------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Checks the balance of tokens in this contract.\\n\\n @return The contract's balance.\\n */\\n function _balance() internal view virtual returns (uint256);\\n\\n //*********************************************************************//\\n // -------------------------- constructor ---------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @param _token The token that this terminal manages.\\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\\n @param _currency The currency that this terminal's token adheres to for price feeds.\\n @param _baseWeightCurrency The currency to base token issuance on.\\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\\n @param _operatorStore A contract storing operator assignments.\\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\\n @param _directory A contract storing directories of terminals and controllers for each project.\\n @param _splitsStore A contract that stores splits for each project.\\n @param _prices A contract that exposes price feeds.\\n @param _store A contract that stores the terminal's data.\\n @param _owner The address that will own this contract.\\n */\\n constructor(\\n // payable constructor save the gas used to check msg.value==0\\n address _token,\\n uint256 _decimals,\\n uint256 _currency,\\n uint256 _baseWeightCurrency,\\n uint256 _payoutSplitsGroup,\\n IJBOperatorStore _operatorStore,\\n IJBProjects _projects,\\n IJBDirectory _directory,\\n IJBSplitsStore _splitsStore,\\n IJBPrices _prices,\\n IJBSingleTokenPaymentTerminalStore _store,\\n address _owner\\n )\\n payable\\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\\n JBOperatable(_operatorStore)\\n {\\n baseWeightCurrency = _baseWeightCurrency;\\n payoutSplitsGroup = _payoutSplitsGroup;\\n projects = _projects;\\n directory = _directory;\\n splitsStore = _splitsStore;\\n prices = _prices;\\n store = _store;\\n\\n transferOwnership(_owner);\\n }\\n\\n //*********************************************************************//\\n // ---------------------- external transactions ---------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Contribute tokens to a project.\\n\\n @param _projectId The ID of the project being paid.\\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\\n\\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\\n */\\n function pay(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n // ETH shouldn't be sent if this terminal's token isn't ETH.\\n if (token != JBTokens.ETH) {\\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\\n\\n // Get a reference to the balance before receiving tokens.\\n uint256 _balanceBefore = _balance();\\n\\n // Transfer tokens to this terminal from the msg sender.\\n _transferFrom(msg.sender, payable(address(this)), _amount);\\n\\n // The amount should reflect the change in balance.\\n _amount = _balance() - _balanceBefore;\\n }\\n // If this terminal's token is ETH, override _amount with msg.value.\\n else _amount = msg.value;\\n\\n return\\n _pay(\\n _amount,\\n msg.sender,\\n _projectId,\\n _beneficiary,\\n _minReturnedTokens,\\n _preferClaimedTokens,\\n _memo,\\n _metadata\\n );\\n }\\n\\n /**\\n @notice\\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\\n\\n @dev\\n Only a token holder or a designated operator can redeem its tokens.\\n\\n @param _holder The account to redeem tokens for.\\n @param _projectId The ID of the project to which the tokens being redeemed belong.\\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\\n @param _beneficiary The address to send the terminal tokens to.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\\n\\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\\n */\\n function redeemTokensOf(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n address _token,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string memory _memo,\\n bytes memory _metadata\\n )\\n external\\n virtual\\n override\\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\\n returns (uint256 reclaimAmount)\\n {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n return\\n _redeemTokensOf(\\n _holder,\\n _projectId,\\n _tokenCount,\\n _minReturnedTokens,\\n _beneficiary,\\n _memo,\\n _metadata\\n );\\n }\\n\\n /**\\n @notice\\n Distributes payouts for a project with the distribution limit of its current funding cycle.\\n\\n @dev\\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\\n\\n @dev\\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\\n\\n @dev\\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\\n\\n @param _projectId The ID of the project having its payouts distributed.\\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\\n @param _metadata Bytes to send along to the emitted event, if provided.\\n\\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\\n */\\n function distributePayoutsOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n address _token,\\n uint256 _minReturnedTokens,\\n bytes calldata _metadata\\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _metadata);\\n }\\n\\n /**\\n @notice\\n Allows a project to send funds from its overflow up to the preconfigured allowance.\\n\\n @dev\\n Only a project's owner or a designated operator can use its allowance.\\n\\n @dev\\n Incurs the protocol fee.\\n\\n @param _projectId The ID of the project to use the allowance of.\\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\\n @param _beneficiary The address to send the funds to.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Bytes to send along to the emitted event, if provided.\\n\\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\\n */\\n function useAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n address _token,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string memory _memo,\\n bytes calldata _metadata\\n )\\n external\\n virtual\\n override\\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\\n returns (uint256 netDistributedAmount)\\n {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n return\\n _useAllowanceOf(\\n _projectId,\\n _amount,\\n _currency,\\n _minReturnedTokens,\\n _beneficiary,\\n _memo,\\n _metadata\\n );\\n }\\n\\n /**\\n @notice\\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\\n\\n @dev\\n Only a project's owner or a designated operator can migrate it.\\n\\n @param _projectId The ID of the project being migrated.\\n @param _to The terminal contract that will gain the project's funds.\\n\\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\\n */\\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\\n external\\n virtual\\n override\\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\\n returns (uint256 balance)\\n {\\n // The terminal being migrated to must accept the same token as this terminal.\\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\\n\\n // Record the migration in the store.\\n balance = store.recordMigration(_projectId);\\n\\n // Transfer the balance if needed.\\n if (balance > 0) {\\n // Trigger any inherited pre-transfer logic.\\n _beforeTransferTo(address(_to), balance);\\n\\n // If this terminal's token is ETH, send it in msg.value.\\n uint256 _payableValue = token == JBTokens.ETH ? balance : 0;\\n\\n // Withdraw the balance to transfer to the new terminal;\\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\\n }\\n\\n emit Migrate(_projectId, _to, balance, msg.sender);\\n }\\n\\n /**\\n @notice\\n Receives funds belonging to the specified project.\\n\\n @param _projectId The ID of the project to which the funds received belong.\\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Extra data to pass along to the emitted event.\\n */\\n function addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable virtual override isTerminalOf(_projectId) {\\n // Do not refund held fees by default.\\n addToBalanceOf(_projectId, _amount, _token, false, _memo, _metadata);\\n }\\n\\n /**\\n @notice\\n Process any fees that are being held for the project.\\n\\n @dev\\n Only a project owner, an operator, or the contract's owner can process held fees.\\n\\n @param _projectId The ID of the project whos held fees should be processed.\\n */\\n function processFees(uint256 _projectId)\\n external\\n virtual\\n override\\n requirePermissionAllowingOverride(\\n projects.ownerOf(_projectId),\\n _projectId,\\n JBOperations.PROCESS_FEES,\\n msg.sender == owner()\\n )\\n {\\n // Get a reference to the project's held fees.\\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\\n\\n // Delete the held fees.\\n delete _heldFeesOf[_projectId];\\n\\n // Push array length in stack\\n uint256 _heldFeeLength = _heldFees.length;\\n\\n // Process each fee.\\n for (uint256 _i; _i < _heldFeeLength; ) {\\n // Get the fee amount.\\n uint256 _amount = _feeAmount(\\n _heldFees[_i].amount,\\n _heldFees[_i].fee,\\n _heldFees[_i].feeDiscount\\n );\\n\\n // Process the fee.\\n _processFee(_amount, _heldFees[_i].beneficiary, _projectId);\\n\\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n\\n /**\\n @notice\\n Allows the fee to be updated.\\n\\n @dev\\n Only the owner of this contract can change the fee.\\n\\n @param _fee The new fee, out of MAX_FEE.\\n */\\n function setFee(uint256 _fee) external virtual override onlyOwner {\\n // The provided fee must be within the max.\\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\\n\\n // Store the new fee.\\n fee = _fee;\\n\\n emit SetFee(_fee, msg.sender);\\n }\\n\\n /**\\n @notice\\n Allows the fee gauge to be updated.\\n\\n @dev\\n Only the owner of this contract can change the fee gauge.\\n\\n @param _feeGauge The new fee gauge.\\n */\\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\\n // Store the new fee gauge.\\n feeGauge = _feeGauge;\\n\\n emit SetFeeGauge(_feeGauge, msg.sender);\\n }\\n\\n /**\\n @notice\\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\\n\\n @dev\\n Only the owner of this contract can set addresses as feeless.\\n\\n @param _address The address that can be paid towards while still bypassing fees.\\n @param _flag A flag indicating whether the terminal should be feeless or not.\\n */\\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\\n // Set the flag value.\\n isFeelessAddress[_address] = _flag;\\n\\n emit SetFeelessAddress(_address, _flag, msg.sender);\\n }\\n\\n //*********************************************************************//\\n // ----------------------- public transactions ----------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Receives funds belonging to the specified project.\\n\\n @param _projectId The ID of the project to which the funds received belong.\\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Extra data to pass along to the emitted event.\\n */\\n function addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n bool _shouldRefundHeldFees,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) public payable virtual override isTerminalOf(_projectId) {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\\n if (token != JBTokens.ETH) {\\n // Amount must be greater than 0.\\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\\n\\n // Get a reference to the balance before receiving tokens.\\n uint256 _balanceBefore = _balance();\\n\\n // Transfer tokens to this terminal from the msg sender.\\n _transferFrom(msg.sender, payable(address(this)), _amount);\\n\\n // The amount should reflect the change in balance.\\n _amount = _balance() - _balanceBefore;\\n }\\n // If the terminal's token is ETH, override `_amount` with msg.value.\\n else _amount = msg.value;\\n\\n // Add to balance.\\n _addToBalanceOf(_projectId, _amount, _shouldRefundHeldFees, _memo, _metadata);\\n }\\n\\n //*********************************************************************//\\n // ---------------------- internal transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Transfers tokens.\\n\\n @param _from The address from which the transfer should originate.\\n @param _to The address to which the transfer should go.\\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\\n */\\n function _transferFrom(\\n address _from,\\n address payable _to,\\n uint256 _amount\\n ) internal virtual {\\n _from; // Prevents unused var compiler and natspec complaints.\\n _to; // Prevents unused var compiler and natspec complaints.\\n _amount; // Prevents unused var compiler and natspec complaints.\\n }\\n\\n /** \\n @notice\\n Logic to be triggered before transferring tokens from this terminal.\\n\\n @param _to The address to which the transfer is going.\\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\\n */\\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\\n _to; // Prevents unused var compiler and natspec complaints.\\n _amount; // Prevents unused var compiler and natspec complaints.\\n }\\n\\n /** \\n @notice\\n Logic to be triggered if a transfer should be undone\\n\\n @param _to The address to which the transfer went.\\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\\n */\\n function _cancelTransferTo(address _to, uint256 _amount) internal virtual {\\n _to; // Prevents unused var compiler and natspec complaints.\\n _amount; // Prevents unused var compiler and natspec complaints.\\n }\\n\\n /**\\n @notice\\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\\n\\n @dev\\n Only a token holder or a designated operator can redeem its tokens.\\n\\n @param _holder The account to redeem tokens for.\\n @param _projectId The ID of the project to which the tokens being redeemed belong.\\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\\n @param _beneficiary The address to send the terminal tokens to.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\\n\\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\\n */\\n function _redeemTokensOf(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string memory _memo,\\n bytes memory _metadata\\n ) internal returns (uint256 reclaimAmount) {\\n // Can't send reclaimed funds to the zero address.\\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\\n\\n // Define variables that will be needed outside the scoped section below.\\n // Keep a reference to the funding cycle during which the redemption is being made.\\n JBFundingCycle memory _fundingCycle;\\n\\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\\n {\\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\\n\\n // Record the redemption.\\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\\n _holder,\\n _projectId,\\n _tokenCount,\\n _memo,\\n _metadata\\n );\\n\\n // The amount being reclaimed must be at least as much as was expected.\\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\\n\\n // Burn the project tokens.\\n if (_tokenCount > 0)\\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\\n _holder,\\n _projectId,\\n _tokenCount,\\n '',\\n false\\n );\\n\\n // If delegate allocations were specified by the data source, fulfill them.\\n if (_delegateAllocations.length != 0) {\\n // Keep a reference to the token amount being forwarded to the delegate.\\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\\n\\n JBDidRedeemData memory _data = JBDidRedeemData(\\n _holder,\\n _projectId,\\n _fundingCycle.configuration,\\n _tokenCount,\\n JBTokenAmount(token, reclaimAmount, decimals, currency),\\n _forwardedAmount,\\n _beneficiary,\\n _memo,\\n _metadata\\n );\\n\\n uint256 _numDelegates = _delegateAllocations.length;\\n\\n for (uint256 _i; _i < _numDelegates; ) {\\n // Get a reference to the delegate being iterated on.\\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\\n\\n // Trigger any inherited pre-transfer logic.\\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\\n\\n // Keep track of the msg.value to use in the delegate call\\n uint256 _payableValue;\\n\\n // If this terminal's token is ETH, send it in msg.value.\\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\\n\\n // Pass the correct token forwardedAmount to the delegate\\n _data.forwardedAmount.value = _delegateAllocation.amount;\\n\\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\\n\\n emit DelegateDidRedeem(\\n _delegateAllocation.delegate,\\n _data,\\n _delegateAllocation.amount,\\n msg.sender\\n );\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n }\\n\\n // Send the reclaimed funds to the beneficiary.\\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\\n\\n emit RedeemTokens(\\n _fundingCycle.configuration,\\n _fundingCycle.number,\\n _projectId,\\n _holder,\\n _beneficiary,\\n _tokenCount,\\n reclaimAmount,\\n _memo,\\n _metadata,\\n msg.sender\\n );\\n }\\n\\n /**\\n @notice\\n Distributes payouts for a project with the distribution limit of its current funding cycle.\\n\\n @dev\\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\\n\\n @dev\\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\\n\\n @dev\\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\\n\\n @param _projectId The ID of the project having its payouts distributed.\\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\\n @param _metadata Bytes to send along to the emitted event, if provided.\\n\\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\\n */\\n function _distributePayoutsOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n uint256 _minReturnedTokens,\\n bytes calldata _metadata\\n ) internal returns (uint256 netLeftoverDistributionAmount) {\\n // Record the distribution.\\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\\n _projectId,\\n _amount,\\n _currency\\n );\\n\\n // The amount being distributed must be at least as much as was expected.\\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\\n\\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\\n // and receive any extra distributable funds not allocated to payout splits.\\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\\n\\n // Define variables that will be needed outside the scoped section below.\\n // Keep a reference to the fee amount that was paid.\\n uint256 _fee;\\n\\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\\n {\\n // Get the amount of discount that should be applied to any fees taken.\\n // If the fee is zero, set the discount to 100% for convenience.\\n uint256 _feeDiscount = fee == 0\\n ? JBConstants.MAX_FEE_DISCOUNT\\n : _currentFeeDiscount(_projectId);\\n\\n // The amount distributed that is eligible for incurring fees.\\n uint256 _feeEligibleDistributionAmount;\\n\\n // The amount leftover after distributing to the splits.\\n uint256 _leftoverDistributionAmount;\\n\\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\\n _projectId,\\n _fundingCycle.configuration,\\n payoutSplitsGroup,\\n _distributedAmount,\\n _feeDiscount\\n );\\n\\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\\n unchecked {\\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\\n }\\n }\\n\\n // Take the fee.\\n _fee = _feeEligibleDistributionAmount != 0\\n ? _takeFeeFrom(\\n _projectId,\\n _fundingCycle,\\n _feeEligibleDistributionAmount,\\n _projectOwner,\\n _feeDiscount\\n )\\n : 0;\\n\\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\\n if (_leftoverDistributionAmount != 0) {\\n // Subtract the fee from the net leftover amount.\\n netLeftoverDistributionAmount =\\n _leftoverDistributionAmount -\\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\\n\\n // Transfer the amount to the project owner.\\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\\n }\\n }\\n\\n emit DistributePayouts(\\n _fundingCycle.configuration,\\n _fundingCycle.number,\\n _projectId,\\n _projectOwner,\\n _amount,\\n _distributedAmount,\\n _fee,\\n netLeftoverDistributionAmount,\\n _metadata,\\n msg.sender\\n );\\n }\\n\\n /**\\n @notice\\n Allows a project to send funds from its overflow up to the preconfigured allowance.\\n\\n @dev\\n Only a project's owner or a designated operator can use its allowance.\\n\\n @dev\\n Incurs the protocol fee.\\n\\n @param _projectId The ID of the project to use the allowance of.\\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\\n @param _beneficiary The address to send the funds to.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Bytes to send along to the emitted event, if provided.\\n\\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\\n */\\n function _useAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string memory _memo,\\n bytes calldata _metadata\\n ) internal returns (uint256 netDistributedAmount) {\\n // Record the use of the allowance.\\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\\n _projectId,\\n _amount,\\n _currency\\n );\\n\\n // The amount being withdrawn must be at least as much as was expected.\\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\\n\\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\\n {\\n // Keep a reference to the fee amount that was paid.\\n uint256 _fee;\\n\\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\\n address _projectOwner = projects.ownerOf(_projectId);\\n\\n // Get the amount of discount that should be applied to any fees taken.\\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\\n ? JBConstants.MAX_FEE_DISCOUNT\\n : _currentFeeDiscount(_projectId);\\n\\n // Take a fee from the `_distributedAmount`, if needed.\\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\\n ? 0\\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\\n\\n unchecked {\\n // The net amount is the withdrawn amount without the fee.\\n netDistributedAmount = _distributedAmount - _fee;\\n }\\n\\n // Transfer any remaining balance to the beneficiary.\\n if (netDistributedAmount > 0)\\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\\n }\\n\\n emit UseAllowance(\\n _fundingCycle.configuration,\\n _fundingCycle.number,\\n _projectId,\\n _beneficiary,\\n _amount,\\n _distributedAmount,\\n netDistributedAmount,\\n _memo,\\n _metadata,\\n msg.sender\\n );\\n }\\n\\n /**\\n @notice\\n Pays out splits for a project's funding cycle configuration.\\n\\n @param _projectId The ID of the project for which payout splits are being distributed.\\n @param _domain The domain of the splits to distribute the payout between.\\n @param _group The group of the splits to distribute the payout between.\\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\\n\\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\\n */\\n function _distributeToPayoutSplitsOf(\\n uint256 _projectId,\\n uint256 _domain,\\n uint256 _group,\\n uint256 _amount,\\n uint256 _feeDiscount\\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\\n // Set the leftover amount to the initial amount.\\n leftoverAmount = _amount;\\n // The total percentage available to split\\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\\n\\n // Get a reference to the project's payout splits.\\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\\n\\n // Transfer between all splits.\\n for (uint256 _i; _i < _splits.length; ) {\\n // Get a reference to the split being iterated on.\\n JBSplit memory _split = _splits[_i];\\n\\n // The amount to send towards the split.\\n uint256 _payoutAmount = _split.percent == leftoverPercentage\\n ? leftoverAmount\\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\\n\\n // Decrement the leftover percentage.\\n leftoverPercentage -= _split.percent;\\n\\n // The payout amount substracting any applicable incurred fees.\\n uint256 _netPayoutAmount = _distributeToPayoutSplit(\\n _split,\\n _projectId,\\n _group,\\n _payoutAmount,\\n _feeDiscount\\n );\\n\\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\\n if (_netPayoutAmount != 0 && _netPayoutAmount != _payoutAmount)\\n feeEligibleDistributionAmount += _payoutAmount;\\n\\n if (_payoutAmount > 0) {\\n // Subtract from the amount to be sent to the beneficiary.\\n unchecked {\\n leftoverAmount = leftoverAmount - _payoutAmount;\\n }\\n }\\n\\n emit DistributeToPayoutSplit(\\n _projectId,\\n _domain,\\n _group,\\n _split,\\n _payoutAmount,\\n _netPayoutAmount,\\n msg.sender\\n );\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n\\n /**\\n @notice\\n Pays out a split for a project's funding cycle configuration.\\n \\n @param _split The split to distribute payouts to.\\n @param _amount The total amount being distributed to the split, as a fixed point number with the same number of decimals as this terminal.\\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\\n\\n @return netPayoutAmount The amount sent to the split after subtracting fees.\\n */\\n function _distributeToPayoutSplit(\\n JBSplit memory _split,\\n uint256 _projectId,\\n uint256 _group,\\n uint256 _amount,\\n uint256 _feeDiscount\\n ) internal returns (uint256 netPayoutAmount) {\\n // If there's an allocator set, transfer to its `allocate` function.\\n if (_split.allocator != IJBSplitAllocator(address(0))) {\\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\\n if (\\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_split.allocator)]\\n )\\n netPayoutAmount = _amount;\\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\\n else {\\n unchecked {\\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\\n }\\n }\\n\\n // Trigger any inherited pre-transfer logic.\\n _beforeTransferTo(address(_split.allocator), netPayoutAmount);\\n\\n // Create the data to send to the allocator.\\n JBSplitAllocationData memory _data = JBSplitAllocationData(\\n token,\\n netPayoutAmount,\\n decimals,\\n _projectId,\\n _group,\\n _split\\n );\\n\\n // Trigger the allocator's `allocate` function.\\n uint256 _error;\\n bytes memory _reason;\\n\\n if (\\n ERC165Checker.supportsInterface(\\n address(_split.allocator),\\n type(IJBSplitAllocator).interfaceId\\n )\\n )\\n // If this terminal's token is ETH, send it in msg.value.\\n try _split.allocator.allocate{value: token == JBTokens.ETH ? netPayoutAmount : 0}(_data) {\\n\\n } catch (bytes memory reason) {\\n _reason = reason;\\n _error = 1;\\n }\\n else _error = 2;\\n\\n\\n if (_error != 0) {\\n // Trigger any inhereted post-transfer cancelation logic.\\n _cancelTransferTo(address(_split.allocator), netPayoutAmount);\\n\\n // Set the net payout amount to 0 to signal the reversion.\\n netPayoutAmount = 0;\\n\\n // Add undistributed amount back to project's balance.\\n store.recordAddedBalanceFor(_projectId, _amount);\\n\\n emit PayoutReverted(_projectId, _split, _amount, _error == 1 ? _reason : abi.encode(\\\"IERC165 fail\\\"), msg.sender);\\n }\\n\\n // Otherwise, if a project is specified, make a payment to it.\\n } else if (_split.projectId != 0) {\\n // Get a reference to the Juicebox terminal being used.\\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\\n\\n // The project must have a terminal to send funds to.\\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\\n\\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\\n if (\\n _terminal == this ||\\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\\n isFeelessAddress[address(_terminal)]\\n )\\n netPayoutAmount = _amount;\\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\\n else {\\n unchecked {\\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\\n }\\n }\\n\\n // Trigger any inherited pre-transfer logic.\\n _beforeTransferTo(address(_terminal), netPayoutAmount);\\n\\n // Send the projectId in the metadata.\\n bytes memory _projectMetadata = new bytes(32);\\n _projectMetadata = bytes(abi.encodePacked(_projectId));\\n\\n // Add to balance if prefered.\\n if (_split.preferAddToBalance)\\n try\\n _terminal.addToBalanceOf{value: token == JBTokens.ETH ? netPayoutAmount : 0}(\\n _split.projectId,\\n netPayoutAmount,\\n token,\\n '',\\n _projectMetadata\\n )\\n {} catch (bytes memory reason) {\\n // Trigger any inhereted post-transfer cancelation logic.\\n _cancelTransferTo(address(_terminal), netPayoutAmount);\\n\\n // Set the net payout amount to 0 to signal the reversion.\\n netPayoutAmount = 0;\\n\\n // Add undistributed amount back to project's balance.\\n store.recordAddedBalanceFor(_projectId, _amount);\\n\\n emit PayoutReverted(_projectId, _split, _amount, reason, msg.sender);\\n }\\n else\\n try\\n _terminal.pay{value: token == JBTokens.ETH ? netPayoutAmount : 0}(\\n _split.projectId,\\n netPayoutAmount,\\n token,\\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\\n 0,\\n _split.preferClaimed,\\n '',\\n _projectMetadata\\n )\\n {} catch (bytes memory reason) {\\n // Trigger any inhereted post-transfer cancelation logic.\\n _cancelTransferTo(address(_terminal), netPayoutAmount);\\n\\n // Set the net payout amount to 0 to signal the reversion.\\n netPayoutAmount = 0;\\n\\n // Add undistributed amount back to project's balance.\\n store.recordAddedBalanceFor(_projectId, _amount);\\n\\n emit PayoutReverted(_projectId, _split, _amount, reason, msg.sender);\\n }\\n } else {\\n // Keep a reference to the beneficiary.\\n address payable _beneficiary = _split.beneficiary != address(0)\\n ? _split.beneficiary\\n : payable(msg.sender);\\n\\n // If there's a full discount, this distribution is not eligible for a fee.\\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\\n netPayoutAmount = _amount;\\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\\n else {\\n unchecked {\\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\\n }\\n }\\n\\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\\n _transferFrom(address(this), _beneficiary, netPayoutAmount);\\n }\\n }\\n\\n /**\\n @notice\\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\\n\\n @param _projectId The ID of the project having fees taken from.\\n @param _fundingCycle The funding cycle during which the fee is being taken.\\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\\n @param _beneficiary The address to mint the platforms tokens for.\\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\\n\\n @return feeAmount The amount of the fee taken.\\n */\\n function _takeFeeFrom(\\n uint256 _projectId,\\n JBFundingCycle memory _fundingCycle,\\n uint256 _amount,\\n address _beneficiary,\\n uint256 _feeDiscount\\n ) internal returns (uint256 feeAmount) {\\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\\n\\n if (_fundingCycle.shouldHoldFees()) {\\n // Store the held fee.\\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\\n\\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\\n } else {\\n // Process the fee.\\n _processFee(feeAmount, _beneficiary, _projectId); // Take the fee.\\n\\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\\n }\\n }\\n\\n /**\\n @notice\\n Process a fee of the specified amount.\\n\\n @param _amount The fee amount, as a floating point number with 18 decimals.\\n @param _beneficiary The address to mint the platform's tokens for.\\n @param _from The project ID the fee is being paid from.\\n */\\n function _processFee(\\n uint256 _amount,\\n address _beneficiary,\\n uint256 _from\\n ) internal {\\n // Get the terminal for the protocol project.\\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\\n\\n // If this terminal's token is ETH, send it in msg.value.\\n uint256 _payableValue = token == JBTokens.ETH ? _amount : 0;\\n\\n // Send the projectId in the metadata.\\n bytes memory _projectMetadata = new bytes(32);\\n _projectMetadata = bytes(abi.encodePacked(_from));\\n\\n // Trigger any inherited pre-transfer logic if funds will be transferred.\\n if (address(_terminal) != address(this)) _beforeTransferTo(address(_terminal), _amount);\\n\\n try\\n // Send the fee.\\n _terminal.pay{value: _payableValue}(\\n _FEE_BENEFICIARY_PROJECT_ID,\\n _amount,\\n token,\\n _beneficiary,\\n 0,\\n false,\\n '',\\n _projectMetadata\\n )\\n {} catch (bytes memory reason) {\\n // Trigger any inhereted post-transfer cancelation logic if the pre-transfer logic was triggered.\\n if (address(_terminal) != address(this)) _cancelTransferTo(address(_terminal), _amount);\\n\\n // Add fee amount back to project's balance.\\n store.recordAddedBalanceFor(_from, _amount);\\n\\n emit FeeReverted(_from, _FEE_BENEFICIARY_PROJECT_ID, _amount, reason, msg.sender);\\n }\\n }\\n\\n /**\\n @notice\\n Contribute tokens to a project.\\n\\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\\n @param _payer The address making the payment.\\n @param _projectId The ID of the project being paid.\\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\\n\\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\\n */\\n function _pay(\\n uint256 _amount,\\n address _payer,\\n uint256 _projectId,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string memory _memo,\\n bytes memory _metadata\\n ) internal returns (uint256 beneficiaryTokenCount) {\\n // Cant send tokens to the zero address.\\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\\n\\n // Define variables that will be needed outside the scoped section below.\\n // Keep a reference to the funding cycle during which the payment is being made.\\n JBFundingCycle memory _fundingCycle;\\n\\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\\n {\\n JBPayDelegateAllocation[] memory _delegateAllocations;\\n uint256 _tokenCount;\\n\\n // Bundle the amount info into a JBTokenAmount struct.\\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\\n\\n // Record the payment.\\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\\n _payer,\\n _bundledAmount,\\n _projectId,\\n baseWeightCurrency,\\n _beneficiary,\\n _memo,\\n _metadata\\n );\\n\\n // Mint the tokens if needed.\\n if (_tokenCount > 0)\\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\\n _projectId,\\n _tokenCount,\\n _beneficiary,\\n '',\\n _preferClaimedTokens,\\n true\\n );\\n\\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\\n\\n // If delegate allocations were specified by the data source, fulfill them.\\n if (_delegateAllocations.length != 0) {\\n // Keep a reference to the token amount being forwarded to the delegate.\\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\\n\\n JBDidPayData memory _data = JBDidPayData(\\n _payer,\\n _projectId,\\n _fundingCycle.configuration,\\n _bundledAmount,\\n _forwardedAmount,\\n beneficiaryTokenCount,\\n _beneficiary,\\n _preferClaimedTokens,\\n _memo,\\n _metadata\\n );\\n\\n // Get a reference to the number of delegates to allocate to.\\n uint256 _numDelegates = _delegateAllocations.length;\\n\\n for (uint256 _i; _i < _numDelegates; ) {\\n // Get a reference to the delegate being iterated on.\\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\\n\\n // Trigger any inherited pre-transfer logic.\\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\\n\\n // Keep track of the msg.value to use in the delegate call\\n uint256 _payableValue;\\n\\n // If this terminal's token is ETH, send it in msg.value.\\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\\n\\n // Pass the correct token forwardedAmount to the delegate\\n _data.forwardedAmount.value = _delegateAllocation.amount;\\n\\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\\n\\n emit DelegateDidPay(\\n _delegateAllocation.delegate,\\n _data,\\n _delegateAllocation.amount,\\n msg.sender\\n );\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n }\\n\\n emit Pay(\\n _fundingCycle.configuration,\\n _fundingCycle.number,\\n _projectId,\\n _payer,\\n _beneficiary,\\n _amount,\\n beneficiaryTokenCount,\\n _memo,\\n _metadata,\\n msg.sender\\n );\\n }\\n\\n /**\\n @notice\\n Receives funds belonging to the specified project.\\n\\n @param _projectId The ID of the project to which the funds received belong.\\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Extra data to pass along to the emitted event.\\n */\\n function _addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n bool _shouldRefundHeldFees,\\n string memory _memo,\\n bytes memory _metadata\\n ) internal {\\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\\n\\n // Record the added funds with any refunded fees.\\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\\n\\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\\n }\\n\\n /**\\n @notice\\n Refund fees based on the specified amount.\\n\\n @param _projectId The project for which fees are being refunded.\\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\\n\\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\\n */\\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\\n internal\\n returns (uint256 refundedFees)\\n {\\n // Get a reference to the project's held fees.\\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\\n\\n // Delete the current held fees.\\n delete _heldFeesOf[_projectId];\\n\\n // Get a reference to the leftover amount once all fees have been settled.\\n uint256 leftoverAmount = _amount;\\n\\n // Push length in stack\\n uint256 _heldFeesLength = _heldFees.length;\\n\\n // Process each fee.\\n for (uint256 _i; _i < _heldFeesLength; ) {\\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\\n else if (leftoverAmount >= _heldFees[_i].amount) {\\n unchecked {\\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\\n refundedFees += _feeAmount(\\n _heldFees[_i].amount,\\n _heldFees[_i].fee,\\n _heldFees[_i].feeDiscount\\n );\\n }\\n } else {\\n unchecked {\\n _heldFeesOf[_projectId].push(\\n JBFee(\\n _heldFees[_i].amount - leftoverAmount,\\n _heldFees[_i].fee,\\n _heldFees[_i].feeDiscount,\\n _heldFees[_i].beneficiary\\n )\\n );\\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\\n }\\n leftoverAmount = 0;\\n }\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n\\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\\n }\\n\\n /** \\n @notice \\n Returns the fee amount based on the provided amount for the specified project.\\n\\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\\n @param _fee The percentage of the fee, out of MAX_FEE. \\n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\\n\\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\\n */\\n function _feeAmount(\\n uint256 _amount,\\n uint256 _fee,\\n uint256 _feeDiscount\\n ) internal pure returns (uint256) {\\n // Calculate the discounted fee.\\n uint256 _discountedFee = _fee -\\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\\n\\n // The amount of tokens from the `_amount` to pay as a fee.\\n return\\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\\n }\\n\\n /** \\n @notice\\n Get the fee discount from the fee gauge for the specified project.\\n\\n @param _projectId The ID of the project to get a fee discount for.\\n \\n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\\n */\\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\\n if (\\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\\n IJBPaymentTerminal(address(0))\\n ) return JBConstants.MAX_FEE_DISCOUNT;\\n\\n // Get the fee discount.\\n if (feeGauge != IJBFeeGauge(address(0)))\\n // If the guage reverts, keep the discount at 0.\\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\\n // If the fee discount is greater than the max, we ignore the return value\\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\\n } catch {\\n return 0;\\n }\\n\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0x1af3116bfcffd711bd25c79f41f389a1a163716420d22869c072e83e4be60c68\",\"license\":\"MIT\"},\"contracts/abstract/JBSingleTokenPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\\nimport './../interfaces/IJBSingleTokenPaymentTerminal.sol';\\n\\n/**\\n @notice\\n Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\\n\\n @dev\\n Adheres to -\\n IJBSingleTokenPaymentTerminals: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n\\n @dev\\n Inherits from -\\n ERC165: Introspection on interface adherance. \\n*/\\nabstract contract JBSingleTokenPaymentTerminal is ERC165, IJBSingleTokenPaymentTerminal {\\n //*********************************************************************//\\n // ---------------- public immutable stored properties --------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The token that this terminal accepts.\\n */\\n address public immutable override token;\\n\\n /**\\n @notice\\n The number of decimals the token fixed point amounts are expected to have.\\n */\\n uint256 public immutable override decimals;\\n\\n /**\\n @notice\\n The currency to use when resolving price feeds for this terminal.\\n */\\n uint256 public immutable override currency;\\n\\n //*********************************************************************//\\n // ------------------------- external views -------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n A flag indicating if this terminal accepts the specified token.\\n\\n @param _token The token to check if this terminal accepts or not.\\n @param _projectId The project ID to check for token acceptance.\\n\\n @return The flag.\\n */\\n function acceptsToken(address _token, uint256 _projectId) external view override returns (bool) {\\n _projectId; // Prevents unused var compiler and natspec complaints.\\n\\n return _token == token;\\n }\\n\\n /** \\n @notice\\n The decimals that should be used in fixed number accounting for the specified token.\\n\\n @param _token The token to check for the decimals of.\\n\\n @return The number of decimals for the token.\\n */\\n function decimalsForToken(address _token) external view override returns (uint256) {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n return decimals;\\n }\\n\\n /** \\n @notice\\n The currency that should be used for the specified token.\\n\\n @param _token The token to check for the currency of.\\n\\n @return The currency index.\\n */\\n function currencyForToken(address _token) external view override returns (uint256) {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n return currency;\\n }\\n\\n //*********************************************************************//\\n // -------------------------- public views --------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Indicates if this contract adheres to the specified interface.\\n\\n @dev \\n See {IERC165-supportsInterface}.\\n\\n @param _interfaceId The ID of the interface to check for adherance to.\\n */\\n function supportsInterface(bytes4 _interfaceId)\\n public\\n view\\n virtual\\n override(ERC165, IERC165)\\n returns (bool)\\n {\\n return\\n _interfaceId == type(IJBPaymentTerminal).interfaceId ||\\n _interfaceId == type(IJBSingleTokenPaymentTerminal).interfaceId ||\\n super.supportsInterface(_interfaceId);\\n }\\n\\n //*********************************************************************//\\n // -------------------------- constructor ---------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @param _token The token that this terminal manages.\\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\\n @param _currency The currency that this terminal's token adheres to for price feeds.\\n */\\n constructor(\\n address _token,\\n uint256 _decimals,\\n uint256 _currency\\n ) {\\n token = _token;\\n decimals = _decimals;\\n currency = _currency;\\n }\\n}\\n\",\"keccak256\":\"0xdc82ad3e01b918d3d21ffea8c9f30950d81e225137c851599d028dcd22125f89\",\"license\":\"MIT\"},\"contracts/enums/JBBallotState.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nenum JBBallotState {\\n Active,\\n Approved,\\n Failed\\n}\\n\",\"keccak256\":\"0x891fcac63470398b3a11239da7feba6b07d640809fcefd2404303b823d7378f8\",\"license\":\"MIT\"},\"contracts/interfaces/IJBAllowanceTerminal3_1.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBAllowanceTerminal3_1 {\\n function useAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n address _token,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external returns (uint256 netDistributedAmount);\\n}\\n\",\"keccak256\":\"0x4e1ef83fc258e44f7880005b7944e3b4799d87129b2300236d93269a00adb4ee\",\"license\":\"MIT\"},\"contracts/interfaces/IJBController.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBFundAccessConstraints.sol';\\nimport './../structs/JBFundingCycleData.sol';\\nimport './../structs/JBFundingCycleMetadata.sol';\\nimport './../structs/JBGroupedSplits.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBMigratable.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBSplitsStore.sol';\\nimport './IJBTokenStore.sol';\\n\\ninterface IJBController is IERC165 {\\n event LaunchProject(uint256 configuration, uint256 projectId, string memo, address caller);\\n\\n event LaunchFundingCycles(uint256 configuration, uint256 projectId, string memo, address caller);\\n\\n event ReconfigureFundingCycles(\\n uint256 configuration,\\n uint256 projectId,\\n string memo,\\n address caller\\n );\\n\\n event SetFundAccessConstraints(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n JBFundAccessConstraints constraints,\\n address caller\\n );\\n\\n event DistributeReservedTokens(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address beneficiary,\\n uint256 tokenCount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n address caller\\n );\\n\\n event DistributeToReservedTokenSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n uint256 tokenCount,\\n address caller\\n );\\n\\n event MintTokens(\\n address indexed beneficiary,\\n uint256 indexed projectId,\\n uint256 tokenCount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n uint256 reservedRate,\\n address caller\\n );\\n\\n event BurnTokens(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 tokenCount,\\n string memo,\\n address caller\\n );\\n\\n event Migrate(uint256 indexed projectId, IJBMigratable to, address caller);\\n\\n event PrepMigration(uint256 indexed projectId, address from, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function tokenStore() external view returns (IJBTokenStore);\\n\\n function splitsStore() external view returns (IJBSplitsStore);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function reservedTokenBalanceOf(uint256 _projectId, uint256 _reservedRate)\\n external\\n view\\n returns (uint256);\\n\\n function distributionLimitOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n IJBPaymentTerminal _terminal,\\n address _token\\n ) external view returns (uint256 distributionLimit, uint256 distributionLimitCurrency);\\n\\n function overflowAllowanceOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n IJBPaymentTerminal _terminal,\\n address _token\\n ) external view returns (uint256 overflowAllowance, uint256 overflowAllowanceCurrency);\\n\\n function totalOutstandingTokensOf(uint256 _projectId, uint256 _reservedRate)\\n external\\n view\\n returns (uint256);\\n\\n function getFundingCycleOf(uint256 _projectId, uint256 _configuration)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function latestConfiguredFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (\\n JBFundingCycle memory,\\n JBFundingCycleMetadata memory metadata,\\n JBBallotState\\n );\\n\\n function currentFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function queuedFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function launchProjectFor(\\n address _owner,\\n JBProjectMetadata calldata _projectMetadata,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n IJBPaymentTerminal[] memory _terminals,\\n string calldata _memo\\n ) external returns (uint256 projectId);\\n\\n function launchFundingCyclesFor(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n IJBPaymentTerminal[] memory _terminals,\\n string calldata _memo\\n ) external returns (uint256 configuration);\\n\\n function reconfigureFundingCyclesOf(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n string calldata _memo\\n ) external returns (uint256);\\n\\n function mintTokensOf(\\n uint256 _projectId,\\n uint256 _tokenCount,\\n address _beneficiary,\\n string calldata _memo,\\n bool _preferClaimedTokens,\\n bool _useReservedRate\\n ) external returns (uint256 beneficiaryTokenCount);\\n\\n function burnTokensOf(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n string calldata _memo,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function distributeReservedTokensOf(uint256 _projectId, string memory _memo)\\n external\\n returns (uint256);\\n\\n function migrate(uint256 _projectId, IJBMigratable _to) external;\\n}\\n\",\"keccak256\":\"0xb1ee4b41f2a06f28f69c74cb729b8964f2e75f3c545a68f85bd9082b5575bc85\",\"license\":\"MIT\"},\"contracts/interfaces/IJBDirectory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBProjects.sol';\\n\\ninterface IJBDirectory {\\n event SetController(uint256 indexed projectId, address indexed controller, address caller);\\n\\n event AddTerminal(uint256 indexed projectId, IJBPaymentTerminal indexed terminal, address caller);\\n\\n event SetTerminals(uint256 indexed projectId, IJBPaymentTerminal[] terminals, address caller);\\n\\n event SetPrimaryTerminal(\\n uint256 indexed projectId,\\n address indexed token,\\n IJBPaymentTerminal indexed terminal,\\n address caller\\n );\\n\\n event SetIsAllowedToSetFirstController(address indexed addr, bool indexed flag, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function controllerOf(uint256 _projectId) external view returns (address);\\n\\n function isAllowedToSetFirstController(address _address) external view returns (bool);\\n\\n function terminalsOf(uint256 _projectId) external view returns (IJBPaymentTerminal[] memory);\\n\\n function isTerminalOf(uint256 _projectId, IJBPaymentTerminal _terminal)\\n external\\n view\\n returns (bool);\\n\\n function primaryTerminalOf(uint256 _projectId, address _token)\\n external\\n view\\n returns (IJBPaymentTerminal);\\n\\n function setControllerOf(uint256 _projectId, address _controller) external;\\n\\n function setTerminalsOf(uint256 _projectId, IJBPaymentTerminal[] calldata _terminals) external;\\n\\n function setPrimaryTerminalOf(\\n uint256 _projectId,\\n address _token,\\n IJBPaymentTerminal _terminal\\n ) external;\\n\\n function setIsAllowedToSetFirstController(address _address, bool _flag) external;\\n}\\n\",\"keccak256\":\"0x715321646db00514d1355ed43c40cd3f01e94959552fd07797b315d9c49cdb1d\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFeeGauge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBFeeGauge {\\n function currentDiscountFor(uint256 _projectId) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x8e19959617191320fe1210760860e668a57319258c0c74fcfabac829ae0222c0\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFeeHoldingTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBFeeHoldingTerminal {\\n function addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n bool _shouldRefundHeldFees,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable;\\n}\\n\",\"keccak256\":\"0x8c9edae0768a737097835b8b9ef4a60f000de122a867c90f20cfc653287541a4\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleBallot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../enums/JBBallotState.sol';\\n\\ninterface IJBFundingCycleBallot is IERC165 {\\n function duration() external view returns (uint256);\\n\\n function stateOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n uint256 _start\\n ) external view returns (JBBallotState);\\n}\\n\",\"keccak256\":\"0x49553a56209237846bc400cf27f260824a6bd06fd8094a7eb5abb9de75779598\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../enums/JBBallotState.sol';\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBFundingCycleData.sol';\\n\\ninterface IJBFundingCycleStore {\\n event Configure(\\n uint256 indexed configuration,\\n uint256 indexed projectId,\\n JBFundingCycleData data,\\n uint256 metadata,\\n uint256 mustStartAtOrAfter,\\n address caller\\n );\\n\\n event Init(uint256 indexed configuration, uint256 indexed projectId, uint256 indexed basedOn);\\n\\n function latestConfigurationOf(uint256 _projectId) external view returns (uint256);\\n\\n function get(uint256 _projectId, uint256 _configuration)\\n external\\n view\\n returns (JBFundingCycle memory);\\n\\n function latestConfiguredOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBBallotState ballotState);\\n\\n function queuedOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentBallotStateOf(uint256 _projectId) external view returns (JBBallotState);\\n\\n function configureFor(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n uint256 _metadata,\\n uint256 _mustStartAtOrAfter\\n ) external returns (JBFundingCycle memory fundingCycle);\\n}\\n\",\"keccak256\":\"0xaead823851433be0c2ddc8f8086813e6cd647de3a1bc0f7570a5d6b38c378b5a\",\"license\":\"MIT\"},\"contracts/interfaces/IJBMigratable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBMigratable {\\n function prepForMigrationOf(uint256 _projectId, address _from) external;\\n}\\n\",\"keccak256\":\"0xc81053e4b4754fc510aa04fecd3ab1460f01e3e27761e7a8c94f631a978ae127\",\"license\":\"MIT\"},\"contracts/interfaces/IJBOperatable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBOperatorStore.sol';\\n\\ninterface IJBOperatable {\\n function operatorStore() external view returns (IJBOperatorStore);\\n}\\n\",\"keccak256\":\"0x09a55a91c6ce3625379334271d236cfa47bf36522a91568b406bf06f7239407e\",\"license\":\"MIT\"},\"contracts/interfaces/IJBOperatorStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBOperatorData.sol';\\n\\ninterface IJBOperatorStore {\\n event SetOperator(\\n address indexed operator,\\n address indexed account,\\n uint256 indexed domain,\\n uint256[] permissionIndexes,\\n uint256 packed\\n );\\n\\n function permissionsOf(\\n address _operator,\\n address _account,\\n uint256 _domain\\n ) external view returns (uint256);\\n\\n function hasPermission(\\n address _operator,\\n address _account,\\n uint256 _domain,\\n uint256 _permissionIndex\\n ) external view returns (bool);\\n\\n function hasPermissions(\\n address _operator,\\n address _account,\\n uint256 _domain,\\n uint256[] calldata _permissionIndexes\\n ) external view returns (bool);\\n\\n function setOperator(JBOperatorData calldata _operatorData) external;\\n\\n function setOperators(JBOperatorData[] calldata _operatorData) external;\\n}\\n\",\"keccak256\":\"0x17f4929812a356984795fafed8cb2be816a025c9a0771d85595ac0b5ff3cffc5\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPayDelegate.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBDidPayData.sol';\\n\\n/**\\n @title\\n Pay delegate\\n\\n @notice\\n Delegate called after JBTerminal.pay(..) logic completion (if passed by the funding cycle datasource)\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n*/\\ninterface IJBPayDelegate is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.pay(..), after the execution of its logic\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control\\n \\n @param _data the data passed by the terminal, as a JBDidPayData struct:\\n address payer;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n JBTokenAmount amount;\\n JBTokenAmount forwardedAmount;\\n uint256 projectTokenCount;\\n address beneficiary;\\n bool preferClaimedTokens;\\n string memo;\\n bytes metadata;\\n */\\n function didPay(JBDidPayData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0xa797de18b69eceba117e1f0b3810cf3cc2d2791417d580a5bdc510d1b868ab26\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\n\\ninterface IJBPaymentTerminal is IERC165 {\\n function acceptsToken(address _token, uint256 _projectId) external view returns (bool);\\n\\n function currencyForToken(address _token) external view returns (uint256);\\n\\n function decimalsForToken(address _token) external view returns (uint256);\\n\\n // Return value must be a fixed point number with 18 decimals.\\n function currentEthOverflowOf(uint256 _projectId) external view returns (uint256);\\n\\n function pay(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable returns (uint256 beneficiaryTokenCount);\\n\\n function addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable;\\n}\\n\",\"keccak256\":\"0xb7826f5ed609359ce322c09e83236c47ba385df1c3cad3607e56fd0a2e00eee2\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPayoutRedemptionPaymentTerminal3_1.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBFee.sol';\\nimport './IJBAllowanceTerminal3_1.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFeeGauge.sol';\\nimport './IJBFeeHoldingTerminal.sol';\\nimport './IJBPayDelegate.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBPayoutTerminal3_1.sol';\\nimport './IJBPrices.sol';\\nimport './IJBProjects.sol';\\nimport './IJBRedemptionDelegate.sol';\\nimport './IJBRedemptionTerminal.sol';\\nimport './IJBSingleTokenPaymentTerminalStore.sol';\\nimport './IJBSplitsStore.sol';\\n\\ninterface IJBPayoutRedemptionPaymentTerminal3_1 is\\n IJBPaymentTerminal,\\n IJBPayoutTerminal3_1,\\n IJBAllowanceTerminal3_1,\\n IJBRedemptionTerminal,\\n IJBFeeHoldingTerminal\\n{\\n event AddToBalance(\\n uint256 indexed projectId,\\n uint256 amount,\\n uint256 refundedFees,\\n string memo,\\n bytes metadata,\\n address caller\\n );\\n\\n event Migrate(\\n uint256 indexed projectId,\\n IJBPaymentTerminal indexed to,\\n uint256 amount,\\n address caller\\n );\\n\\n event DistributePayouts(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address beneficiary,\\n uint256 amount,\\n uint256 distributedAmount,\\n uint256 fee,\\n uint256 beneficiaryDistributionAmount,\\n bytes metadata,\\n address caller\\n );\\n\\n event UseAllowance(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address beneficiary,\\n uint256 amount,\\n uint256 distributedAmount,\\n uint256 netDistributedamount,\\n string memo,\\n bytes metadata,\\n address caller\\n );\\n\\n event HoldFee(\\n uint256 indexed projectId,\\n uint256 indexed amount,\\n uint256 indexed fee,\\n uint256 feeDiscount,\\n address beneficiary,\\n address caller\\n );\\n\\n event ProcessFee(\\n uint256 indexed projectId,\\n uint256 indexed amount,\\n bool indexed wasHeld,\\n address beneficiary,\\n address caller\\n );\\n\\n event RefundHeldFees(\\n uint256 indexed projectId,\\n uint256 indexed amount,\\n uint256 indexed refundedFees,\\n uint256 leftoverAmount,\\n address caller\\n );\\n\\n event Pay(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address payer,\\n address beneficiary,\\n uint256 amount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n bytes metadata,\\n address caller\\n );\\n\\n event DelegateDidPay(\\n IJBPayDelegate indexed delegate,\\n JBDidPayData data,\\n uint256 delegatedAmount,\\n address caller\\n );\\n\\n event RedeemTokens(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address holder,\\n address beneficiary,\\n uint256 tokenCount,\\n uint256 reclaimedAmount,\\n string memo,\\n bytes metadata,\\n address caller\\n );\\n\\n event DelegateDidRedeem(\\n IJBRedemptionDelegate indexed delegate,\\n JBDidRedeemData data,\\n uint256 delegatedAmount,\\n address caller\\n );\\n\\n event DistributeToPayoutSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n uint256 amount,\\n uint256 netAmount,\\n address caller\\n );\\n\\n event SetFee(uint256 fee, address caller);\\n\\n event SetFeeGauge(IJBFeeGauge indexed feeGauge, address caller);\\n\\n event SetFeelessAddress(address indexed addrs, bool indexed flag, address caller);\\n\\n event PayoutReverted(uint256 indexed projectId, JBSplit split, uint256 amount, bytes reason, address caller);\\n\\n event FeeReverted(\\n uint256 indexed projectId,\\n uint256 indexed feeProjectId,\\n uint256 amount,\\n bytes reason,\\n address caller\\n );\\n\\n function projects() external view returns (IJBProjects);\\n\\n function splitsStore() external view returns (IJBSplitsStore);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function prices() external view returns (IJBPrices);\\n\\n function store() external view returns (IJBSingleTokenPaymentTerminalStore);\\n\\n function baseWeightCurrency() external view returns (uint256);\\n\\n function payoutSplitsGroup() external view returns (uint256);\\n\\n function heldFeesOf(uint256 _projectId) external view returns (JBFee[] memory);\\n\\n function fee() external view returns (uint256);\\n\\n function feeGauge() external view returns (IJBFeeGauge);\\n\\n function isFeelessAddress(address _contract) external view returns (bool);\\n\\n function migrate(uint256 _projectId, IJBPaymentTerminal _to) external returns (uint256 balance);\\n\\n function processFees(uint256 _projectId) external;\\n\\n function setFee(uint256 _fee) external;\\n\\n function setFeeGauge(IJBFeeGauge _feeGauge) external;\\n\\n function setFeelessAddress(address _contract, bool _flag) external;\\n}\\n\",\"keccak256\":\"0xe823526fd535dc962784820cac32e6fdd56f2a5020dbf9883979b9ddfcc093fa\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPayoutTerminal3_1.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBPayoutTerminal3_1 {\\n function distributePayoutsOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n address _token,\\n uint256 _minReturnedTokens,\\n bytes calldata _metadata\\n ) external returns (uint256 netLeftoverDistributionAmount);\\n}\\n\",\"keccak256\":\"0x415707a4902f90945ecee641e96dd88c733b1d159c35c1184e665ca3509ffe49\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPriceFeed.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBPriceFeed {\\n function currentPrice(uint256 _targetDecimals) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x57c71282fec1b34b00cf991ffed2e36031c393e35bfa7ca5d723eb6572fb7122\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPrices.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBPriceFeed.sol';\\n\\ninterface IJBPrices {\\n event AddFeed(uint256 indexed currency, uint256 indexed base, IJBPriceFeed feed);\\n\\n function feedFor(uint256 _currency, uint256 _base) external view returns (IJBPriceFeed);\\n\\n function priceFor(\\n uint256 _currency,\\n uint256 _base,\\n uint256 _decimals\\n ) external view returns (uint256);\\n\\n function addFeedFor(\\n uint256 _currency,\\n uint256 _base,\\n IJBPriceFeed _priceFeed\\n ) external;\\n}\\n\",\"keccak256\":\"0x82a175b1f4b95b506c98406576cd59cbe04615e3df24f9cf3587b61b8ee323b1\",\"license\":\"MIT\"},\"contracts/interfaces/IJBProjects.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBTokenUriResolver.sol';\\n\\ninterface IJBProjects is IERC721 {\\n event Create(\\n uint256 indexed projectId,\\n address indexed owner,\\n JBProjectMetadata metadata,\\n address caller\\n );\\n\\n event SetMetadata(uint256 indexed projectId, JBProjectMetadata metadata, address caller);\\n\\n event SetTokenUriResolver(IJBTokenUriResolver indexed resolver, address caller);\\n\\n function count() external view returns (uint256);\\n\\n function metadataContentOf(uint256 _projectId, uint256 _domain)\\n external\\n view\\n returns (string memory);\\n\\n function tokenUriResolver() external view returns (IJBTokenUriResolver);\\n\\n function createFor(address _owner, JBProjectMetadata calldata _metadata)\\n external\\n returns (uint256 projectId);\\n\\n function setMetadataOf(uint256 _projectId, JBProjectMetadata calldata _metadata) external;\\n\\n function setTokenUriResolver(IJBTokenUriResolver _newResolver) external;\\n}\\n\",\"keccak256\":\"0x7cfc021d0bd7e73b1ba8f4845d7d35e3419d6a14d3d25ca3a8010e7f91062fe4\",\"license\":\"MIT\"},\"contracts/interfaces/IJBRedemptionDelegate.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBDidRedeemData.sol';\\n\\n/**\\n @title\\n Redemption delegate\\n\\n @notice\\n Delegate called after JBTerminal.redeemTokensOf(..) logic completion (if passed by the funding cycle datasource)\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n*/\\ninterface IJBRedemptionDelegate is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.redeemTokensOf(..), after the execution of its logic\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control\\n \\n @param _data the data passed by the terminal, as a JBDidRedeemData struct:\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 projectTokenCount;\\n JBTokenAmount reclaimedAmount;\\n JBTokenAmount forwardedAmount;\\n address payable beneficiary;\\n string memo;\\n bytes metadata;\\n */\\n function didRedeem(JBDidRedeemData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0x172d2c0be65e72e54f71ae521907067f0fa30e8ca05c4f88826903208aa437e2\",\"license\":\"MIT\"},\"contracts/interfaces/IJBRedemptionTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBRedemptionTerminal {\\n function redeemTokensOf(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n address _token,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external returns (uint256 reclaimAmount);\\n}\\n\",\"keccak256\":\"0xe26a6a03468401b802ae5328b39a266f53b9331a1c077fcbf7719d10ba74ff44\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSingleTokenPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBPaymentTerminal.sol';\\n\\ninterface IJBSingleTokenPaymentTerminal is IJBPaymentTerminal {\\n function token() external view returns (address);\\n\\n function currency() external view returns (uint256);\\n\\n function decimals() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xf6e78323caa9af7bbf024f44b2032a83fed0394e0b3a242a6346e73c85b2e46f\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSingleTokenPaymentTerminalStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBPayDelegateAllocation.sol';\\nimport './../structs/JBRedemptionDelegateAllocation.sol';\\nimport './../structs/JBTokenAmount.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBPrices.sol';\\nimport './IJBSingleTokenPaymentTerminal.sol';\\n\\ninterface IJBSingleTokenPaymentTerminalStore {\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function prices() external view returns (IJBPrices);\\n\\n function balanceOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\\n external\\n view\\n returns (uint256);\\n\\n function usedDistributionLimitOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _fundingCycleNumber\\n ) external view returns (uint256);\\n\\n function usedOverflowAllowanceOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _fundingCycleConfiguration\\n ) external view returns (uint256);\\n\\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\\n external\\n view\\n returns (uint256);\\n\\n function currentTotalOverflowOf(\\n uint256 _projectId,\\n uint256 _decimals,\\n uint256 _currency\\n ) external view returns (uint256);\\n\\n function currentReclaimableOverflowOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n bool _useTotalOverflow\\n ) external view returns (uint256);\\n\\n function currentReclaimableOverflowOf(\\n uint256 _projectId,\\n uint256 _tokenCount,\\n uint256 _totalSupply,\\n uint256 _overflow\\n ) external view returns (uint256);\\n\\n function recordPaymentFrom(\\n address _payer,\\n JBTokenAmount memory _amount,\\n uint256 _projectId,\\n uint256 _baseWeightCurrency,\\n address _beneficiary,\\n string calldata _memo,\\n bytes calldata _metadata\\n )\\n external\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 tokenCount,\\n JBPayDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n );\\n\\n function recordRedemptionFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n string calldata _memo,\\n bytes calldata _metadata\\n )\\n external\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 reclaimAmount,\\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n );\\n\\n function recordDistributionFor(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n ) external returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount);\\n\\n function recordUsedAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n ) external returns (JBFundingCycle memory fundingCycle, uint256 withdrawnAmount);\\n\\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external;\\n\\n function recordMigration(uint256 _projectId) external returns (uint256 balance);\\n}\\n\",\"keccak256\":\"0xd78929c9371fd7895b829ef5e4ad4b3786523c3580ac3f6f5f25d2b5941c0dd3\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSplitAllocator.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport '../structs/JBSplitAllocationData.sol';\\n\\n/**\\n @title\\n Split allocator\\n\\n @notice\\n Provide a way to process a single split with extra logic\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n\\n @dev\\n The contract address should be set as an allocator in the adequate split\\n*/\\ninterface IJBSplitAllocator is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.distributePayoutOf(..), during the processing of the split including it\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control. The token and/or eth are optimistically transfered\\n to the allocator for its logic.\\n \\n @param _data the data passed by the terminal, as a JBSplitAllocationData struct:\\n address token;\\n uint256 amount;\\n uint256 decimals;\\n uint256 projectId;\\n uint256 group;\\n JBSplit split;\\n */\\n function allocate(JBSplitAllocationData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0x5efb6f51fc161f42ff58989386ad99028e4039a0ba897d66f358c3dfcf686105\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSplitsStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBGroupedSplits.sol';\\nimport './../structs/JBSplit.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBProjects.sol';\\n\\ninterface IJBSplitsStore {\\n event SetSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n address caller\\n );\\n\\n function projects() external view returns (IJBProjects);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function splitsOf(\\n uint256 _projectId,\\n uint256 _domain,\\n uint256 _group\\n ) external view returns (JBSplit[] memory);\\n\\n function set(\\n uint256 _projectId,\\n uint256 _domain,\\n JBGroupedSplits[] memory _groupedSplits\\n ) external;\\n}\\n\",\"keccak256\":\"0x66dab3dd394e318b850401ca92c2963b906cc0ad5562fa5d4f6f850175d1c77a\",\"license\":\"MIT\"},\"contracts/interfaces/IJBToken.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBToken {\\n function projectId() external view returns (uint256);\\n\\n function decimals() external view returns (uint8);\\n\\n function totalSupply(uint256 _projectId) external view returns (uint256);\\n\\n function balanceOf(address _account, uint256 _projectId) external view returns (uint256);\\n\\n function mint(\\n uint256 _projectId,\\n address _account,\\n uint256 _amount\\n ) external;\\n\\n function burn(\\n uint256 _projectId,\\n address _account,\\n uint256 _amount\\n ) external;\\n\\n function approve(\\n uint256,\\n address _spender,\\n uint256 _amount\\n ) external;\\n\\n function transfer(\\n uint256 _projectId,\\n address _to,\\n uint256 _amount\\n ) external;\\n\\n function transferFrom(\\n uint256 _projectId,\\n address _from,\\n address _to,\\n uint256 _amount\\n ) external;\\n}\\n\",\"keccak256\":\"0xe8969210417736c85d71101bf1c0bd8ebbf9d1e62a93e758148bd5709a6c7097\",\"license\":\"MIT\"},\"contracts/interfaces/IJBTokenStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBProjects.sol';\\nimport './IJBToken.sol';\\n\\ninterface IJBTokenStore {\\n event Issue(\\n uint256 indexed projectId,\\n IJBToken indexed token,\\n string name,\\n string symbol,\\n address caller\\n );\\n\\n event Mint(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 amount,\\n bool tokensWereClaimed,\\n bool preferClaimedTokens,\\n address caller\\n );\\n\\n event Burn(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 amount,\\n uint256 initialUnclaimedBalance,\\n uint256 initialClaimedBalance,\\n bool preferClaimedTokens,\\n address caller\\n );\\n\\n event Claim(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 initialUnclaimedBalance,\\n uint256 amount,\\n address caller\\n );\\n\\n event Set(uint256 indexed projectId, IJBToken indexed newToken, address caller);\\n\\n event Transfer(\\n address indexed holder,\\n uint256 indexed projectId,\\n address indexed recipient,\\n uint256 amount,\\n address caller\\n );\\n\\n function tokenOf(uint256 _projectId) external view returns (IJBToken);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function unclaimedBalanceOf(address _holder, uint256 _projectId) external view returns (uint256);\\n\\n function unclaimedTotalSupplyOf(uint256 _projectId) external view returns (uint256);\\n\\n function totalSupplyOf(uint256 _projectId) external view returns (uint256);\\n\\n function balanceOf(address _holder, uint256 _projectId) external view returns (uint256 _result);\\n\\n function issueFor(\\n uint256 _projectId,\\n string calldata _name,\\n string calldata _symbol\\n ) external returns (IJBToken token);\\n\\n function setFor(uint256 _projectId, IJBToken _token) external;\\n\\n function burnFrom(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function mintFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function claimFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount\\n ) external;\\n\\n function transferFrom(\\n address _holder,\\n uint256 _projectId,\\n address _recipient,\\n uint256 _amount\\n ) external;\\n}\\n\",\"keccak256\":\"0x98459e3af050d41dfeffdc97f1c93330207ba450f8ff3613224b49a89eeca9c6\",\"license\":\"MIT\"},\"contracts/interfaces/IJBTokenUriResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBTokenUriResolver {\\n function getUri(uint256 _projectId) external view returns (string memory tokenUri);\\n}\\n\",\"keccak256\":\"0xd267fd8ca7c21c2c71794acdb9a98314c33a35fc559e0bf0897a6686d196d174\",\"license\":\"MIT\"},\"contracts/libraries/JBConstants.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/**\\n @notice\\n Global constants used across Juicebox contracts.\\n*/\\nlibrary JBConstants {\\n uint256 public constant MAX_RESERVED_RATE = 10_000;\\n uint256 public constant MAX_REDEMPTION_RATE = 10_000;\\n uint256 public constant MAX_DISCOUNT_RATE = 1_000_000_000;\\n uint256 public constant SPLITS_TOTAL_PERCENT = 1_000_000_000;\\n uint256 public constant MAX_FEE = 1_000_000_000;\\n uint256 public constant MAX_FEE_DISCOUNT = 1_000_000_000;\\n}\\n\",\"keccak256\":\"0x34362846a1cd428a8bdedf4ab6857e11402f345cb87b994b2e7fb6d2474b808d\",\"license\":\"MIT\"},\"contracts/libraries/JBCurrencies.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBCurrencies {\\n uint256 public constant ETH = 1;\\n uint256 public constant USD = 2;\\n}\\n\",\"keccak256\":\"0x7e417ff25c173608ee4fe6d9fc3dcd5e1458c78c889af12bac47b1189a436076\",\"license\":\"MIT\"},\"contracts/libraries/JBFixedPointNumber.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nlibrary JBFixedPointNumber {\\n function adjustDecimals(\\n uint256 _value,\\n uint256 _decimals,\\n uint256 _targetDecimals\\n ) internal pure returns (uint256) {\\n // If decimals need adjusting, multiply or divide the price by the decimal adjuster to get the normalized result.\\n if (_targetDecimals == _decimals) return _value;\\n else if (_targetDecimals > _decimals) return _value * 10**(_targetDecimals - _decimals);\\n else return _value / 10**(_decimals - _targetDecimals);\\n }\\n}\\n\",\"keccak256\":\"0x18efac48269f3a3bd7e9a1c770776f950e0afa86769e6f8b128002c3b8c6742c\",\"license\":\"MIT\"},\"contracts/libraries/JBFundingCycleMetadataResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBFundingCycleMetadata.sol';\\nimport './../structs/JBGlobalFundingCycleMetadata.sol';\\nimport './JBConstants.sol';\\nimport './JBGlobalFundingCycleMetadataResolver.sol';\\n\\nlibrary JBFundingCycleMetadataResolver {\\n function global(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (JBGlobalFundingCycleMetadata memory)\\n {\\n return JBGlobalFundingCycleMetadataResolver.expandMetadata(uint8(_fundingCycle.metadata >> 8));\\n }\\n\\n function reservedRate(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n return uint256(uint16(_fundingCycle.metadata >> 24));\\n }\\n\\n function redemptionRate(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n // Redemption rate is a number 0-10000. It's inverse was stored so the most common case of 100% results in no storage needs.\\n return JBConstants.MAX_REDEMPTION_RATE - uint256(uint16(_fundingCycle.metadata >> 40));\\n }\\n\\n function ballotRedemptionRate(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (uint256)\\n {\\n // Redemption rate is a number 0-10000. It's inverse was stored so the most common case of 100% results in no storage needs.\\n return JBConstants.MAX_REDEMPTION_RATE - uint256(uint16(_fundingCycle.metadata >> 56));\\n }\\n\\n function payPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 72) & 1) == 1;\\n }\\n\\n function distributionsPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 73) & 1) == 1;\\n }\\n\\n function redeemPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 74) & 1) == 1;\\n }\\n\\n function burnPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 75) & 1) == 1;\\n }\\n\\n function mintingAllowed(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 76) & 1) == 1;\\n }\\n\\n function terminalMigrationAllowed(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 77) & 1) == 1;\\n }\\n\\n function controllerMigrationAllowed(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 78) & 1) == 1;\\n }\\n\\n function shouldHoldFees(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 79) & 1) == 1;\\n }\\n\\n function preferClaimedTokenOverride(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 80) & 1) == 1;\\n }\\n\\n function useTotalOverflowForRedemptions(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 81) & 1) == 1;\\n }\\n\\n function useDataSourceForPay(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return (_fundingCycle.metadata >> 82) & 1 == 1;\\n }\\n\\n function useDataSourceForRedeem(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return (_fundingCycle.metadata >> 83) & 1 == 1;\\n }\\n\\n function dataSource(JBFundingCycle memory _fundingCycle) internal pure returns (address) {\\n return address(uint160(_fundingCycle.metadata >> 84));\\n }\\n\\n function metadata(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n return uint256(uint8(_fundingCycle.metadata >> 244));\\n }\\n\\n /**\\n @notice\\n Pack the funding cycle metadata.\\n\\n @param _metadata The metadata to validate and pack.\\n\\n @return packed The packed uint256 of all metadata params. The first 8 bits specify the version.\\n */\\n function packFundingCycleMetadata(JBFundingCycleMetadata memory _metadata)\\n internal\\n pure\\n returns (uint256 packed)\\n {\\n // version 1 in the bits 0-7 (8 bits).\\n packed = 1;\\n // global metadta in bits 8-23 (16 bits).\\n packed |=\\n JBGlobalFundingCycleMetadataResolver.packFundingCycleGlobalMetadata(_metadata.global) <<\\n 8;\\n // reserved rate in bits 24-39 (16 bits).\\n packed |= _metadata.reservedRate << 24;\\n // redemption rate in bits 40-55 (16 bits).\\n // redemption rate is a number 0-10000. Store the reverse so the most common case of 100% results in no storage needs.\\n packed |= (JBConstants.MAX_REDEMPTION_RATE - _metadata.redemptionRate) << 40;\\n // ballot redemption rate rate in bits 56-71 (16 bits).\\n // ballot redemption rate is a number 0-10000. Store the reverse so the most common case of 100% results in no storage needs.\\n packed |= (JBConstants.MAX_REDEMPTION_RATE - _metadata.ballotRedemptionRate) << 56;\\n // pause pay in bit 72.\\n if (_metadata.pausePay) packed |= 1 << 72;\\n // pause tap in bit 73.\\n if (_metadata.pauseDistributions) packed |= 1 << 73;\\n // pause redeem in bit 74.\\n if (_metadata.pauseRedeem) packed |= 1 << 74;\\n // pause burn in bit 75.\\n if (_metadata.pauseBurn) packed |= 1 << 75;\\n // allow minting in bit 76.\\n if (_metadata.allowMinting) packed |= 1 << 76;\\n // allow terminal migration in bit 77.\\n if (_metadata.allowTerminalMigration) packed |= 1 << 77;\\n // allow controller migration in bit 78.\\n if (_metadata.allowControllerMigration) packed |= 1 << 78;\\n // hold fees in bit 79.\\n if (_metadata.holdFees) packed |= 1 << 79;\\n // prefer claimed token override in bit 80.\\n if (_metadata.preferClaimedTokenOverride) packed |= 1 << 80;\\n // useTotalOverflowForRedemptions in bit 81.\\n if (_metadata.useTotalOverflowForRedemptions) packed |= 1 << 81;\\n // use pay data source in bit 82.\\n if (_metadata.useDataSourceForPay) packed |= 1 << 82;\\n // use redeem data source in bit 83.\\n if (_metadata.useDataSourceForRedeem) packed |= 1 << 83;\\n // data source address in bits 84-243.\\n packed |= uint256(uint160(address(_metadata.dataSource))) << 84;\\n // metadata in bits 244-252 (8 bits).\\n packed |= _metadata.metadata << 244;\\n }\\n\\n /**\\n @notice\\n Expand the funding cycle metadata.\\n\\n @param _fundingCycle The funding cycle having its metadata expanded.\\n\\n @return metadata The metadata object.\\n */\\n function expandMetadata(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (JBFundingCycleMetadata memory)\\n {\\n return\\n JBFundingCycleMetadata(\\n global(_fundingCycle),\\n reservedRate(_fundingCycle),\\n redemptionRate(_fundingCycle),\\n ballotRedemptionRate(_fundingCycle),\\n payPaused(_fundingCycle),\\n distributionsPaused(_fundingCycle),\\n redeemPaused(_fundingCycle),\\n burnPaused(_fundingCycle),\\n mintingAllowed(_fundingCycle),\\n terminalMigrationAllowed(_fundingCycle),\\n controllerMigrationAllowed(_fundingCycle),\\n shouldHoldFees(_fundingCycle),\\n preferClaimedTokenOverride(_fundingCycle),\\n useTotalOverflowForRedemptions(_fundingCycle),\\n useDataSourceForPay(_fundingCycle),\\n useDataSourceForRedeem(_fundingCycle),\\n dataSource(_fundingCycle),\\n metadata(_fundingCycle)\\n );\\n }\\n}\\n\",\"keccak256\":\"0x3d045c38593102cfb6ac67f3ddf2232e1ff5518d6d021423ae2681387599fbd3\",\"license\":\"MIT\"},\"contracts/libraries/JBGlobalFundingCycleMetadataResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport './../structs/JBFundingCycleMetadata.sol';\\n\\nlibrary JBGlobalFundingCycleMetadataResolver {\\n function setTerminalsAllowed(uint8 _data) internal pure returns (bool) {\\n return (_data & 1) == 1;\\n }\\n\\n function setControllerAllowed(uint8 _data) internal pure returns (bool) {\\n return ((_data >> 1) & 1) == 1;\\n }\\n\\n function transfersPaused(uint8 _data) internal pure returns (bool) {\\n return ((_data >> 2) & 1) == 1;\\n }\\n\\n /**\\n @notice\\n Pack the global funding cycle metadata.\\n\\n @param _metadata The metadata to validate and pack.\\n\\n @return packed The packed uint256 of all global metadata params. The first 8 bits specify the version.\\n */\\n function packFundingCycleGlobalMetadata(JBGlobalFundingCycleMetadata memory _metadata)\\n internal\\n pure\\n returns (uint256 packed)\\n {\\n // allow set terminals in bit 0.\\n if (_metadata.allowSetTerminals) packed |= 1;\\n // allow set controller in bit 1.\\n if (_metadata.allowSetController) packed |= 1 << 1;\\n // pause transfers in bit 2.\\n if (_metadata.pauseTransfers) packed |= 1 << 2;\\n }\\n\\n /**\\n @notice\\n Expand the global funding cycle metadata.\\n\\n @param _packedMetadata The packed metadata to expand.\\n\\n @return metadata The global metadata object.\\n */\\n function expandMetadata(uint8 _packedMetadata)\\n internal\\n pure\\n returns (JBGlobalFundingCycleMetadata memory metadata)\\n {\\n return\\n JBGlobalFundingCycleMetadata(\\n setTerminalsAllowed(_packedMetadata),\\n setControllerAllowed(_packedMetadata),\\n transfersPaused(_packedMetadata)\\n );\\n }\\n}\\n\",\"keccak256\":\"0x0d998f938026edeb755987a79421267cf860801161b5f171206a200b60f1061f\",\"license\":\"MIT\"},\"contracts/libraries/JBOperations.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBOperations {\\n uint256 public constant RECONFIGURE = 1;\\n uint256 public constant REDEEM = 2;\\n uint256 public constant MIGRATE_CONTROLLER = 3;\\n uint256 public constant MIGRATE_TERMINAL = 4;\\n uint256 public constant PROCESS_FEES = 5;\\n uint256 public constant SET_METADATA = 6;\\n uint256 public constant ISSUE = 7;\\n uint256 public constant SET_TOKEN = 8;\\n uint256 public constant MINT = 9;\\n uint256 public constant BURN = 10;\\n uint256 public constant CLAIM = 11;\\n uint256 public constant TRANSFER = 12;\\n uint256 public constant REQUIRE_CLAIM = 13; // unused in v3\\n uint256 public constant SET_CONTROLLER = 14;\\n uint256 public constant SET_TERMINALS = 15;\\n uint256 public constant SET_PRIMARY_TERMINAL = 16;\\n uint256 public constant USE_ALLOWANCE = 17;\\n uint256 public constant SET_SPLITS = 18;\\n}\\n\",\"keccak256\":\"0x7f8e501e6890297f4015b1c27cebdb44fadbf21204bea1f3162f5388c060f690\",\"license\":\"MIT\"},\"contracts/libraries/JBSplitsGroups.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBSplitsGroups {\\n uint256 public constant ETH_PAYOUT = 1;\\n uint256 public constant RESERVED_TOKENS = 2;\\n}\\n\",\"keccak256\":\"0x4183db6087bd8db645fc3a0d3d8afb0d6356e003650793f63c301ebbbae47269\",\"license\":\"MIT\"},\"contracts/libraries/JBTokens.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBTokens {\\n /** \\n @notice \\n The ETH token address in Juicebox is represented by 0x000000000000000000000000000000000000EEEe.\\n */\\n address public constant ETH = address(0x000000000000000000000000000000000000EEEe);\\n}\\n\",\"keccak256\":\"0xecf82992f7b827766aa55f16872517a646521eef414d8cc9786617ea377e5463\",\"license\":\"MIT\"},\"contracts/structs/JBDidPayData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member payer The address from which the payment originated.\\n @member projectId The ID of the project for which the payment was made.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the payment is being made.\\n @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.\\n @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.\\n @member projectTokenCount The number of project tokens minted for the beneficiary.\\n @member beneficiary The address to which the tokens were minted.\\n @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.\\n @member memo The memo that is being emitted alongside the payment.\\n @member metadata Extra data to send to the delegate.\\n*/\\nstruct JBDidPayData {\\n address payer;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n JBTokenAmount amount;\\n JBTokenAmount forwardedAmount;\\n uint256 projectTokenCount;\\n address beneficiary;\\n bool preferClaimedTokens;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0xf3c664309b37790f16047ae97b0459889ae0242dfcde7fc8902c8d10c7f8e6b6\",\"license\":\"MIT\"},\"contracts/structs/JBDidRedeemData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member holder The holder of the tokens being redeemed.\\n @member projectId The ID of the project with which the redeemed tokens are associated.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the redemption is being made.\\n @member projectTokenCount The number of project tokens being redeemed.\\n @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.\\n @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.\\n @member beneficiary The address to which the reclaimed amount will be sent.\\n @member memo The memo that is being emitted alongside the redemption.\\n @member metadata Extra data to send to the delegate.\\n*/\\nstruct JBDidRedeemData {\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 projectTokenCount;\\n JBTokenAmount reclaimedAmount;\\n JBTokenAmount forwardedAmount;\\n address payable beneficiary;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0xe2c401f39723a7ce915b8bef328744c66daaf57460843964b941456c2258a412\",\"license\":\"MIT\"},\"contracts/structs/JBFee.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member amount The total amount the fee was taken from, as a fixed point number with the same number of decimals as the terminal in which this struct was created.\\n @member fee The percent of the fee, out of MAX_FEE.\\n @member feeDiscount The discount of the fee.\\n @member beneficiary The address that will receive the tokens that are minted as a result of the fee payment.\\n*/\\nstruct JBFee {\\n uint256 amount;\\n uint32 fee;\\n uint32 feeDiscount;\\n address beneficiary;\\n}\\n\",\"keccak256\":\"0xf4759ff41fe7f1db0fd1ccc7b2a326b239389fd8d69df9b9ed5e1d5926f6fe38\",\"license\":\"MIT\"},\"contracts/structs/JBFundAccessConstraints.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBPaymentTerminal.sol';\\n\\n/** \\n @member terminal The terminal within which the distribution limit and the overflow allowance applies.\\n @member token The token for which the fund access constraints apply.\\n @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.\\n @member distributionLimitCurrency The currency of the distribution limit.\\n @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.\\n @member overflowAllowanceCurrency The currency of the overflow allowance.\\n*/\\nstruct JBFundAccessConstraints {\\n IJBPaymentTerminal terminal;\\n address token;\\n uint256 distributionLimit;\\n uint256 distributionLimitCurrency;\\n uint256 overflowAllowance;\\n uint256 overflowAllowanceCurrency;\\n}\\n\",\"keccak256\":\"0x85ebaa57b788cbdedc7a3d0eec4892eda5d79db7c1a6103797f10d0d989775b2\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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.\\n @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.\\n @member basedOn The `configuration` of the funding cycle that was active when this cycle was created.\\n @member start The timestamp marking the moment from which the funding cycle is considered active. It is a unix timestamp measured in seconds.\\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n @member metadata Extra data that can be associated with a funding cycle.\\n*/\\nstruct JBFundingCycle {\\n uint256 number;\\n uint256 configuration;\\n uint256 basedOn;\\n uint256 start;\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n uint256 metadata;\\n}\\n\",\"keccak256\":\"0xcdd3ac9b6fa67e62ada88d09b73bc35ade1cd77d43db712289266a788928b4c2\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycleData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n*/\\nstruct JBFundingCycleData {\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n}\\n\",\"keccak256\":\"0x2aa6368bf4dfc5797e8b02a978293de0c777fae2658de2c825a103587240f3b0\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycleMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBGlobalFundingCycleMetadata.sol';\\n\\n/** \\n @member global Data used globally in non-migratable ecosystem contracts.\\n @member reservedRate The reserved rate of the funding cycle. This number is a percentage calculated out of `JBConstants.MAX_RESERVED_RATE`.\\n @member redemptionRate The redemption rate of the funding cycle. This number is a percentage calculated out of `JBConstants.MAX_REDEMPTION_RATE`.\\n @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`.\\n @member pausePay A flag indicating if the pay functionality should be paused during the funding cycle.\\n @member pauseDistributions A flag indicating if the distribute functionality should be paused during the funding cycle.\\n @member pauseRedeem A flag indicating if the redeem functionality should be paused during the funding cycle.\\n @member pauseBurn A flag indicating if the burn functionality should be paused during the funding cycle.\\n @member allowMinting A flag indicating if minting tokens should be allowed during this funding cycle.\\n @member allowTerminalMigration A flag indicating if migrating terminals should be allowed during this funding cycle.\\n @member allowControllerMigration A flag indicating if migrating controllers should be allowed during this funding cycle.\\n @member holdFees A flag indicating if fees should be held during this funding cycle.\\n @member preferClaimedTokenOverride A flag indicating if claimed tokens should always be prefered to unclaimed tokens when minting.\\n @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.\\n @member useDataSourceForPay A flag indicating if the data source should be used for pay transactions during this funding cycle.\\n @member useDataSourceForRedeem A flag indicating if the data source should be used for redeem transactions during this funding cycle.\\n @member dataSource The data source to use during this funding cycle.\\n @member metadata Metadata of the metadata, up to uint8 in size.\\n*/\\nstruct JBFundingCycleMetadata {\\n JBGlobalFundingCycleMetadata global;\\n uint256 reservedRate;\\n uint256 redemptionRate;\\n uint256 ballotRedemptionRate;\\n bool pausePay;\\n bool pauseDistributions;\\n bool pauseRedeem;\\n bool pauseBurn;\\n bool allowMinting;\\n bool allowTerminalMigration;\\n bool allowControllerMigration;\\n bool holdFees;\\n bool preferClaimedTokenOverride;\\n bool useTotalOverflowForRedemptions;\\n bool useDataSourceForPay;\\n bool useDataSourceForRedeem;\\n address dataSource;\\n uint256 metadata;\\n}\\n\",\"keccak256\":\"0x783604440cac8d176332eab28166f188ee5c230378c08cfc95fea4f7187dc77d\",\"license\":\"MIT\"},\"contracts/structs/JBGlobalFundingCycleMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member allowSetTerminals A flag indicating if setting terminals should be allowed during this funding cycle.\\n @member allowSetController A flag indicating if setting a new controller should be allowed during this funding cycle.\\n @member pauseTransfers A flag indicating if the project token transfer functionality should be paused during the funding cycle.\\n*/\\nstruct JBGlobalFundingCycleMetadata {\\n bool allowSetTerminals;\\n bool allowSetController;\\n bool pauseTransfers;\\n}\\n\",\"keccak256\":\"0x05d85530305fec6d6eca54cdbc2cd9110cbda0146598032b0203aa4b622944ff\",\"license\":\"MIT\"},\"contracts/structs/JBGroupedSplits.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBSplit.sol';\\n\\n/** \\n @member group The group indentifier.\\n @member splits The splits to associate with the group.\\n*/\\nstruct JBGroupedSplits {\\n uint256 group;\\n JBSplit[] splits;\\n}\\n\",\"keccak256\":\"0x80be1b220da4ac04851ea540ebb94c1ec2b0442ec5bd1e88fdf78a56becd8b5a\",\"license\":\"MIT\"},\"contracts/structs/JBOperatorData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member operator The address of the operator.\\n @member domain The domain within which the operator is being given permissions. A domain of 0 is a wildcard domain, which gives an operator access to all domains.\\n @member permissionIndexes The indexes of the permissions the operator is being given.\\n*/\\nstruct JBOperatorData {\\n address operator;\\n uint256 domain;\\n uint256[] permissionIndexes;\\n}\\n\",\"keccak256\":\"0x3b85be7b69515976ee10770776283911666aceca820b0cf4e201ea4dbffeb6f0\",\"license\":\"MIT\"},\"contracts/structs/JBPayDelegateAllocation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '../interfaces/IJBPayDelegate.sol';\\n\\n/** \\n @member delegate A delegate contract to use for subsequent calls.\\n @member amount The amount to send to the delegate.\\n*/\\nstruct JBPayDelegateAllocation {\\n IJBPayDelegate delegate;\\n uint256 amount;\\n}\\n\",\"keccak256\":\"0xb4e558dc62231d89e9b48998012577d22c3e52b58e23401f22d9096827f6ea0c\",\"license\":\"MIT\"},\"contracts/structs/JBProjectMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member content The metadata content.\\n @member domain The domain within which the metadata applies.\\n*/\\nstruct JBProjectMetadata {\\n string content;\\n uint256 domain;\\n}\\n\",\"keccak256\":\"0x90ad7b1014c0a9f945fe7a2efde9d5de41e40574fa27969070b1d2ff52033ea0\",\"license\":\"MIT\"},\"contracts/structs/JBRedemptionDelegateAllocation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '../interfaces/IJBRedemptionDelegate.sol';\\n\\n/** \\n @member delegate A delegate contract to use for subsequent calls.\\n @member amount The amount to send to the delegate.\\n*/\\nstruct JBRedemptionDelegateAllocation {\\n IJBRedemptionDelegate delegate;\\n uint256 amount;\\n}\\n\",\"keccak256\":\"0x10c29d33dd0d875a0d4692a2b9a9355c2ebf433cc06a9a60253d4366b60d4d31\",\"license\":\"MIT\"},\"contracts/structs/JBSplit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBSplitAllocator.sol';\\n\\n/** \\n @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.\\n @member preferAddToBalance A flag indicating if a distribution to a project should prefer triggering it's addToBalance function instead of its pay function.\\n @member percent The percent of the whole group that this split occupies. This number is out of `JBConstants.SPLITS_TOTAL_PERCENT`.\\n @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.\\n @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.\\n @member lockedUntil Specifies if the split should be unchangeable until the specified time, with the exception of extending the locked period.\\n @member allocator If an allocator is specified, funds will be sent to the allocator contract along with all properties of this split.\\n*/\\nstruct JBSplit {\\n bool preferClaimed;\\n bool preferAddToBalance;\\n uint256 percent;\\n uint256 projectId;\\n address payable beneficiary;\\n uint256 lockedUntil;\\n IJBSplitAllocator allocator;\\n}\\n\",\"keccak256\":\"0xc80a16606da8abf76d0f73abc38aee041e24f29342c1939018f70c286e89f105\",\"license\":\"MIT\"},\"contracts/structs/JBSplitAllocationData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBSplit.sol';\\n\\n/** \\n @member token The token being sent to the split allocator.\\n @member amount The amount being sent to the split allocator, as a fixed point number.\\n @member decimals The number of decimals in the amount.\\n @member projectId The project to which the split belongs.\\n @member group The group to which the split belongs.\\n @member split The split that caused the allocation.\\n*/\\nstruct JBSplitAllocationData {\\n address token;\\n uint256 amount;\\n uint256 decimals;\\n uint256 projectId;\\n uint256 group;\\n JBSplit split;\\n}\\n\",\"keccak256\":\"0x39f5c41bd31d36774744698ac94484b6cab62d7038df2f29d947668959782e63\",\"license\":\"MIT\"},\"contracts/structs/JBTokenAmount.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/* \\n @member token The token the payment was made in.\\n @member value The amount of tokens that was paid, as a fixed point number.\\n @member decimals The number of decimals included in the value fixed point number.\\n @member currency The expected currency of the value.\\n**/\\nstruct JBTokenAmount {\\n address token;\\n uint256 value;\\n uint256 decimals;\\n uint256 currency;\\n}\\n\",\"keccak256\":\"0x4a778e779ba257ba5638c5469e07a4d21b55a3128d56db5a0fdfacb1f3301c51\",\"license\":\"MIT\"},\"prb-math/contracts/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivFixedPointOverflow(uint256 prod1);\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivOverflow(uint256 prod1, uint256 denominator);\\n\\n/// @notice Emitted when one of the inputs is type(int256).min.\\nerror PRBMath__MulDivSignedInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows int256.\\nerror PRBMath__MulDivSignedOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is MIN_SD59x18.\\nerror PRBMathSD59x18__AbsInputTooSmall();\\n\\n/// @notice Emitted when ceiling a number overflows SD59x18.\\nerror PRBMathSD59x18__CeilOverflow(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__DivInputTooSmall();\\n\\n/// @notice Emitted when one of the intermediary unsigned results overflows SD59x18.\\nerror PRBMathSD59x18__DivOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathSD59x18__ExpInputTooBig(int256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathSD59x18__Exp2InputTooBig(int256 x);\\n\\n/// @notice Emitted when flooring a number underflows SD59x18.\\nerror PRBMathSD59x18__FloorUnderflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format overflows SD59x18.\\nerror PRBMathSD59x18__FromIntOverflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format underflows SD59x18.\\nerror PRBMathSD59x18__FromIntUnderflow(int256 x);\\n\\n/// @notice Emitted when the product of the inputs is negative.\\nerror PRBMathSD59x18__GmNegativeProduct(int256 x, int256 y);\\n\\n/// @notice Emitted when multiplying the inputs overflows SD59x18.\\nerror PRBMathSD59x18__GmOverflow(int256 x, int256 y);\\n\\n/// @notice Emitted when the input is less than or equal to zero.\\nerror PRBMathSD59x18__LogInputTooSmall(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__MulInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__MulOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__PowuOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is negative.\\nerror PRBMathSD59x18__SqrtNegativeInput(int256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows SD59x18.\\nerror PRBMathSD59x18__SqrtOverflow(int256 x);\\n\\n/// @notice Emitted when addition overflows UD60x18.\\nerror PRBMathUD60x18__AddOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when ceiling a number overflows UD60x18.\\nerror PRBMathUD60x18__CeilOverflow(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathUD60x18__ExpInputTooBig(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathUD60x18__Exp2InputTooBig(uint256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format format overflows UD60x18.\\nerror PRBMathUD60x18__FromUintOverflow(uint256 x);\\n\\n/// @notice Emitted when multiplying the inputs overflows UD60x18.\\nerror PRBMathUD60x18__GmOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when the input is less than 1.\\nerror PRBMathUD60x18__LogInputTooSmall(uint256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows UD60x18.\\nerror PRBMathUD60x18__SqrtOverflow(uint256 x);\\n\\n/// @notice Emitted when subtraction underflows UD60x18.\\nerror PRBMathUD60x18__SubUnderflow(uint256 x, uint256 y);\\n\\n/// @dev Common mathematical functions used in both PRBMathSD59x18 and PRBMathUD60x18. Note that this shared library\\n/// does not always assume the signed 59.18-decimal fixed-point or the unsigned 60.18-decimal fixed-point\\n/// representation. When it does not, it is explicitly mentioned in the NatSpec documentation.\\nlibrary PRBMath {\\n /// STRUCTS ///\\n\\n struct SD59x18 {\\n int256 value;\\n }\\n\\n struct UD60x18 {\\n uint256 value;\\n }\\n\\n /// STORAGE ///\\n\\n /// @dev How many trailing decimals can be represented.\\n uint256 internal constant SCALE = 1e18;\\n\\n /// @dev Largest power of two divisor of SCALE.\\n uint256 internal constant SCALE_LPOTD = 262144;\\n\\n /// @dev SCALE inverted mod 2^256.\\n uint256 internal constant SCALE_INVERSE =\\n 78156646155174841979727994598816262306175212592076161876661_508869554232690281;\\n\\n /// FUNCTIONS ///\\n\\n /// @notice Calculates the binary exponent of x using the binary fraction method.\\n /// @dev Has to use 192.64-bit fixed-point numbers.\\n /// See https://ethereum.stackexchange.com/a/96594/24693.\\n /// @param x The exponent as an unsigned 192.64-bit fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp2(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n // Start from 0.5 in the 192.64-bit fixed-point format.\\n result = 0x800000000000000000000000000000000000000000000000;\\n\\n // Multiply the result by root(2, 2^-i) when the bit at position i is 1. None of the intermediary results overflows\\n // because the initial result is 2^191 and all magic factors are less than 2^65.\\n if (x & 0x8000000000000000 > 0) {\\n result = (result * 0x16A09E667F3BCC909) >> 64;\\n }\\n if (x & 0x4000000000000000 > 0) {\\n result = (result * 0x1306FE0A31B7152DF) >> 64;\\n }\\n if (x & 0x2000000000000000 > 0) {\\n result = (result * 0x1172B83C7D517ADCE) >> 64;\\n }\\n if (x & 0x1000000000000000 > 0) {\\n result = (result * 0x10B5586CF9890F62A) >> 64;\\n }\\n if (x & 0x800000000000000 > 0) {\\n result = (result * 0x1059B0D31585743AE) >> 64;\\n }\\n if (x & 0x400000000000000 > 0) {\\n result = (result * 0x102C9A3E778060EE7) >> 64;\\n }\\n if (x & 0x200000000000000 > 0) {\\n result = (result * 0x10163DA9FB33356D8) >> 64;\\n }\\n if (x & 0x100000000000000 > 0) {\\n result = (result * 0x100B1AFA5ABCBED61) >> 64;\\n }\\n if (x & 0x80000000000000 > 0) {\\n result = (result * 0x10058C86DA1C09EA2) >> 64;\\n }\\n if (x & 0x40000000000000 > 0) {\\n result = (result * 0x1002C605E2E8CEC50) >> 64;\\n }\\n if (x & 0x20000000000000 > 0) {\\n result = (result * 0x100162F3904051FA1) >> 64;\\n }\\n if (x & 0x10000000000000 > 0) {\\n result = (result * 0x1000B175EFFDC76BA) >> 64;\\n }\\n if (x & 0x8000000000000 > 0) {\\n result = (result * 0x100058BA01FB9F96D) >> 64;\\n }\\n if (x & 0x4000000000000 > 0) {\\n result = (result * 0x10002C5CC37DA9492) >> 64;\\n }\\n if (x & 0x2000000000000 > 0) {\\n result = (result * 0x1000162E525EE0547) >> 64;\\n }\\n if (x & 0x1000000000000 > 0) {\\n result = (result * 0x10000B17255775C04) >> 64;\\n }\\n if (x & 0x800000000000 > 0) {\\n result = (result * 0x1000058B91B5BC9AE) >> 64;\\n }\\n if (x & 0x400000000000 > 0) {\\n result = (result * 0x100002C5C89D5EC6D) >> 64;\\n }\\n if (x & 0x200000000000 > 0) {\\n result = (result * 0x10000162E43F4F831) >> 64;\\n }\\n if (x & 0x100000000000 > 0) {\\n result = (result * 0x100000B1721BCFC9A) >> 64;\\n }\\n if (x & 0x80000000000 > 0) {\\n result = (result * 0x10000058B90CF1E6E) >> 64;\\n }\\n if (x & 0x40000000000 > 0) {\\n result = (result * 0x1000002C5C863B73F) >> 64;\\n }\\n if (x & 0x20000000000 > 0) {\\n result = (result * 0x100000162E430E5A2) >> 64;\\n }\\n if (x & 0x10000000000 > 0) {\\n result = (result * 0x1000000B172183551) >> 64;\\n }\\n if (x & 0x8000000000 > 0) {\\n result = (result * 0x100000058B90C0B49) >> 64;\\n }\\n if (x & 0x4000000000 > 0) {\\n result = (result * 0x10000002C5C8601CC) >> 64;\\n }\\n if (x & 0x2000000000 > 0) {\\n result = (result * 0x1000000162E42FFF0) >> 64;\\n }\\n if (x & 0x1000000000 > 0) {\\n result = (result * 0x10000000B17217FBB) >> 64;\\n }\\n if (x & 0x800000000 > 0) {\\n result = (result * 0x1000000058B90BFCE) >> 64;\\n }\\n if (x & 0x400000000 > 0) {\\n result = (result * 0x100000002C5C85FE3) >> 64;\\n }\\n if (x & 0x200000000 > 0) {\\n result = (result * 0x10000000162E42FF1) >> 64;\\n }\\n if (x & 0x100000000 > 0) {\\n result = (result * 0x100000000B17217F8) >> 64;\\n }\\n if (x & 0x80000000 > 0) {\\n result = (result * 0x10000000058B90BFC) >> 64;\\n }\\n if (x & 0x40000000 > 0) {\\n result = (result * 0x1000000002C5C85FE) >> 64;\\n }\\n if (x & 0x20000000 > 0) {\\n result = (result * 0x100000000162E42FF) >> 64;\\n }\\n if (x & 0x10000000 > 0) {\\n result = (result * 0x1000000000B17217F) >> 64;\\n }\\n if (x & 0x8000000 > 0) {\\n result = (result * 0x100000000058B90C0) >> 64;\\n }\\n if (x & 0x4000000 > 0) {\\n result = (result * 0x10000000002C5C860) >> 64;\\n }\\n if (x & 0x2000000 > 0) {\\n result = (result * 0x1000000000162E430) >> 64;\\n }\\n if (x & 0x1000000 > 0) {\\n result = (result * 0x10000000000B17218) >> 64;\\n }\\n if (x & 0x800000 > 0) {\\n result = (result * 0x1000000000058B90C) >> 64;\\n }\\n if (x & 0x400000 > 0) {\\n result = (result * 0x100000000002C5C86) >> 64;\\n }\\n if (x & 0x200000 > 0) {\\n result = (result * 0x10000000000162E43) >> 64;\\n }\\n if (x & 0x100000 > 0) {\\n result = (result * 0x100000000000B1721) >> 64;\\n }\\n if (x & 0x80000 > 0) {\\n result = (result * 0x10000000000058B91) >> 64;\\n }\\n if (x & 0x40000 > 0) {\\n result = (result * 0x1000000000002C5C8) >> 64;\\n }\\n if (x & 0x20000 > 0) {\\n result = (result * 0x100000000000162E4) >> 64;\\n }\\n if (x & 0x10000 > 0) {\\n result = (result * 0x1000000000000B172) >> 64;\\n }\\n if (x & 0x8000 > 0) {\\n result = (result * 0x100000000000058B9) >> 64;\\n }\\n if (x & 0x4000 > 0) {\\n result = (result * 0x10000000000002C5D) >> 64;\\n }\\n if (x & 0x2000 > 0) {\\n result = (result * 0x1000000000000162E) >> 64;\\n }\\n if (x & 0x1000 > 0) {\\n result = (result * 0x10000000000000B17) >> 64;\\n }\\n if (x & 0x800 > 0) {\\n result = (result * 0x1000000000000058C) >> 64;\\n }\\n if (x & 0x400 > 0) {\\n result = (result * 0x100000000000002C6) >> 64;\\n }\\n if (x & 0x200 > 0) {\\n result = (result * 0x10000000000000163) >> 64;\\n }\\n if (x & 0x100 > 0) {\\n result = (result * 0x100000000000000B1) >> 64;\\n }\\n if (x & 0x80 > 0) {\\n result = (result * 0x10000000000000059) >> 64;\\n }\\n if (x & 0x40 > 0) {\\n result = (result * 0x1000000000000002C) >> 64;\\n }\\n if (x & 0x20 > 0) {\\n result = (result * 0x10000000000000016) >> 64;\\n }\\n if (x & 0x10 > 0) {\\n result = (result * 0x1000000000000000B) >> 64;\\n }\\n if (x & 0x8 > 0) {\\n result = (result * 0x10000000000000006) >> 64;\\n }\\n if (x & 0x4 > 0) {\\n result = (result * 0x10000000000000003) >> 64;\\n }\\n if (x & 0x2 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n if (x & 0x1 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n\\n // We're doing two things at the same time:\\n //\\n // 1. Multiply the result by 2^n + 1, where \\\"2^n\\\" is the integer part and the one is added to account for\\n // the fact that we initially set the result to 0.5. This is accomplished by subtracting from 191\\n // rather than 192.\\n // 2. Convert the result to the unsigned 60.18-decimal fixed-point format.\\n //\\n // This works because 2^(191-ip) = 2^ip / 2^191, where \\\"ip\\\" is the integer part \\\"2^n\\\".\\n result *= SCALE;\\n result >>= (191 - (x >> 64));\\n }\\n }\\n\\n /// @notice Finds the zero-based index of the first one in the binary representation of x.\\n /// @dev See the note on msb in the \\\"Find First Set\\\" Wikipedia article https://en.wikipedia.org/wiki/Find_first_set\\n /// @param x The uint256 number for which to find the index of the most significant bit.\\n /// @return msb The index of the most significant bit as an uint256.\\n function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\\n if (x >= 2**128) {\\n x >>= 128;\\n msb += 128;\\n }\\n if (x >= 2**64) {\\n x >>= 64;\\n msb += 64;\\n }\\n if (x >= 2**32) {\\n x >>= 32;\\n msb += 32;\\n }\\n if (x >= 2**16) {\\n x >>= 16;\\n msb += 16;\\n }\\n if (x >= 2**8) {\\n x >>= 8;\\n msb += 8;\\n }\\n if (x >= 2**4) {\\n x >>= 4;\\n msb += 4;\\n }\\n if (x >= 2**2) {\\n x >>= 2;\\n msb += 2;\\n }\\n if (x >= 2**1) {\\n // No need to shift x any more.\\n msb += 1;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.\\n ///\\n /// Requirements:\\n /// - The denominator cannot be zero.\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The multiplicand as an uint256.\\n /// @param y The multiplier as an uint256.\\n /// @param denominator The divisor as an uint256.\\n /// @return result The result as an uint256.\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n unchecked {\\n result = prod0 / denominator;\\n }\\n return result;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n if (prod1 >= denominator) {\\n revert PRBMath__MulDivOverflow(prod1, denominator);\\n }\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n unchecked {\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 lpotdod = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by lpotdod.\\n denominator := div(denominator, lpotdod)\\n\\n // Divide [prod1 prod0] by lpotdod.\\n prod0 := div(prod0, lpotdod)\\n\\n // Flip lpotdod such that it is 2^256 / lpotdod. If lpotdod is zero, then it becomes one.\\n lpotdod := add(div(sub(0, lpotdod), lpotdod), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * lpotdod;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f71e18) with full precision.\\n ///\\n /// @dev Variant of \\\"mulDiv\\\" with constant folding, i.e. in which the denominator is always 1e18. Before returning the\\n /// final result, we add 1 if (x * y) % SCALE >= HALF_SCALE. Without this, 6.6e-19 would be truncated to 0 instead of\\n /// being rounded to 1e-18. See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717.\\n ///\\n /// Requirements:\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - The body is purposely left uncommented; see the NatSpec comments in \\\"PRBMath.mulDiv\\\" to understand how this works.\\n /// - It is assumed that the result can never be type(uint256).max when x and y solve the following two equations:\\n /// 1. x * y = type(uint256).max * SCALE\\n /// 2. (x * y) % SCALE >= SCALE / 2\\n ///\\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function mulDivFixedPoint(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n uint256 prod0;\\n uint256 prod1;\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n if (prod1 >= SCALE) {\\n revert PRBMath__MulDivFixedPointOverflow(prod1);\\n }\\n\\n uint256 remainder;\\n uint256 roundUpUnit;\\n assembly {\\n remainder := mulmod(x, y, SCALE)\\n roundUpUnit := gt(remainder, 499999999999999999)\\n }\\n\\n if (prod1 == 0) {\\n unchecked {\\n result = (prod0 / SCALE) + roundUpUnit;\\n return result;\\n }\\n }\\n\\n assembly {\\n result := add(\\n mul(\\n or(\\n div(sub(prod0, remainder), SCALE_LPOTD),\\n mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, SCALE_LPOTD), SCALE_LPOTD), 1))\\n ),\\n SCALE_INVERSE\\n ),\\n roundUpUnit\\n )\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev An extension of \\\"mulDiv\\\" for signed numbers. Works by computing the signs and the absolute values separately.\\n ///\\n /// Requirements:\\n /// - None of the inputs can be type(int256).min.\\n /// - The result must fit within int256.\\n ///\\n /// @param x The multiplicand as an int256.\\n /// @param y The multiplier as an int256.\\n /// @param denominator The divisor as an int256.\\n /// @return result The result as an int256.\\n function mulDivSigned(\\n int256 x,\\n int256 y,\\n int256 denominator\\n ) internal pure returns (int256 result) {\\n if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {\\n revert PRBMath__MulDivSignedInputTooSmall();\\n }\\n\\n // Get hold of the absolute values of x, y and the denominator.\\n uint256 ax;\\n uint256 ay;\\n uint256 ad;\\n unchecked {\\n ax = x < 0 ? uint256(-x) : uint256(x);\\n ay = y < 0 ? uint256(-y) : uint256(y);\\n ad = denominator < 0 ? uint256(-denominator) : uint256(denominator);\\n }\\n\\n // Compute the absolute value of (x*y)\\u00f7denominator. The result must fit within int256.\\n uint256 rAbs = mulDiv(ax, ay, ad);\\n if (rAbs > uint256(type(int256).max)) {\\n revert PRBMath__MulDivSignedOverflow(rAbs);\\n }\\n\\n // Get the signs of x, y and the denominator.\\n uint256 sx;\\n uint256 sy;\\n uint256 sd;\\n assembly {\\n sx := sgt(x, sub(0, 1))\\n sy := sgt(y, sub(0, 1))\\n sd := sgt(denominator, sub(0, 1))\\n }\\n\\n // XOR over sx, sy and sd. This is checking whether there are one or three negative signs in the inputs.\\n // If yes, the result should be negative.\\n result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs);\\n }\\n\\n /// @notice Calculates the square root of x, rounding down.\\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The uint256 number for which to calculate the square root.\\n /// @return result The result as an uint256.\\n function sqrt(uint256 x) internal pure returns (uint256 result) {\\n if (x == 0) {\\n return 0;\\n }\\n\\n // Set the initial guess to the closest power of two that is higher than x.\\n uint256 xAux = uint256(x);\\n result = 1;\\n if (xAux >= 0x100000000000000000000000000000000) {\\n xAux >>= 128;\\n result <<= 64;\\n }\\n if (xAux >= 0x10000000000000000) {\\n xAux >>= 64;\\n result <<= 32;\\n }\\n if (xAux >= 0x100000000) {\\n xAux >>= 32;\\n result <<= 16;\\n }\\n if (xAux >= 0x10000) {\\n xAux >>= 16;\\n result <<= 8;\\n }\\n if (xAux >= 0x100) {\\n xAux >>= 8;\\n result <<= 4;\\n }\\n if (xAux >= 0x10) {\\n xAux >>= 4;\\n result <<= 2;\\n }\\n if (xAux >= 0x8) {\\n result <<= 1;\\n }\\n\\n // The operations can never overflow because the result is max 2^127 when it enters this block.\\n unchecked {\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1; // Seven iterations should be enough\\n uint256 roundedDownResult = x / result;\\n return result >= roundedDownResult ? roundedDownResult : result;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x62cbabae4910e168e99b9c2c3e3b5c9c7ad5e7abd961dcc63b7ea3d83d8ea87e\",\"license\":\"Unlicense\"}},\"version\":1}", + "metadata": "{\"compiler\":{\"version\":\"0.8.16+commit.07a7930e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_baseWeightCurrency\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBOperatorStore\",\"name\":\"_operatorStore\",\"type\":\"address\"},{\"internalType\":\"contract IJBProjects\",\"name\":\"_projects\",\"type\":\"address\"},{\"internalType\":\"contract IJBDirectory\",\"name\":\"_directory\",\"type\":\"address\"},{\"internalType\":\"contract IJBSplitsStore\",\"name\":\"_splitsStore\",\"type\":\"address\"},{\"internalType\":\"contract IJBPrices\",\"name\":\"_prices\",\"type\":\"address\"},{\"internalType\":\"contract IJBSingleTokenPaymentTerminalStore\",\"name\":\"_store\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"FEE_TOO_HIGH\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INADEQUATE_DISTRIBUTION_AMOUNT\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INADEQUATE_RECLAIM_AMOUNT\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INADEQUATE_TOKEN_COUNT\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NO_MSG_VALUE_ALLOWED\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PAY_TO_ZERO_ADDRESS\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"prod1\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"denominator\",\"type\":\"uint256\"}],\"name\":\"PRBMath__MulDivOverflow\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PROJECT_TERMINAL_MISMATCH\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"REDEEM_TO_ZERO_ADDRESS\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TERMINAL_IN_SPLIT_ZERO_ADDRESS\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TERMINAL_TOKENS_INCOMPATIBLE\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UNAUTHORIZED\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"refundedFees\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AddToBalance\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IJBPayDelegate\",\"name\":\"delegate\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"currentFundingCycleConfiguration\",\"type\":\"uint256\"},{\"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\"},{\"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\":\"forwardedAmount\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"projectTokenCount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"preferClaimedTokens\",\"type\":\"bool\"},{\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"struct JBDidPayData\",\"name\":\"data\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"delegatedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"DelegateDidPay\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IJBRedemptionDelegate\",\"name\":\"delegate\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"currentFundingCycleConfiguration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"projectTokenCount\",\"type\":\"uint256\"},{\"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\":\"reclaimedAmount\",\"type\":\"tuple\"},{\"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\":\"forwardedAmount\",\"type\":\"tuple\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"struct JBDidRedeemData\",\"name\":\"data\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"delegatedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"DelegateDidRedeem\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleConfiguration\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleNumber\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"distributedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"beneficiaryDistributionAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"DistributePayouts\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"domain\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"group\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"preferClaimed\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"preferAddToBalance\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"percent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"lockedUntil\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBSplitAllocator\",\"name\":\"allocator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"struct JBSplit\",\"name\":\"split\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"netAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"DistributeToPayoutSplit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"feeProjectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"reason\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"FeeReverted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"feeDiscount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"HoldFee\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"contract IJBPaymentTerminal\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Migrate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleConfiguration\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleNumber\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"beneficiaryTokenCount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Pay\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"preferClaimed\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"preferAddToBalance\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"percent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"lockedUntil\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBSplitAllocator\",\"name\":\"allocator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"struct JBSplit\",\"name\":\"split\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"reason\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"PayoutReverted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"wasHeld\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"ProcessFee\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleConfiguration\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleNumber\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenCount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"reclaimedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"RedeemTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"refundedFees\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"leftoverAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"RefundHeldFees\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"SetFee\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IJBFeeGauge\",\"name\":\"feeGauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"SetFeeGauge\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"addrs\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"flag\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"SetFeelessAddress\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleConfiguration\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleNumber\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"distributedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"netDistributedamount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"UseAllowance\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"}],\"name\":\"acceptsToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"addToBalanceOf\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_shouldRefundHeldFees\",\"type\":\"bool\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"addToBalanceOf\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"baseWeightCurrency\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currency\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"currencyForToken\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"}],\"name\":\"currentEthOverflowOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"decimalsForToken\",\"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\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_currency\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_minReturnedTokens\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"distributePayoutsOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"netLeftoverDistributionAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"feeGauge\",\"outputs\":[{\"internalType\":\"contract IJBFeeGauge\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"}],\"name\":\"heldFeesOf\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"fee\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"feeDiscount\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"internalType\":\"struct JBFee[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isFeelessAddress\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBPaymentTerminal\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"migrate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"operatorStore\",\"outputs\":[{\"internalType\":\"contract IJBOperatorStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_minReturnedTokens\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"_preferClaimedTokens\",\"type\":\"bool\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"pay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"payoutSplitsGroup\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"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\"}],\"name\":\"processFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"projects\",\"outputs\":[{\"internalType\":\"contract IJBProjects\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_holder\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_tokenCount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_minReturnedTokens\",\"type\":\"uint256\"},{\"internalType\":\"address payable\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"redeemTokensOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"reclaimAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_fee\",\"type\":\"uint256\"}],\"name\":\"setFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IJBFeeGauge\",\"name\":\"_feeGauge\",\"type\":\"address\"}],\"name\":\"setFeeGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_flag\",\"type\":\"bool\"}],\"name\":\"setFeelessAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"splitsStore\",\"outputs\":[{\"internalType\":\"contract IJBSplitsStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"store\",\"outputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminalStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_currency\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_minReturnedTokens\",\"type\":\"uint256\"},{\"internalType\":\"address payable\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"useAllowanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"netDistributedAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Inherits from - JBPayoutRedemptionPaymentTerminal3_1: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\",\"kind\":\"dev\",\"methods\":{\"acceptsToken(address,uint256)\":{\"params\":{\"_projectId\":\"The project ID to check for token acceptance.\",\"_token\":\"The token to check if this terminal accepts or not.\"},\"returns\":{\"_0\":\"The flag.\"}},\"addToBalanceOf(uint256,uint256,address,bool,string,bytes)\":{\"params\":{\"_amount\":\"The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\",\"_memo\":\"A memo to pass along to the emitted event.\",\"_metadata\":\"Extra data to pass along to the emitted event.\",\"_projectId\":\"The ID of the project to which the funds received belong.\",\"_shouldRefundHeldFees\":\"A flag indicating if held fees should be refunded based on the amount being added.\",\"_token\":\"The token being paid. This terminal ignores this property since it only manages one currency. \"}},\"addToBalanceOf(uint256,uint256,address,string,bytes)\":{\"params\":{\"_amount\":\"The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\",\"_memo\":\"A memo to pass along to the emitted event.\",\"_metadata\":\"Extra data to pass along to the emitted event.\",\"_projectId\":\"The ID of the project to which the funds received belong.\",\"_token\":\"The token being paid. This terminal ignores this property since it only manages one currency. \"}},\"constructor\":{\"params\":{\"_baseWeightCurrency\":\"The currency to base token issuance on.\",\"_directory\":\"A contract storing directories of terminals and controllers for each project.\",\"_operatorStore\":\"A contract storing operator assignments.\",\"_owner\":\"The address that will own this contract.\",\"_prices\":\"A contract that exposes price feeds.\",\"_projects\":\"A contract which mints ERC-721's that represent project ownership and transfers.\",\"_splitsStore\":\"A contract that stores splits for each project.\",\"_store\":\"A contract that stores the terminal's data.\"}},\"currencyForToken(address)\":{\"params\":{\"_token\":\"The token to check for the currency of.\"},\"returns\":{\"_0\":\"The currency index.\"}},\"currentEthOverflowOf(uint256)\":{\"details\":\"The current overflow is represented as a fixed point number with 18 decimals.\",\"params\":{\"_projectId\":\"The ID of the project to get overflow for.\"},\"returns\":{\"_0\":\"The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\"}},\"decimalsForToken(address)\":{\"params\":{\"_token\":\"The token to check for the decimals of.\"},\"returns\":{\"_0\":\"The number of decimals for the token.\"}},\"distributePayoutsOf(uint256,uint256,uint256,address,uint256,bytes)\":{\"details\":\"Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\",\"params\":{\"_amount\":\"The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\",\"_currency\":\"The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\",\"_metadata\":\"Bytes to send along to the emitted event, if provided.\",\"_minReturnedTokens\":\"The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\",\"_projectId\":\"The ID of the project having its payouts distributed.\",\"_token\":\"The token being distributed. This terminal ignores this property since it only manages one token. \"},\"returns\":{\"netLeftoverDistributionAmount\":\"The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\"}},\"heldFeesOf(uint256)\":{\"params\":{\"_projectId\":\"The ID of the project for which fees are being held.\"},\"returns\":{\"_0\":\"An array of fees that are being held.\"}},\"migrate(uint256,address)\":{\"details\":\"Only a project's owner or a designated operator can migrate it.\",\"params\":{\"_projectId\":\"The ID of the project being migrated.\",\"_to\":\"The terminal contract that will gain the project's funds.\"},\"returns\":{\"balance\":\"The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pay(uint256,uint256,address,address,uint256,bool,string,bytes)\":{\"params\":{\"_amount\":\"The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\",\"_beneficiary\":\"The address to mint tokens for and pass along to the funding cycle's data source and delegate.\",\"_memo\":\"A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\",\"_metadata\":\"Bytes to send along to the data source, delegate, and emitted event, if provided.\",\"_minReturnedTokens\":\"The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\",\"_preferClaimedTokens\":\"A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\",\"_projectId\":\"The ID of the project being paid.\",\"_token\":\"The token being paid. This terminal ignores this property since it only manages one token. \"},\"returns\":{\"_0\":\"The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\"}},\"processFees(uint256)\":{\"details\":\"Only a project owner, an operator, or the contract's owner can process held fees.\",\"params\":{\"_projectId\":\"The ID of the project whos held fees should be processed.\"}},\"redeemTokensOf(address,uint256,uint256,address,uint256,address,string,bytes)\":{\"details\":\"Only a token holder or a designated operator can redeem its tokens.\",\"params\":{\"_beneficiary\":\"The address to send the terminal tokens to.\",\"_holder\":\"The account to redeem tokens for.\",\"_memo\":\"A memo to pass along to the emitted event.\",\"_metadata\":\"Bytes to send along to the data source, delegate, and emitted event, if provided.\",\"_minReturnedTokens\":\"The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\",\"_projectId\":\"The ID of the project to which the tokens being redeemed belong.\",\"_token\":\"The token being reclaimed. This terminal ignores this property since it only manages one token. \",\"_tokenCount\":\"The number of project tokens to redeem, as a fixed point number with 18 decimals.\"},\"returns\":{\"reclaimAmount\":\"The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"setFee(uint256)\":{\"details\":\"Only the owner of this contract can change the fee.\",\"params\":{\"_fee\":\"The new fee, out of MAX_FEE.\"}},\"setFeeGauge(address)\":{\"details\":\"Only the owner of this contract can change the fee gauge.\",\"params\":{\"_feeGauge\":\"The new fee gauge.\"}},\"setFeelessAddress(address,bool)\":{\"details\":\"Only the owner of this contract can set addresses as feeless.\",\"params\":{\"_address\":\"The address that can be paid towards while still bypassing fees.\",\"_flag\":\"A flag indicating whether the terminal should be feeless or not.\"}},\"supportsInterface(bytes4)\":{\"details\":\" See {IERC165-supportsInterface}.\",\"params\":{\"_interfaceId\":\"The ID of the interface to check for adherance to.\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"useAllowanceOf(uint256,uint256,uint256,address,uint256,address,string,bytes)\":{\"details\":\"Only a project's owner or a designated operator can use its allowance.Incurs the protocol fee.\",\"params\":{\"_amount\":\"The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\",\"_beneficiary\":\"The address to send the funds to.\",\"_currency\":\"The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\",\"_memo\":\"A memo to pass along to the emitted event.\",\"_metadata\":\"Bytes to send along to the emitted event, if provided.\",\"_minReturnedTokens\":\"The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\",\"_projectId\":\"The ID of the project to use the allowance of.\",\"_token\":\"The token being distributed. This terminal ignores this property since it only manages one token. \"},\"returns\":{\"netDistributedAmount\":\"The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\"}}},\"version\":1},\"userdoc\":{\"errors\":{\"PRBMath__MulDivOverflow(uint256,uint256)\":[{\"notice\":\"Emitted when the result overflows uint256.\"}]},\"kind\":\"user\",\"methods\":{\"acceptsToken(address,uint256)\":{\"notice\":\"A flag indicating if this terminal accepts the specified token.\"},\"addToBalanceOf(uint256,uint256,address,bool,string,bytes)\":{\"notice\":\"Receives funds belonging to the specified project.\"},\"addToBalanceOf(uint256,uint256,address,string,bytes)\":{\"notice\":\"Receives funds belonging to the specified project.\"},\"baseWeightCurrency()\":{\"notice\":\"The currency to base token issuance on.\"},\"currency()\":{\"notice\":\"The currency to use when resolving price feeds for this terminal.\"},\"currencyForToken(address)\":{\"notice\":\"The currency that should be used for the specified token.\"},\"currentEthOverflowOf(uint256)\":{\"notice\":\"Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\"},\"decimals()\":{\"notice\":\"The number of decimals the token fixed point amounts are expected to have.\"},\"decimalsForToken(address)\":{\"notice\":\"The decimals that should be used in fixed number accounting for the specified token.\"},\"directory()\":{\"notice\":\"The directory of terminals and controllers for projects.\"},\"distributePayoutsOf(uint256,uint256,uint256,address,uint256,bytes)\":{\"notice\":\"Distributes payouts for a project with the distribution limit of its current funding cycle.\"},\"fee()\":{\"notice\":\"The platform fee percent.\"},\"feeGauge()\":{\"notice\":\"The data source that returns a discount to apply to a project's fee.\"},\"heldFeesOf(uint256)\":{\"notice\":\"The fees that are currently being held to be processed later for each project.\"},\"isFeelessAddress(address)\":{\"notice\":\"Addresses that can be paid towards from this terminal without incurring a fee.\"},\"migrate(uint256,address)\":{\"notice\":\"Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\"},\"operatorStore()\":{\"notice\":\" A contract storing operator assignments.\"},\"pay(uint256,uint256,address,address,uint256,bool,string,bytes)\":{\"notice\":\"Contribute tokens to a project.\"},\"payoutSplitsGroup()\":{\"notice\":\"The group that payout splits coming from this terminal are identified by.\"},\"prices()\":{\"notice\":\"The contract that exposes price feeds.\"},\"processFees(uint256)\":{\"notice\":\"Process any fees that are being held for the project.\"},\"projects()\":{\"notice\":\"Mints ERC-721's that represent project ownership and transfers.\"},\"redeemTokensOf(address,uint256,uint256,address,uint256,address,string,bytes)\":{\"notice\":\"Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\"},\"setFee(uint256)\":{\"notice\":\"Allows the fee to be updated.\"},\"setFeeGauge(address)\":{\"notice\":\"Allows the fee gauge to be updated.\"},\"setFeelessAddress(address,bool)\":{\"notice\":\"Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\"},\"splitsStore()\":{\"notice\":\"The contract that stores splits for each project.\"},\"store()\":{\"notice\":\"The contract that stores and manages the terminal's data.\"},\"supportsInterface(bytes4)\":{\"notice\":\"Indicates if this contract adheres to the specified interface.\"},\"token()\":{\"notice\":\"The token that this terminal accepts.\"},\"useAllowanceOf(uint256,uint256,uint256,address,uint256,address,string,bytes)\":{\"notice\":\"Allows a project to send funds from its overflow up to the preconfigured allowance.\"}},\"notice\":\"Manages all inflows and outflows of ETH funds into the protocol ecosystem.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/JBETHPaymentTerminal3_1.sol\":\"JBETHPaymentTerminal3_1\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0x24e0364e503a9bbde94c715d26573a76f14cd2a202d45f96f52134ab806b67b9\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool _approved) external;\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x516a22876c1fab47f49b1bc22b4614491cd05338af8bd2e7b382da090a079990\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3777e696b62134e6177440dbe6e6601c0c156a443f57167194b67e75527439de\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165Checker.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Library used to query support of an interface declared via {IERC165}.\\n *\\n * Note that these functions return the actual result of the query: they do not\\n * `revert` if an interface is not supported. It is up to the caller to decide\\n * what to do in these cases.\\n */\\nlibrary ERC165Checker {\\n // As per the EIP-165 spec, no interface should ever match 0xffffffff\\n bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;\\n\\n /**\\n * @dev Returns true if `account` supports the {IERC165} interface,\\n */\\n function supportsERC165(address account) internal view returns (bool) {\\n // Any contract that implements ERC165 must explicitly indicate support of\\n // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid\\n return\\n _supportsERC165Interface(account, type(IERC165).interfaceId) &&\\n !_supportsERC165Interface(account, _INTERFACE_ID_INVALID);\\n }\\n\\n /**\\n * @dev Returns true if `account` supports the interface defined by\\n * `interfaceId`. Support for {IERC165} itself is queried automatically.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {\\n // query support of both ERC165 as per the spec and support of _interfaceId\\n return supportsERC165(account) && _supportsERC165Interface(account, interfaceId);\\n }\\n\\n /**\\n * @dev Returns a boolean array where each value corresponds to the\\n * interfaces passed in and whether they're supported or not. This allows\\n * you to batch check interfaces for a contract where your expectation\\n * is that some interfaces may not be supported.\\n *\\n * See {IERC165-supportsInterface}.\\n *\\n * _Available since v3.4._\\n */\\n function getSupportedInterfaces(address account, bytes4[] memory interfaceIds)\\n internal\\n view\\n returns (bool[] memory)\\n {\\n // an array of booleans corresponding to interfaceIds and whether they're supported or not\\n bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);\\n\\n // query support of ERC165 itself\\n if (supportsERC165(account)) {\\n // query support of each interface in interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n interfaceIdsSupported[i] = _supportsERC165Interface(account, interfaceIds[i]);\\n }\\n }\\n\\n return interfaceIdsSupported;\\n }\\n\\n /**\\n * @dev Returns true if `account` supports all the interfaces defined in\\n * `interfaceIds`. Support for {IERC165} itself is queried automatically.\\n *\\n * Batch-querying can lead to gas savings by skipping repeated checks for\\n * {IERC165} support.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {\\n // query support of ERC165 itself\\n if (!supportsERC165(account)) {\\n return false;\\n }\\n\\n // query support of each interface in _interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n if (!_supportsERC165Interface(account, interfaceIds[i])) {\\n return false;\\n }\\n }\\n\\n // all interfaces supported\\n return true;\\n }\\n\\n /**\\n * @notice Query if a contract implements an interface, does not check ERC165 support\\n * @param account The address of the contract to query for support of an interface\\n * @param interfaceId The interface identifier, as specified in ERC-165\\n * @return true if the contract at account indicates support of the interface with\\n * identifier interfaceId, false otherwise\\n * @dev Assumes that account contains a contract that supports ERC165, otherwise\\n * the behavior of this method is undefined. This precondition can be checked\\n * with {supportsERC165}.\\n * Interface identification is specified in ERC-165.\\n */\\n function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) {\\n bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);\\n (bool success, bytes memory result) = account.staticcall{gas: 30000}(encodedParams);\\n if (result.length < 32) return false;\\n return success && abi.decode(result, (bool));\\n }\\n}\\n\",\"keccak256\":\"0xf7291d7213336b00ee7edbf7cd5034778dd7b0bda2a7489e664f1e5cacc6c24e\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"@paulrberg/contracts/math/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\nimport \\\"prb-math/contracts/PRBMath.sol\\\";\\n\",\"keccak256\":\"0x42821345981bc0434a90ba2268a2f5278dfe9e38166981d72fc7f3b776a29495\",\"license\":\"Unlicense\"},\"contracts/JBETHPaymentTerminal3_1.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport '@openzeppelin/contracts/utils/Address.sol';\\nimport './abstract/JBPayoutRedemptionPaymentTerminal3_1.sol';\\nimport './libraries/JBSplitsGroups.sol';\\n\\n/**\\n @notice\\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\\n\\n @dev\\n Inherits from -\\n JBPayoutRedemptionPaymentTerminal3_1: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\\n*/\\ncontract JBETHPaymentTerminal3_1 is JBPayoutRedemptionPaymentTerminal3_1 {\\n //*********************************************************************//\\n // -------------------------- internal views ------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Checks the balance of tokens in this contract.\\n\\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\\n */\\n function _balance() internal view override returns (uint256) {\\n return address(this).balance;\\n }\\n\\n //*********************************************************************//\\n // -------------------------- constructor ---------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @param _baseWeightCurrency The currency to base token issuance on.\\n @param _operatorStore A contract storing operator assignments.\\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\\n @param _directory A contract storing directories of terminals and controllers for each project.\\n @param _splitsStore A contract that stores splits for each project.\\n @param _prices A contract that exposes price feeds.\\n @param _store A contract that stores the terminal's data.\\n @param _owner The address that will own this contract.\\n */\\n constructor(\\n uint256 _baseWeightCurrency,\\n IJBOperatorStore _operatorStore,\\n IJBProjects _projects,\\n IJBDirectory _directory,\\n IJBSplitsStore _splitsStore,\\n IJBPrices _prices,\\n IJBSingleTokenPaymentTerminalStore _store,\\n address _owner\\n )\\n JBPayoutRedemptionPaymentTerminal3_1(\\n JBTokens.GAS_TOKEN,\\n 18, // 18 decimals.\\n JBCurrencies.GAS_CURRENCY,\\n _baseWeightCurrency,\\n JBSplitsGroups.ETH_PAYOUT,\\n _operatorStore,\\n _projects,\\n _directory,\\n _splitsStore,\\n _prices,\\n _store,\\n _owner\\n )\\n // solhint-disable-next-line no-empty-blocks\\n {\\n\\n }\\n\\n //*********************************************************************//\\n // ---------------------- internal transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Transfers tokens.\\n\\n @param _from The address from which the transfer should originate.\\n @param _to The address to which the transfer should go.\\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\\n */\\n function _transferFrom(\\n address _from,\\n address payable _to,\\n uint256 _amount\\n ) internal override {\\n _from; // Prevents unused var compiler and natspec complaints.\\n\\n Address.sendValue(_to, _amount);\\n }\\n}\\n\",\"keccak256\":\"0x51cd7cb442d31c0cede341af67b5ed069d467a72cb812dad5c0763f51960bbe5\",\"license\":\"MIT\"},\"contracts/abstract/JBOperatable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport './../interfaces/IJBOperatable.sol';\\n\\n/** \\n @notice\\n Modifiers to allow access to functions based on the message sender's operator status.\\n\\n @dev\\n Adheres to -\\n IJBOperatable: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n*/\\nabstract contract JBOperatable is IJBOperatable {\\n //*********************************************************************//\\n // --------------------------- custom errors -------------------------- //\\n //*********************************************************************//\\n error UNAUTHORIZED();\\n\\n //*********************************************************************//\\n // ---------------------------- modifiers ---------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Only allows the speficied account or an operator of the account to proceed. \\n\\n @param _account The account to check for.\\n @param _domain The domain namespace to look for an operator within. \\n @param _permissionIndex The index of the permission to check for. \\n */\\n modifier requirePermission(\\n address _account,\\n uint256 _domain,\\n uint256 _permissionIndex\\n ) {\\n _requirePermission(_account, _domain, _permissionIndex);\\n _;\\n }\\n\\n /** \\n @notice\\n Only allows the speficied account, an operator of the account to proceed, or a truthy override flag. \\n\\n @param _account The account to check for.\\n @param _domain The domain namespace to look for an operator within. \\n @param _permissionIndex The index of the permission to check for. \\n @param _override A condition to force allowance for.\\n */\\n modifier requirePermissionAllowingOverride(\\n address _account,\\n uint256 _domain,\\n uint256 _permissionIndex,\\n bool _override\\n ) {\\n _requirePermissionAllowingOverride(_account, _domain, _permissionIndex, _override);\\n _;\\n }\\n\\n //*********************************************************************//\\n // ---------------- public immutable stored properties --------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n A contract storing operator assignments.\\n */\\n IJBOperatorStore public immutable override operatorStore;\\n\\n //*********************************************************************//\\n // -------------------------- constructor ---------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @param _operatorStore A contract storing operator assignments.\\n */\\n constructor(IJBOperatorStore _operatorStore) {\\n operatorStore = _operatorStore;\\n }\\n\\n //*********************************************************************//\\n // -------------------------- internal views ------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Require the message sender is either the account or has the specified permission.\\n\\n @param _account The account to allow.\\n @param _domain The domain namespace within which the permission index will be checked.\\n @param _permissionIndex The permission index that an operator must have within the specified domain to be allowed.\\n */\\n function _requirePermission(\\n address _account,\\n uint256 _domain,\\n uint256 _permissionIndex\\n ) internal view {\\n if (\\n msg.sender != _account &&\\n !operatorStore.hasPermission(msg.sender, _account, _domain, _permissionIndex) &&\\n !operatorStore.hasPermission(msg.sender, _account, 0, _permissionIndex)\\n ) revert UNAUTHORIZED();\\n }\\n\\n /** \\n @notice\\n Require the message sender is either the account, has the specified permission, or the override condition is true.\\n\\n @param _account The account to allow.\\n @param _domain The domain namespace within which the permission index will be checked.\\n @param _domain The permission index that an operator must have within the specified domain to be allowed.\\n @param _override The override condition to allow.\\n */\\n function _requirePermissionAllowingOverride(\\n address _account,\\n uint256 _domain,\\n uint256 _permissionIndex,\\n bool _override\\n ) internal view {\\n if (\\n !_override &&\\n msg.sender != _account &&\\n !operatorStore.hasPermission(msg.sender, _account, _domain, _permissionIndex) &&\\n !operatorStore.hasPermission(msg.sender, _account, 0, _permissionIndex)\\n ) revert UNAUTHORIZED();\\n }\\n}\\n\",\"keccak256\":\"0x9e62cac5c464eb973f881cf6c373b95aab31d2ddbeb048ee7ad82b5c9ab28add\",\"license\":\"MIT\"},\"contracts/abstract/JBPayoutRedemptionPaymentTerminal3_1.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport '@openzeppelin/contracts/access/Ownable.sol';\\nimport '@openzeppelin/contracts/utils/introspection/ERC165Checker.sol';\\nimport '@paulrberg/contracts/math/PRBMath.sol';\\nimport './../interfaces/IJBController.sol';\\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal3_1.sol';\\nimport './../libraries/JBConstants.sol';\\nimport './../libraries/JBCurrencies.sol';\\nimport './../libraries/JBFixedPointNumber.sol';\\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\\nimport './../libraries/JBOperations.sol';\\nimport './../libraries/JBTokens.sol';\\nimport './../structs/JBPayDelegateAllocation.sol';\\nimport './../structs/JBTokenAmount.sol';\\nimport './JBOperatable.sol';\\nimport './JBSingleTokenPaymentTerminal.sol';\\n\\n/**\\n @notice\\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\\n\\n @dev\\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\\n\\n @dev\\n Adheres to -\\n IJBPayoutRedemptionPaymentTerminal3_1: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n\\n @dev\\n Inherits from -\\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\\n*/\\nabstract contract JBPayoutRedemptionPaymentTerminal3_1 is\\n JBSingleTokenPaymentTerminal,\\n JBOperatable,\\n Ownable,\\n IJBPayoutRedemptionPaymentTerminal3_1\\n{\\n // A library that parses the packed funding cycle metadata into a friendlier format.\\n using JBFundingCycleMetadataResolver for JBFundingCycle;\\n\\n //*********************************************************************//\\n // --------------------------- custom errors ------------------------- //\\n //*********************************************************************//\\n error FEE_TOO_HIGH();\\n error INADEQUATE_DISTRIBUTION_AMOUNT();\\n error INADEQUATE_RECLAIM_AMOUNT();\\n error INADEQUATE_TOKEN_COUNT();\\n error NO_MSG_VALUE_ALLOWED();\\n error PAY_TO_ZERO_ADDRESS();\\n error PROJECT_TERMINAL_MISMATCH();\\n error REDEEM_TO_ZERO_ADDRESS();\\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\\n error TERMINAL_TOKENS_INCOMPATIBLE();\\n\\n //*********************************************************************//\\n // ---------------------------- modifiers ---------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n A modifier that verifies this terminal is a terminal of provided project ID.\\n */\\n modifier isTerminalOf(uint256 _projectId) {\\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\\n _;\\n }\\n\\n //*********************************************************************//\\n // --------------------- internal stored constants ------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Maximum fee that can be set for a funding cycle configuration.\\n\\n @dev\\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\\n */\\n uint256 internal constant _FEE_CAP = 50_000_000;\\n\\n /**\\n @notice\\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\\n */\\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\\n\\n //*********************************************************************//\\n // --------------------- internal stored properties ------------------ //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Fees that are being held to be processed later.\\n\\n _projectId The ID of the project for which fees are being held.\\n */\\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\\n\\n //*********************************************************************//\\n // ---------------- public immutable stored properties --------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Mints ERC-721's that represent project ownership and transfers.\\n */\\n IJBProjects public immutable override projects;\\n\\n /**\\n @notice\\n The directory of terminals and controllers for projects.\\n */\\n IJBDirectory public immutable override directory;\\n\\n /**\\n @notice\\n The contract that stores splits for each project.\\n */\\n IJBSplitsStore public immutable override splitsStore;\\n\\n /**\\n @notice\\n The contract that exposes price feeds.\\n */\\n IJBPrices public immutable override prices;\\n\\n /**\\n @notice\\n The contract that stores and manages the terminal's data.\\n */\\n IJBSingleTokenPaymentTerminalStore public immutable override store;\\n\\n /**\\n @notice\\n The currency to base token issuance on.\\n\\n @dev\\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\\n */\\n uint256 public immutable override baseWeightCurrency;\\n\\n /**\\n @notice\\n The group that payout splits coming from this terminal are identified by.\\n */\\n uint256 public immutable override payoutSplitsGroup;\\n\\n //*********************************************************************//\\n // --------------------- public stored properties -------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The platform fee percent.\\n\\n @dev\\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\\n */\\n uint256 public override fee = 25_000_000; // 2.5%\\n\\n /**\\n @notice\\n The data source that returns a discount to apply to a project's fee.\\n */\\n IJBFeeGauge public override feeGauge;\\n\\n /**\\n @notice\\n Addresses that can be paid towards from this terminal without incurring a fee.\\n\\n @dev\\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\\n\\n _address The address that can be paid toward.\\n */\\n mapping(address => bool) public override isFeelessAddress;\\n\\n //*********************************************************************//\\n // ------------------------- external views -------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\\n\\n @dev\\n The current overflow is represented as a fixed point number with 18 decimals.\\n\\n @param _projectId The ID of the project to get overflow for.\\n\\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\\n */\\n function currentEthOverflowOf(uint256 _projectId)\\n external\\n view\\n virtual\\n override\\n returns (uint256)\\n {\\n // Get this terminal's current overflow.\\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\\n\\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\\n uint256 _adjustedOverflow = (decimals == 18)\\n ? _overflow\\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\\n\\n // Return the amount converted to ETH.\\n return\\n (currency == JBCurrencies.GAS_CURRENCY)\\n ? _adjustedOverflow\\n : PRBMath.mulDiv(\\n _adjustedOverflow,\\n 10**decimals,\\n prices.priceFor(currency, JBCurrencies.GAS_CURRENCY, decimals)\\n );\\n }\\n\\n /**\\n @notice\\n The fees that are currently being held to be processed later for each project.\\n\\n @param _projectId The ID of the project for which fees are being held.\\n\\n @return An array of fees that are being held.\\n */\\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\\n return _heldFeesOf[_projectId];\\n }\\n\\n //*********************************************************************//\\n // -------------------------- public views --------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Indicates if this contract adheres to the specified interface.\\n\\n @dev \\n See {IERC165-supportsInterface}.\\n\\n @param _interfaceId The ID of the interface to check for adherance to.\\n */\\n function supportsInterface(bytes4 _interfaceId)\\n public\\n view\\n virtual\\n override(JBSingleTokenPaymentTerminal, IERC165)\\n returns (bool)\\n {\\n return\\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal3_1).interfaceId ||\\n _interfaceId == type(IJBPayoutTerminal3_1).interfaceId ||\\n _interfaceId == type(IJBAllowanceTerminal3_1).interfaceId ||\\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\\n _interfaceId == type(IJBOperatable).interfaceId ||\\n super.supportsInterface(_interfaceId);\\n }\\n\\n //*********************************************************************//\\n // -------------------------- internal views ------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Checks the balance of tokens in this contract.\\n\\n @return The contract's balance.\\n */\\n function _balance() internal view virtual returns (uint256);\\n\\n //*********************************************************************//\\n // -------------------------- constructor ---------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @param _token The token that this terminal manages.\\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\\n @param _currency The currency that this terminal's token adheres to for price feeds.\\n @param _baseWeightCurrency The currency to base token issuance on.\\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\\n @param _operatorStore A contract storing operator assignments.\\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\\n @param _directory A contract storing directories of terminals and controllers for each project.\\n @param _splitsStore A contract that stores splits for each project.\\n @param _prices A contract that exposes price feeds.\\n @param _store A contract that stores the terminal's data.\\n @param _owner The address that will own this contract.\\n */\\n constructor(\\n // payable constructor save the gas used to check msg.value==0\\n address _token,\\n uint256 _decimals,\\n uint256 _currency,\\n uint256 _baseWeightCurrency,\\n uint256 _payoutSplitsGroup,\\n IJBOperatorStore _operatorStore,\\n IJBProjects _projects,\\n IJBDirectory _directory,\\n IJBSplitsStore _splitsStore,\\n IJBPrices _prices,\\n IJBSingleTokenPaymentTerminalStore _store,\\n address _owner\\n )\\n payable\\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\\n JBOperatable(_operatorStore)\\n {\\n baseWeightCurrency = _baseWeightCurrency;\\n payoutSplitsGroup = _payoutSplitsGroup;\\n projects = _projects;\\n directory = _directory;\\n splitsStore = _splitsStore;\\n prices = _prices;\\n store = _store;\\n\\n transferOwnership(_owner);\\n }\\n\\n //*********************************************************************//\\n // ---------------------- external transactions ---------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Contribute tokens to a project.\\n\\n @param _projectId The ID of the project being paid.\\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\\n\\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\\n */\\n function pay(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n // ETH shouldn't be sent if this terminal's token isn't ETH.\\n if (token != JBTokens.GAS_TOKEN) {\\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\\n\\n // Get a reference to the balance before receiving tokens.\\n uint256 _balanceBefore = _balance();\\n\\n // Transfer tokens to this terminal from the msg sender.\\n _transferFrom(msg.sender, payable(address(this)), _amount);\\n\\n // The amount should reflect the change in balance.\\n _amount = _balance() - _balanceBefore;\\n }\\n // If this terminal's token is ETH, override _amount with msg.value.\\n else _amount = msg.value;\\n\\n return\\n _pay(\\n _amount,\\n msg.sender,\\n _projectId,\\n _beneficiary,\\n _minReturnedTokens,\\n _preferClaimedTokens,\\n _memo,\\n _metadata\\n );\\n }\\n\\n /**\\n @notice\\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\\n\\n @dev\\n Only a token holder or a designated operator can redeem its tokens.\\n\\n @param _holder The account to redeem tokens for.\\n @param _projectId The ID of the project to which the tokens being redeemed belong.\\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\\n @param _beneficiary The address to send the terminal tokens to.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\\n\\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\\n */\\n function redeemTokensOf(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n address _token,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string memory _memo,\\n bytes memory _metadata\\n )\\n external\\n virtual\\n override\\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\\n returns (uint256 reclaimAmount)\\n {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n return\\n _redeemTokensOf(\\n _holder,\\n _projectId,\\n _tokenCount,\\n _minReturnedTokens,\\n _beneficiary,\\n _memo,\\n _metadata\\n );\\n }\\n\\n /**\\n @notice\\n Distributes payouts for a project with the distribution limit of its current funding cycle.\\n\\n @dev\\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\\n\\n @dev\\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\\n\\n @dev\\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\\n\\n @param _projectId The ID of the project having its payouts distributed.\\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\\n @param _metadata Bytes to send along to the emitted event, if provided.\\n\\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\\n */\\n function distributePayoutsOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n address _token,\\n uint256 _minReturnedTokens,\\n bytes calldata _metadata\\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _metadata);\\n }\\n\\n /**\\n @notice\\n Allows a project to send funds from its overflow up to the preconfigured allowance.\\n\\n @dev\\n Only a project's owner or a designated operator can use its allowance.\\n\\n @dev\\n Incurs the protocol fee.\\n\\n @param _projectId The ID of the project to use the allowance of.\\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\\n @param _beneficiary The address to send the funds to.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Bytes to send along to the emitted event, if provided.\\n\\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\\n */\\n function useAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n address _token,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string memory _memo,\\n bytes calldata _metadata\\n )\\n external\\n virtual\\n override\\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\\n returns (uint256 netDistributedAmount)\\n {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n return\\n _useAllowanceOf(\\n _projectId,\\n _amount,\\n _currency,\\n _minReturnedTokens,\\n _beneficiary,\\n _memo,\\n _metadata\\n );\\n }\\n\\n /**\\n @notice\\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\\n\\n @dev\\n Only a project's owner or a designated operator can migrate it.\\n\\n @param _projectId The ID of the project being migrated.\\n @param _to The terminal contract that will gain the project's funds.\\n\\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\\n */\\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\\n external\\n virtual\\n override\\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\\n returns (uint256 balance)\\n {\\n // The terminal being migrated to must accept the same token as this terminal.\\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\\n\\n // Record the migration in the store.\\n balance = store.recordMigration(_projectId);\\n\\n // Transfer the balance if needed.\\n if (balance > 0) {\\n // Trigger any inherited pre-transfer logic.\\n _beforeTransferTo(address(_to), balance);\\n\\n // If this terminal's token is ETH, send it in msg.value.\\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? balance : 0;\\n\\n // Withdraw the balance to transfer to the new terminal;\\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\\n }\\n\\n emit Migrate(_projectId, _to, balance, msg.sender);\\n }\\n\\n /**\\n @notice\\n Receives funds belonging to the specified project.\\n\\n @param _projectId The ID of the project to which the funds received belong.\\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Extra data to pass along to the emitted event.\\n */\\n function addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable virtual override isTerminalOf(_projectId) {\\n // Do not refund held fees by default.\\n addToBalanceOf(_projectId, _amount, _token, false, _memo, _metadata);\\n }\\n\\n /**\\n @notice\\n Process any fees that are being held for the project.\\n\\n @dev\\n Only a project owner, an operator, or the contract's owner can process held fees.\\n\\n @param _projectId The ID of the project whos held fees should be processed.\\n */\\n function processFees(uint256 _projectId)\\n external\\n virtual\\n override\\n requirePermissionAllowingOverride(\\n projects.ownerOf(_projectId),\\n _projectId,\\n JBOperations.PROCESS_FEES,\\n msg.sender == owner()\\n )\\n {\\n // Get a reference to the project's held fees.\\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\\n\\n // Delete the held fees.\\n delete _heldFeesOf[_projectId];\\n\\n // Push array length in stack\\n uint256 _heldFeeLength = _heldFees.length;\\n\\n // Process each fee.\\n for (uint256 _i; _i < _heldFeeLength; ) {\\n // Get the fee amount.\\n uint256 _amount = _feeAmount(\\n _heldFees[_i].amount,\\n _heldFees[_i].fee,\\n _heldFees[_i].feeDiscount\\n );\\n\\n // Process the fee.\\n _processFee(_amount, _heldFees[_i].beneficiary, _projectId);\\n\\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n\\n /**\\n @notice\\n Allows the fee to be updated.\\n\\n @dev\\n Only the owner of this contract can change the fee.\\n\\n @param _fee The new fee, out of MAX_FEE.\\n */\\n function setFee(uint256 _fee) external virtual override onlyOwner {\\n // The provided fee must be within the max.\\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\\n\\n // Store the new fee.\\n fee = _fee;\\n\\n emit SetFee(_fee, msg.sender);\\n }\\n\\n /**\\n @notice\\n Allows the fee gauge to be updated.\\n\\n @dev\\n Only the owner of this contract can change the fee gauge.\\n\\n @param _feeGauge The new fee gauge.\\n */\\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\\n // Store the new fee gauge.\\n feeGauge = _feeGauge;\\n\\n emit SetFeeGauge(_feeGauge, msg.sender);\\n }\\n\\n /**\\n @notice\\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\\n\\n @dev\\n Only the owner of this contract can set addresses as feeless.\\n\\n @param _address The address that can be paid towards while still bypassing fees.\\n @param _flag A flag indicating whether the terminal should be feeless or not.\\n */\\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\\n // Set the flag value.\\n isFeelessAddress[_address] = _flag;\\n\\n emit SetFeelessAddress(_address, _flag, msg.sender);\\n }\\n\\n //*********************************************************************//\\n // ----------------------- public transactions ----------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Receives funds belonging to the specified project.\\n\\n @param _projectId The ID of the project to which the funds received belong.\\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Extra data to pass along to the emitted event.\\n */\\n function addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n bool _shouldRefundHeldFees,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) public payable virtual override isTerminalOf(_projectId) {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\\n if (token != JBTokens.GAS_TOKEN) {\\n // Amount must be greater than 0.\\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\\n\\n // Get a reference to the balance before receiving tokens.\\n uint256 _balanceBefore = _balance();\\n\\n // Transfer tokens to this terminal from the msg sender.\\n _transferFrom(msg.sender, payable(address(this)), _amount);\\n\\n // The amount should reflect the change in balance.\\n _amount = _balance() - _balanceBefore;\\n }\\n // If the terminal's token is ETH, override `_amount` with msg.value.\\n else _amount = msg.value;\\n\\n // Add to balance.\\n _addToBalanceOf(_projectId, _amount, _shouldRefundHeldFees, _memo, _metadata);\\n }\\n\\n //*********************************************************************//\\n // ---------------------- internal transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Transfers tokens.\\n\\n @param _from The address from which the transfer should originate.\\n @param _to The address to which the transfer should go.\\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\\n */\\n function _transferFrom(\\n address _from,\\n address payable _to,\\n uint256 _amount\\n ) internal virtual {\\n _from; // Prevents unused var compiler and natspec complaints.\\n _to; // Prevents unused var compiler and natspec complaints.\\n _amount; // Prevents unused var compiler and natspec complaints.\\n }\\n\\n /** \\n @notice\\n Logic to be triggered before transferring tokens from this terminal.\\n\\n @param _to The address to which the transfer is going.\\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\\n */\\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\\n _to; // Prevents unused var compiler and natspec complaints.\\n _amount; // Prevents unused var compiler and natspec complaints.\\n }\\n\\n /** \\n @notice\\n Logic to be triggered if a transfer should be undone\\n\\n @param _to The address to which the transfer went.\\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\\n */\\n function _cancelTransferTo(address _to, uint256 _amount) internal virtual {\\n _to; // Prevents unused var compiler and natspec complaints.\\n _amount; // Prevents unused var compiler and natspec complaints.\\n }\\n\\n /**\\n @notice\\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\\n\\n @dev\\n Only a token holder or a designated operator can redeem its tokens.\\n\\n @param _holder The account to redeem tokens for.\\n @param _projectId The ID of the project to which the tokens being redeemed belong.\\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\\n @param _beneficiary The address to send the terminal tokens to.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\\n\\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\\n */\\n function _redeemTokensOf(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string memory _memo,\\n bytes memory _metadata\\n ) internal returns (uint256 reclaimAmount) {\\n // Can't send reclaimed funds to the zero address.\\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\\n\\n // Define variables that will be needed outside the scoped section below.\\n // Keep a reference to the funding cycle during which the redemption is being made.\\n JBFundingCycle memory _fundingCycle;\\n\\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\\n {\\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\\n\\n // Record the redemption.\\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\\n _holder,\\n _projectId,\\n _tokenCount,\\n _memo,\\n _metadata\\n );\\n\\n // The amount being reclaimed must be at least as much as was expected.\\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\\n\\n // Burn the project tokens.\\n if (_tokenCount > 0)\\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\\n _holder,\\n _projectId,\\n _tokenCount,\\n '',\\n false\\n );\\n\\n // If delegate allocations were specified by the data source, fulfill them.\\n if (_delegateAllocations.length != 0) {\\n // Keep a reference to the token amount being forwarded to the delegate.\\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\\n\\n JBDidRedeemData memory _data = JBDidRedeemData(\\n _holder,\\n _projectId,\\n _fundingCycle.configuration,\\n _tokenCount,\\n JBTokenAmount(token, reclaimAmount, decimals, currency),\\n _forwardedAmount,\\n _beneficiary,\\n _memo,\\n _metadata\\n );\\n\\n uint256 _numDelegates = _delegateAllocations.length;\\n\\n for (uint256 _i; _i < _numDelegates; ) {\\n // Get a reference to the delegate being iterated on.\\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\\n\\n // Trigger any inherited pre-transfer logic.\\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\\n\\n // Keep track of the msg.value to use in the delegate call\\n uint256 _payableValue;\\n\\n // If this terminal's token is ETH, send it in msg.value.\\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\\n\\n // Pass the correct token forwardedAmount to the delegate\\n _data.forwardedAmount.value = _delegateAllocation.amount;\\n\\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\\n\\n emit DelegateDidRedeem(\\n _delegateAllocation.delegate,\\n _data,\\n _delegateAllocation.amount,\\n msg.sender\\n );\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n }\\n\\n // Send the reclaimed funds to the beneficiary.\\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\\n\\n emit RedeemTokens(\\n _fundingCycle.configuration,\\n _fundingCycle.number,\\n _projectId,\\n _holder,\\n _beneficiary,\\n _tokenCount,\\n reclaimAmount,\\n _memo,\\n _metadata,\\n msg.sender\\n );\\n }\\n\\n /**\\n @notice\\n Distributes payouts for a project with the distribution limit of its current funding cycle.\\n\\n @dev\\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\\n\\n @dev\\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\\n\\n @dev\\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\\n\\n @param _projectId The ID of the project having its payouts distributed.\\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\\n @param _metadata Bytes to send along to the emitted event, if provided.\\n\\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\\n */\\n function _distributePayoutsOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n uint256 _minReturnedTokens,\\n bytes calldata _metadata\\n ) internal returns (uint256 netLeftoverDistributionAmount) {\\n // Record the distribution.\\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\\n _projectId,\\n _amount,\\n _currency\\n );\\n\\n // The amount being distributed must be at least as much as was expected.\\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\\n\\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\\n // and receive any extra distributable funds not allocated to payout splits.\\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\\n\\n // Define variables that will be needed outside the scoped section below.\\n // Keep a reference to the fee amount that was paid.\\n uint256 _fee;\\n\\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\\n {\\n // Get the amount of discount that should be applied to any fees taken.\\n // If the fee is zero, set the discount to 100% for convenience.\\n uint256 _feeDiscount = fee == 0\\n ? JBConstants.MAX_FEE_DISCOUNT\\n : _currentFeeDiscount(_projectId);\\n\\n // The amount distributed that is eligible for incurring fees.\\n uint256 _feeEligibleDistributionAmount;\\n\\n // The amount leftover after distributing to the splits.\\n uint256 _leftoverDistributionAmount;\\n\\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\\n _projectId,\\n _fundingCycle.configuration,\\n payoutSplitsGroup,\\n _distributedAmount,\\n _feeDiscount\\n );\\n\\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\\n unchecked {\\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\\n }\\n }\\n\\n // Take the fee.\\n _fee = _feeEligibleDistributionAmount != 0\\n ? _takeFeeFrom(\\n _projectId,\\n _fundingCycle,\\n _feeEligibleDistributionAmount,\\n _projectOwner,\\n _feeDiscount\\n )\\n : 0;\\n\\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\\n if (_leftoverDistributionAmount != 0) {\\n // Subtract the fee from the net leftover amount.\\n netLeftoverDistributionAmount =\\n _leftoverDistributionAmount -\\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\\n\\n // Transfer the amount to the project owner.\\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\\n }\\n }\\n\\n emit DistributePayouts(\\n _fundingCycle.configuration,\\n _fundingCycle.number,\\n _projectId,\\n _projectOwner,\\n _amount,\\n _distributedAmount,\\n _fee,\\n netLeftoverDistributionAmount,\\n _metadata,\\n msg.sender\\n );\\n }\\n\\n /**\\n @notice\\n Allows a project to send funds from its overflow up to the preconfigured allowance.\\n\\n @dev\\n Only a project's owner or a designated operator can use its allowance.\\n\\n @dev\\n Incurs the protocol fee.\\n\\n @param _projectId The ID of the project to use the allowance of.\\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\\n @param _beneficiary The address to send the funds to.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Bytes to send along to the emitted event, if provided.\\n\\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\\n */\\n function _useAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string memory _memo,\\n bytes calldata _metadata\\n ) internal returns (uint256 netDistributedAmount) {\\n // Record the use of the allowance.\\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\\n _projectId,\\n _amount,\\n _currency\\n );\\n\\n // The amount being withdrawn must be at least as much as was expected.\\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\\n\\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\\n {\\n // Keep a reference to the fee amount that was paid.\\n uint256 _fee;\\n\\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\\n address _projectOwner = projects.ownerOf(_projectId);\\n\\n // Get the amount of discount that should be applied to any fees taken.\\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\\n ? JBConstants.MAX_FEE_DISCOUNT\\n : _currentFeeDiscount(_projectId);\\n\\n // Take a fee from the `_distributedAmount`, if needed.\\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\\n ? 0\\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\\n\\n unchecked {\\n // The net amount is the withdrawn amount without the fee.\\n netDistributedAmount = _distributedAmount - _fee;\\n }\\n\\n // Transfer any remaining balance to the beneficiary.\\n if (netDistributedAmount > 0)\\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\\n }\\n\\n emit UseAllowance(\\n _fundingCycle.configuration,\\n _fundingCycle.number,\\n _projectId,\\n _beneficiary,\\n _amount,\\n _distributedAmount,\\n netDistributedAmount,\\n _memo,\\n _metadata,\\n msg.sender\\n );\\n }\\n\\n /**\\n @notice\\n Pays out splits for a project's funding cycle configuration.\\n\\n @param _projectId The ID of the project for which payout splits are being distributed.\\n @param _domain The domain of the splits to distribute the payout between.\\n @param _group The group of the splits to distribute the payout between.\\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\\n\\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\\n */\\n function _distributeToPayoutSplitsOf(\\n uint256 _projectId,\\n uint256 _domain,\\n uint256 _group,\\n uint256 _amount,\\n uint256 _feeDiscount\\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\\n // Set the leftover amount to the initial amount.\\n leftoverAmount = _amount;\\n // The total percentage available to split\\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\\n\\n // Get a reference to the project's payout splits.\\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\\n\\n // Transfer between all splits.\\n for (uint256 _i; _i < _splits.length; ) {\\n // Get a reference to the split being iterated on.\\n JBSplit memory _split = _splits[_i];\\n\\n // The amount to send towards the split.\\n uint256 _payoutAmount = _split.percent == leftoverPercentage\\n ? leftoverAmount\\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\\n\\n // Decrement the leftover percentage.\\n leftoverPercentage -= _split.percent;\\n\\n // The payout amount substracting any applicable incurred fees.\\n uint256 _netPayoutAmount = _distributeToPayoutSplit(\\n _split,\\n _projectId,\\n _group,\\n _payoutAmount,\\n _feeDiscount\\n );\\n\\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\\n if (_netPayoutAmount != 0 && _netPayoutAmount != _payoutAmount)\\n feeEligibleDistributionAmount += _payoutAmount;\\n\\n if (_payoutAmount > 0) {\\n // Subtract from the amount to be sent to the beneficiary.\\n unchecked {\\n leftoverAmount = leftoverAmount - _payoutAmount;\\n }\\n }\\n\\n emit DistributeToPayoutSplit(\\n _projectId,\\n _domain,\\n _group,\\n _split,\\n _payoutAmount,\\n _netPayoutAmount,\\n msg.sender\\n );\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n\\n /**\\n @notice\\n Pays out a split for a project's funding cycle configuration.\\n \\n @param _split The split to distribute payouts to.\\n @param _amount The total amount being distributed to the split, as a fixed point number with the same number of decimals as this terminal.\\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\\n\\n @return netPayoutAmount The amount sent to the split after subtracting fees.\\n */\\n function _distributeToPayoutSplit(\\n JBSplit memory _split,\\n uint256 _projectId,\\n uint256 _group,\\n uint256 _amount,\\n uint256 _feeDiscount\\n ) internal returns (uint256 netPayoutAmount) {\\n // If there's an allocator set, transfer to its `allocate` function.\\n if (_split.allocator != IJBSplitAllocator(address(0))) {\\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\\n if (\\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_split.allocator)]\\n )\\n netPayoutAmount = _amount;\\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\\n else {\\n unchecked {\\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\\n }\\n }\\n\\n // Trigger any inherited pre-transfer logic.\\n _beforeTransferTo(address(_split.allocator), netPayoutAmount);\\n\\n // Create the data to send to the allocator.\\n JBSplitAllocationData memory _data = JBSplitAllocationData(\\n token,\\n netPayoutAmount,\\n decimals,\\n _projectId,\\n _group,\\n _split\\n );\\n\\n // Trigger the allocator's `allocate` function.\\n uint256 _error;\\n bytes memory _reason;\\n\\n if (\\n ERC165Checker.supportsInterface(\\n address(_split.allocator),\\n type(IJBSplitAllocator).interfaceId\\n )\\n )\\n // If this terminal's token is ETH, send it in msg.value.\\n try _split.allocator.allocate{value: token == JBTokens.GAS_TOKEN ? netPayoutAmount : 0}(_data) {\\n\\n } catch (bytes memory reason) {\\n _reason = reason;\\n _error = 1;\\n }\\n else _error = 2;\\n\\n\\n if (_error != 0) {\\n // Trigger any inhereted post-transfer cancelation logic.\\n _cancelTransferTo(address(_split.allocator), netPayoutAmount);\\n\\n // Set the net payout amount to 0 to signal the reversion.\\n netPayoutAmount = 0;\\n\\n // Add undistributed amount back to project's balance.\\n store.recordAddedBalanceFor(_projectId, _amount);\\n\\n emit PayoutReverted(_projectId, _split, _amount, _error == 1 ? _reason : abi.encode(\\\"IERC165 fail\\\"), msg.sender);\\n }\\n\\n // Otherwise, if a project is specified, make a payment to it.\\n } else if (_split.projectId != 0) {\\n // Get a reference to the Juicebox terminal being used.\\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\\n\\n // The project must have a terminal to send funds to.\\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\\n\\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\\n if (\\n _terminal == this ||\\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\\n isFeelessAddress[address(_terminal)]\\n )\\n netPayoutAmount = _amount;\\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\\n else {\\n unchecked {\\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\\n }\\n }\\n\\n // Trigger any inherited pre-transfer logic.\\n _beforeTransferTo(address(_terminal), netPayoutAmount);\\n\\n // Send the projectId in the metadata.\\n bytes memory _projectMetadata = new bytes(32);\\n _projectMetadata = bytes(abi.encodePacked(_projectId));\\n\\n // Add to balance if prefered.\\n if (_split.preferAddToBalance)\\n try\\n _terminal.addToBalanceOf{value: token == JBTokens.GAS_TOKEN ? netPayoutAmount : 0}(\\n _split.projectId,\\n netPayoutAmount,\\n token,\\n '',\\n _projectMetadata\\n )\\n {} catch (bytes memory reason) {\\n // Trigger any inhereted post-transfer cancelation logic.\\n _cancelTransferTo(address(_terminal), netPayoutAmount);\\n\\n // Set the net payout amount to 0 to signal the reversion.\\n netPayoutAmount = 0;\\n\\n // Add undistributed amount back to project's balance.\\n store.recordAddedBalanceFor(_projectId, _amount);\\n\\n emit PayoutReverted(_projectId, _split, _amount, reason, msg.sender);\\n }\\n else\\n try\\n _terminal.pay{value: token == JBTokens.GAS_TOKEN ? netPayoutAmount : 0}(\\n _split.projectId,\\n netPayoutAmount,\\n token,\\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\\n 0,\\n _split.preferClaimed,\\n '',\\n _projectMetadata\\n )\\n {} catch (bytes memory reason) {\\n // Trigger any inhereted post-transfer cancelation logic.\\n _cancelTransferTo(address(_terminal), netPayoutAmount);\\n\\n // Set the net payout amount to 0 to signal the reversion.\\n netPayoutAmount = 0;\\n\\n // Add undistributed amount back to project's balance.\\n store.recordAddedBalanceFor(_projectId, _amount);\\n\\n emit PayoutReverted(_projectId, _split, _amount, reason, msg.sender);\\n }\\n } else {\\n // Keep a reference to the beneficiary.\\n address payable _beneficiary = _split.beneficiary != address(0)\\n ? _split.beneficiary\\n : payable(msg.sender);\\n\\n // If there's a full discount, this distribution is not eligible for a fee.\\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\\n netPayoutAmount = _amount;\\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\\n else {\\n unchecked {\\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\\n }\\n }\\n\\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\\n _transferFrom(address(this), _beneficiary, netPayoutAmount);\\n }\\n }\\n\\n /**\\n @notice\\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\\n\\n @param _projectId The ID of the project having fees taken from.\\n @param _fundingCycle The funding cycle during which the fee is being taken.\\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\\n @param _beneficiary The address to mint the platforms tokens for.\\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\\n\\n @return feeAmount The amount of the fee taken.\\n */\\n function _takeFeeFrom(\\n uint256 _projectId,\\n JBFundingCycle memory _fundingCycle,\\n uint256 _amount,\\n address _beneficiary,\\n uint256 _feeDiscount\\n ) internal returns (uint256 feeAmount) {\\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\\n\\n if (_fundingCycle.shouldHoldFees()) {\\n // Store the held fee.\\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\\n\\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\\n } else {\\n // Process the fee.\\n _processFee(feeAmount, _beneficiary, _projectId); // Take the fee.\\n\\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\\n }\\n }\\n\\n /**\\n @notice\\n Process a fee of the specified amount.\\n\\n @param _amount The fee amount, as a floating point number with 18 decimals.\\n @param _beneficiary The address to mint the platform's tokens for.\\n @param _from The project ID the fee is being paid from.\\n */\\n function _processFee(\\n uint256 _amount,\\n address _beneficiary,\\n uint256 _from\\n ) internal {\\n // Get the terminal for the protocol project.\\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\\n\\n // If this terminal's token is ETH, send it in msg.value.\\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _amount : 0;\\n\\n // Send the projectId in the metadata.\\n bytes memory _projectMetadata = new bytes(32);\\n _projectMetadata = bytes(abi.encodePacked(_from));\\n\\n // Trigger any inherited pre-transfer logic if funds will be transferred.\\n if (address(_terminal) != address(this)) _beforeTransferTo(address(_terminal), _amount);\\n\\n try\\n // Send the fee.\\n _terminal.pay{value: _payableValue}(\\n _FEE_BENEFICIARY_PROJECT_ID,\\n _amount,\\n token,\\n _beneficiary,\\n 0,\\n false,\\n '',\\n _projectMetadata\\n )\\n {} catch (bytes memory reason) {\\n // Trigger any inhereted post-transfer cancelation logic if the pre-transfer logic was triggered.\\n if (address(_terminal) != address(this)) _cancelTransferTo(address(_terminal), _amount);\\n\\n // Add fee amount back to project's balance.\\n store.recordAddedBalanceFor(_from, _amount);\\n\\n emit FeeReverted(_from, _FEE_BENEFICIARY_PROJECT_ID, _amount, reason, msg.sender);\\n }\\n }\\n\\n /**\\n @notice\\n Contribute tokens to a project.\\n\\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\\n @param _payer The address making the payment.\\n @param _projectId The ID of the project being paid.\\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\\n\\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\\n */\\n function _pay(\\n uint256 _amount,\\n address _payer,\\n uint256 _projectId,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string memory _memo,\\n bytes memory _metadata\\n ) internal returns (uint256 beneficiaryTokenCount) {\\n // Cant send tokens to the zero address.\\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\\n\\n // Define variables that will be needed outside the scoped section below.\\n // Keep a reference to the funding cycle during which the payment is being made.\\n JBFundingCycle memory _fundingCycle;\\n\\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\\n {\\n JBPayDelegateAllocation[] memory _delegateAllocations;\\n uint256 _tokenCount;\\n\\n // Bundle the amount info into a JBTokenAmount struct.\\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\\n\\n // Record the payment.\\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\\n _payer,\\n _bundledAmount,\\n _projectId,\\n baseWeightCurrency,\\n _beneficiary,\\n _memo,\\n _metadata\\n );\\n\\n // Mint the tokens if needed.\\n if (_tokenCount > 0)\\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\\n _projectId,\\n _tokenCount,\\n _beneficiary,\\n '',\\n _preferClaimedTokens,\\n true\\n );\\n\\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\\n\\n // If delegate allocations were specified by the data source, fulfill them.\\n if (_delegateAllocations.length != 0) {\\n // Keep a reference to the token amount being forwarded to the delegate.\\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\\n\\n JBDidPayData memory _data = JBDidPayData(\\n _payer,\\n _projectId,\\n _fundingCycle.configuration,\\n _bundledAmount,\\n _forwardedAmount,\\n beneficiaryTokenCount,\\n _beneficiary,\\n _preferClaimedTokens,\\n _memo,\\n _metadata\\n );\\n\\n // Get a reference to the number of delegates to allocate to.\\n uint256 _numDelegates = _delegateAllocations.length;\\n\\n for (uint256 _i; _i < _numDelegates; ) {\\n // Get a reference to the delegate being iterated on.\\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\\n\\n // Trigger any inherited pre-transfer logic.\\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\\n\\n // Keep track of the msg.value to use in the delegate call\\n uint256 _payableValue;\\n\\n // If this terminal's token is ETH, send it in msg.value.\\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\\n\\n // Pass the correct token forwardedAmount to the delegate\\n _data.forwardedAmount.value = _delegateAllocation.amount;\\n\\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\\n\\n emit DelegateDidPay(\\n _delegateAllocation.delegate,\\n _data,\\n _delegateAllocation.amount,\\n msg.sender\\n );\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n }\\n\\n emit Pay(\\n _fundingCycle.configuration,\\n _fundingCycle.number,\\n _projectId,\\n _payer,\\n _beneficiary,\\n _amount,\\n beneficiaryTokenCount,\\n _memo,\\n _metadata,\\n msg.sender\\n );\\n }\\n\\n /**\\n @notice\\n Receives funds belonging to the specified project.\\n\\n @param _projectId The ID of the project to which the funds received belong.\\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Extra data to pass along to the emitted event.\\n */\\n function _addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n bool _shouldRefundHeldFees,\\n string memory _memo,\\n bytes memory _metadata\\n ) internal {\\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\\n\\n // Record the added funds with any refunded fees.\\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\\n\\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\\n }\\n\\n /**\\n @notice\\n Refund fees based on the specified amount.\\n\\n @param _projectId The project for which fees are being refunded.\\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\\n\\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\\n */\\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\\n internal\\n returns (uint256 refundedFees)\\n {\\n // Get a reference to the project's held fees.\\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\\n\\n // Delete the current held fees.\\n delete _heldFeesOf[_projectId];\\n\\n // Get a reference to the leftover amount once all fees have been settled.\\n uint256 leftoverAmount = _amount;\\n\\n // Push length in stack\\n uint256 _heldFeesLength = _heldFees.length;\\n\\n // Process each fee.\\n for (uint256 _i; _i < _heldFeesLength; ) {\\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\\n else if (leftoverAmount >= _heldFees[_i].amount) {\\n unchecked {\\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\\n refundedFees += _feeAmount(\\n _heldFees[_i].amount,\\n _heldFees[_i].fee,\\n _heldFees[_i].feeDiscount\\n );\\n }\\n } else {\\n unchecked {\\n _heldFeesOf[_projectId].push(\\n JBFee(\\n _heldFees[_i].amount - leftoverAmount,\\n _heldFees[_i].fee,\\n _heldFees[_i].feeDiscount,\\n _heldFees[_i].beneficiary\\n )\\n );\\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\\n }\\n leftoverAmount = 0;\\n }\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n\\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\\n }\\n\\n /** \\n @notice \\n Returns the fee amount based on the provided amount for the specified project.\\n\\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\\n @param _fee The percentage of the fee, out of MAX_FEE. \\n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\\n\\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\\n */\\n function _feeAmount(\\n uint256 _amount,\\n uint256 _fee,\\n uint256 _feeDiscount\\n ) internal pure returns (uint256) {\\n // Calculate the discounted fee.\\n uint256 _discountedFee = _fee -\\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\\n\\n // The amount of tokens from the `_amount` to pay as a fee.\\n return\\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\\n }\\n\\n /** \\n @notice\\n Get the fee discount from the fee gauge for the specified project.\\n\\n @param _projectId The ID of the project to get a fee discount for.\\n \\n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\\n */\\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\\n if (\\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\\n IJBPaymentTerminal(address(0))\\n ) return JBConstants.MAX_FEE_DISCOUNT;\\n\\n // Get the fee discount.\\n if (feeGauge != IJBFeeGauge(address(0)))\\n // If the guage reverts, keep the discount at 0.\\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\\n // If the fee discount is greater than the max, we ignore the return value\\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\\n } catch {\\n return 0;\\n }\\n\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0x1af3116bfcffd711bd25c79f41f389a1a163716420d22869c072e83e4be60c68\",\"license\":\"MIT\"},\"contracts/abstract/JBSingleTokenPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\\nimport './../interfaces/IJBSingleTokenPaymentTerminal.sol';\\n\\n/**\\n @notice\\n Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\\n\\n @dev\\n Adheres to -\\n IJBSingleTokenPaymentTerminals: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n\\n @dev\\n Inherits from -\\n ERC165: Introspection on interface adherance. \\n*/\\nabstract contract JBSingleTokenPaymentTerminal is ERC165, IJBSingleTokenPaymentTerminal {\\n //*********************************************************************//\\n // ---------------- public immutable stored properties --------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The token that this terminal accepts.\\n */\\n address public immutable override token;\\n\\n /**\\n @notice\\n The number of decimals the token fixed point amounts are expected to have.\\n */\\n uint256 public immutable override decimals;\\n\\n /**\\n @notice\\n The currency to use when resolving price feeds for this terminal.\\n */\\n uint256 public immutable override currency;\\n\\n //*********************************************************************//\\n // ------------------------- external views -------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n A flag indicating if this terminal accepts the specified token.\\n\\n @param _token The token to check if this terminal accepts or not.\\n @param _projectId The project ID to check for token acceptance.\\n\\n @return The flag.\\n */\\n function acceptsToken(address _token, uint256 _projectId) external view override returns (bool) {\\n _projectId; // Prevents unused var compiler and natspec complaints.\\n\\n return _token == token;\\n }\\n\\n /** \\n @notice\\n The decimals that should be used in fixed number accounting for the specified token.\\n\\n @param _token The token to check for the decimals of.\\n\\n @return The number of decimals for the token.\\n */\\n function decimalsForToken(address _token) external view override returns (uint256) {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n return decimals;\\n }\\n\\n /** \\n @notice\\n The currency that should be used for the specified token.\\n\\n @param _token The token to check for the currency of.\\n\\n @return The currency index.\\n */\\n function currencyForToken(address _token) external view override returns (uint256) {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n return currency;\\n }\\n\\n //*********************************************************************//\\n // -------------------------- public views --------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Indicates if this contract adheres to the specified interface.\\n\\n @dev \\n See {IERC165-supportsInterface}.\\n\\n @param _interfaceId The ID of the interface to check for adherance to.\\n */\\n function supportsInterface(bytes4 _interfaceId)\\n public\\n view\\n virtual\\n override(ERC165, IERC165)\\n returns (bool)\\n {\\n return\\n _interfaceId == type(IJBPaymentTerminal).interfaceId ||\\n _interfaceId == type(IJBSingleTokenPaymentTerminal).interfaceId ||\\n super.supportsInterface(_interfaceId);\\n }\\n\\n //*********************************************************************//\\n // -------------------------- constructor ---------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @param _token The token that this terminal manages.\\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\\n @param _currency The currency that this terminal's token adheres to for price feeds.\\n */\\n constructor(\\n address _token,\\n uint256 _decimals,\\n uint256 _currency\\n ) {\\n token = _token;\\n decimals = _decimals;\\n currency = _currency;\\n }\\n}\\n\",\"keccak256\":\"0xdc82ad3e01b918d3d21ffea8c9f30950d81e225137c851599d028dcd22125f89\",\"license\":\"MIT\"},\"contracts/enums/JBBallotState.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nenum JBBallotState {\\n Active,\\n Approved,\\n Failed\\n}\\n\",\"keccak256\":\"0x891fcac63470398b3a11239da7feba6b07d640809fcefd2404303b823d7378f8\",\"license\":\"MIT\"},\"contracts/interfaces/IJBAllowanceTerminal3_1.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBAllowanceTerminal3_1 {\\n function useAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n address _token,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external returns (uint256 netDistributedAmount);\\n}\\n\",\"keccak256\":\"0x4e1ef83fc258e44f7880005b7944e3b4799d87129b2300236d93269a00adb4ee\",\"license\":\"MIT\"},\"contracts/interfaces/IJBController.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBFundAccessConstraints.sol';\\nimport './../structs/JBFundingCycleData.sol';\\nimport './../structs/JBFundingCycleMetadata.sol';\\nimport './../structs/JBGroupedSplits.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBMigratable.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBSplitsStore.sol';\\nimport './IJBTokenStore.sol';\\n\\ninterface IJBController is IERC165 {\\n event LaunchProject(uint256 configuration, uint256 projectId, string memo, address caller);\\n\\n event LaunchFundingCycles(uint256 configuration, uint256 projectId, string memo, address caller);\\n\\n event ReconfigureFundingCycles(\\n uint256 configuration,\\n uint256 projectId,\\n string memo,\\n address caller\\n );\\n\\n event SetFundAccessConstraints(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n JBFundAccessConstraints constraints,\\n address caller\\n );\\n\\n event DistributeReservedTokens(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address beneficiary,\\n uint256 tokenCount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n address caller\\n );\\n\\n event DistributeToReservedTokenSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n uint256 tokenCount,\\n address caller\\n );\\n\\n event MintTokens(\\n address indexed beneficiary,\\n uint256 indexed projectId,\\n uint256 tokenCount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n uint256 reservedRate,\\n address caller\\n );\\n\\n event BurnTokens(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 tokenCount,\\n string memo,\\n address caller\\n );\\n\\n event Migrate(uint256 indexed projectId, IJBMigratable to, address caller);\\n\\n event PrepMigration(uint256 indexed projectId, address from, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function tokenStore() external view returns (IJBTokenStore);\\n\\n function splitsStore() external view returns (IJBSplitsStore);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function reservedTokenBalanceOf(uint256 _projectId, uint256 _reservedRate)\\n external\\n view\\n returns (uint256);\\n\\n function distributionLimitOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n IJBPaymentTerminal _terminal,\\n address _token\\n ) external view returns (uint256 distributionLimit, uint256 distributionLimitCurrency);\\n\\n function overflowAllowanceOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n IJBPaymentTerminal _terminal,\\n address _token\\n ) external view returns (uint256 overflowAllowance, uint256 overflowAllowanceCurrency);\\n\\n function totalOutstandingTokensOf(uint256 _projectId, uint256 _reservedRate)\\n external\\n view\\n returns (uint256);\\n\\n function getFundingCycleOf(uint256 _projectId, uint256 _configuration)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function latestConfiguredFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (\\n JBFundingCycle memory,\\n JBFundingCycleMetadata memory metadata,\\n JBBallotState\\n );\\n\\n function currentFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function queuedFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function launchProjectFor(\\n address _owner,\\n JBProjectMetadata calldata _projectMetadata,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n IJBPaymentTerminal[] memory _terminals,\\n string calldata _memo\\n ) external returns (uint256 projectId);\\n\\n function launchFundingCyclesFor(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n IJBPaymentTerminal[] memory _terminals,\\n string calldata _memo\\n ) external returns (uint256 configuration);\\n\\n function reconfigureFundingCyclesOf(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n string calldata _memo\\n ) external returns (uint256);\\n\\n function mintTokensOf(\\n uint256 _projectId,\\n uint256 _tokenCount,\\n address _beneficiary,\\n string calldata _memo,\\n bool _preferClaimedTokens,\\n bool _useReservedRate\\n ) external returns (uint256 beneficiaryTokenCount);\\n\\n function burnTokensOf(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n string calldata _memo,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function distributeReservedTokensOf(uint256 _projectId, string memory _memo)\\n external\\n returns (uint256);\\n\\n function migrate(uint256 _projectId, IJBMigratable _to) external;\\n}\\n\",\"keccak256\":\"0xb1ee4b41f2a06f28f69c74cb729b8964f2e75f3c545a68f85bd9082b5575bc85\",\"license\":\"MIT\"},\"contracts/interfaces/IJBDirectory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBProjects.sol';\\n\\ninterface IJBDirectory {\\n event SetController(uint256 indexed projectId, address indexed controller, address caller);\\n\\n event AddTerminal(uint256 indexed projectId, IJBPaymentTerminal indexed terminal, address caller);\\n\\n event SetTerminals(uint256 indexed projectId, IJBPaymentTerminal[] terminals, address caller);\\n\\n event SetPrimaryTerminal(\\n uint256 indexed projectId,\\n address indexed token,\\n IJBPaymentTerminal indexed terminal,\\n address caller\\n );\\n\\n event SetIsAllowedToSetFirstController(address indexed addr, bool indexed flag, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function controllerOf(uint256 _projectId) external view returns (address);\\n\\n function isAllowedToSetFirstController(address _address) external view returns (bool);\\n\\n function terminalsOf(uint256 _projectId) external view returns (IJBPaymentTerminal[] memory);\\n\\n function isTerminalOf(uint256 _projectId, IJBPaymentTerminal _terminal)\\n external\\n view\\n returns (bool);\\n\\n function primaryTerminalOf(uint256 _projectId, address _token)\\n external\\n view\\n returns (IJBPaymentTerminal);\\n\\n function setControllerOf(uint256 _projectId, address _controller) external;\\n\\n function setTerminalsOf(uint256 _projectId, IJBPaymentTerminal[] calldata _terminals) external;\\n\\n function setPrimaryTerminalOf(\\n uint256 _projectId,\\n address _token,\\n IJBPaymentTerminal _terminal\\n ) external;\\n\\n function setIsAllowedToSetFirstController(address _address, bool _flag) external;\\n}\\n\",\"keccak256\":\"0x715321646db00514d1355ed43c40cd3f01e94959552fd07797b315d9c49cdb1d\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFeeGauge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBFeeGauge {\\n function currentDiscountFor(uint256 _projectId) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x8e19959617191320fe1210760860e668a57319258c0c74fcfabac829ae0222c0\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFeeHoldingTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBFeeHoldingTerminal {\\n function addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n bool _shouldRefundHeldFees,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable;\\n}\\n\",\"keccak256\":\"0x8c9edae0768a737097835b8b9ef4a60f000de122a867c90f20cfc653287541a4\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleBallot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../enums/JBBallotState.sol';\\n\\ninterface IJBFundingCycleBallot is IERC165 {\\n function duration() external view returns (uint256);\\n\\n function stateOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n uint256 _start\\n ) external view returns (JBBallotState);\\n}\\n\",\"keccak256\":\"0x49553a56209237846bc400cf27f260824a6bd06fd8094a7eb5abb9de75779598\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../enums/JBBallotState.sol';\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBFundingCycleData.sol';\\n\\ninterface IJBFundingCycleStore {\\n event Configure(\\n uint256 indexed configuration,\\n uint256 indexed projectId,\\n JBFundingCycleData data,\\n uint256 metadata,\\n uint256 mustStartAtOrAfter,\\n address caller\\n );\\n\\n event Init(uint256 indexed configuration, uint256 indexed projectId, uint256 indexed basedOn);\\n\\n function latestConfigurationOf(uint256 _projectId) external view returns (uint256);\\n\\n function get(uint256 _projectId, uint256 _configuration)\\n external\\n view\\n returns (JBFundingCycle memory);\\n\\n function latestConfiguredOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBBallotState ballotState);\\n\\n function queuedOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentBallotStateOf(uint256 _projectId) external view returns (JBBallotState);\\n\\n function configureFor(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n uint256 _metadata,\\n uint256 _mustStartAtOrAfter\\n ) external returns (JBFundingCycle memory fundingCycle);\\n}\\n\",\"keccak256\":\"0xaead823851433be0c2ddc8f8086813e6cd647de3a1bc0f7570a5d6b38c378b5a\",\"license\":\"MIT\"},\"contracts/interfaces/IJBMigratable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBMigratable {\\n function prepForMigrationOf(uint256 _projectId, address _from) external;\\n}\\n\",\"keccak256\":\"0xc81053e4b4754fc510aa04fecd3ab1460f01e3e27761e7a8c94f631a978ae127\",\"license\":\"MIT\"},\"contracts/interfaces/IJBOperatable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBOperatorStore.sol';\\n\\ninterface IJBOperatable {\\n function operatorStore() external view returns (IJBOperatorStore);\\n}\\n\",\"keccak256\":\"0x09a55a91c6ce3625379334271d236cfa47bf36522a91568b406bf06f7239407e\",\"license\":\"MIT\"},\"contracts/interfaces/IJBOperatorStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBOperatorData.sol';\\n\\ninterface IJBOperatorStore {\\n event SetOperator(\\n address indexed operator,\\n address indexed account,\\n uint256 indexed domain,\\n uint256[] permissionIndexes,\\n uint256 packed\\n );\\n\\n function permissionsOf(\\n address _operator,\\n address _account,\\n uint256 _domain\\n ) external view returns (uint256);\\n\\n function hasPermission(\\n address _operator,\\n address _account,\\n uint256 _domain,\\n uint256 _permissionIndex\\n ) external view returns (bool);\\n\\n function hasPermissions(\\n address _operator,\\n address _account,\\n uint256 _domain,\\n uint256[] calldata _permissionIndexes\\n ) external view returns (bool);\\n\\n function setOperator(JBOperatorData calldata _operatorData) external;\\n\\n function setOperators(JBOperatorData[] calldata _operatorData) external;\\n}\\n\",\"keccak256\":\"0x17f4929812a356984795fafed8cb2be816a025c9a0771d85595ac0b5ff3cffc5\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPayDelegate.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBDidPayData.sol';\\n\\n/**\\n @title\\n Pay delegate\\n\\n @notice\\n Delegate called after JBTerminal.pay(..) logic completion (if passed by the funding cycle datasource)\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n*/\\ninterface IJBPayDelegate is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.pay(..), after the execution of its logic\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control\\n \\n @param _data the data passed by the terminal, as a JBDidPayData struct:\\n address payer;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n JBTokenAmount amount;\\n JBTokenAmount forwardedAmount;\\n uint256 projectTokenCount;\\n address beneficiary;\\n bool preferClaimedTokens;\\n string memo;\\n bytes metadata;\\n */\\n function didPay(JBDidPayData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0xa797de18b69eceba117e1f0b3810cf3cc2d2791417d580a5bdc510d1b868ab26\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\n\\ninterface IJBPaymentTerminal is IERC165 {\\n function acceptsToken(address _token, uint256 _projectId) external view returns (bool);\\n\\n function currencyForToken(address _token) external view returns (uint256);\\n\\n function decimalsForToken(address _token) external view returns (uint256);\\n\\n // Return value must be a fixed point number with 18 decimals.\\n function currentEthOverflowOf(uint256 _projectId) external view returns (uint256);\\n\\n function pay(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable returns (uint256 beneficiaryTokenCount);\\n\\n function addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable;\\n}\\n\",\"keccak256\":\"0xb7826f5ed609359ce322c09e83236c47ba385df1c3cad3607e56fd0a2e00eee2\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPayoutRedemptionPaymentTerminal3_1.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBFee.sol';\\nimport './IJBAllowanceTerminal3_1.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFeeGauge.sol';\\nimport './IJBFeeHoldingTerminal.sol';\\nimport './IJBPayDelegate.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBPayoutTerminal3_1.sol';\\nimport './IJBPrices.sol';\\nimport './IJBProjects.sol';\\nimport './IJBRedemptionDelegate.sol';\\nimport './IJBRedemptionTerminal.sol';\\nimport './IJBSingleTokenPaymentTerminalStore.sol';\\nimport './IJBSplitsStore.sol';\\n\\ninterface IJBPayoutRedemptionPaymentTerminal3_1 is\\n IJBPaymentTerminal,\\n IJBPayoutTerminal3_1,\\n IJBAllowanceTerminal3_1,\\n IJBRedemptionTerminal,\\n IJBFeeHoldingTerminal\\n{\\n event AddToBalance(\\n uint256 indexed projectId,\\n uint256 amount,\\n uint256 refundedFees,\\n string memo,\\n bytes metadata,\\n address caller\\n );\\n\\n event Migrate(\\n uint256 indexed projectId,\\n IJBPaymentTerminal indexed to,\\n uint256 amount,\\n address caller\\n );\\n\\n event DistributePayouts(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address beneficiary,\\n uint256 amount,\\n uint256 distributedAmount,\\n uint256 fee,\\n uint256 beneficiaryDistributionAmount,\\n bytes metadata,\\n address caller\\n );\\n\\n event UseAllowance(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address beneficiary,\\n uint256 amount,\\n uint256 distributedAmount,\\n uint256 netDistributedamount,\\n string memo,\\n bytes metadata,\\n address caller\\n );\\n\\n event HoldFee(\\n uint256 indexed projectId,\\n uint256 indexed amount,\\n uint256 indexed fee,\\n uint256 feeDiscount,\\n address beneficiary,\\n address caller\\n );\\n\\n event ProcessFee(\\n uint256 indexed projectId,\\n uint256 indexed amount,\\n bool indexed wasHeld,\\n address beneficiary,\\n address caller\\n );\\n\\n event RefundHeldFees(\\n uint256 indexed projectId,\\n uint256 indexed amount,\\n uint256 indexed refundedFees,\\n uint256 leftoverAmount,\\n address caller\\n );\\n\\n event Pay(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address payer,\\n address beneficiary,\\n uint256 amount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n bytes metadata,\\n address caller\\n );\\n\\n event DelegateDidPay(\\n IJBPayDelegate indexed delegate,\\n JBDidPayData data,\\n uint256 delegatedAmount,\\n address caller\\n );\\n\\n event RedeemTokens(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address holder,\\n address beneficiary,\\n uint256 tokenCount,\\n uint256 reclaimedAmount,\\n string memo,\\n bytes metadata,\\n address caller\\n );\\n\\n event DelegateDidRedeem(\\n IJBRedemptionDelegate indexed delegate,\\n JBDidRedeemData data,\\n uint256 delegatedAmount,\\n address caller\\n );\\n\\n event DistributeToPayoutSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n uint256 amount,\\n uint256 netAmount,\\n address caller\\n );\\n\\n event SetFee(uint256 fee, address caller);\\n\\n event SetFeeGauge(IJBFeeGauge indexed feeGauge, address caller);\\n\\n event SetFeelessAddress(address indexed addrs, bool indexed flag, address caller);\\n\\n event PayoutReverted(uint256 indexed projectId, JBSplit split, uint256 amount, bytes reason, address caller);\\n\\n event FeeReverted(\\n uint256 indexed projectId,\\n uint256 indexed feeProjectId,\\n uint256 amount,\\n bytes reason,\\n address caller\\n );\\n\\n function projects() external view returns (IJBProjects);\\n\\n function splitsStore() external view returns (IJBSplitsStore);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function prices() external view returns (IJBPrices);\\n\\n function store() external view returns (IJBSingleTokenPaymentTerminalStore);\\n\\n function baseWeightCurrency() external view returns (uint256);\\n\\n function payoutSplitsGroup() external view returns (uint256);\\n\\n function heldFeesOf(uint256 _projectId) external view returns (JBFee[] memory);\\n\\n function fee() external view returns (uint256);\\n\\n function feeGauge() external view returns (IJBFeeGauge);\\n\\n function isFeelessAddress(address _contract) external view returns (bool);\\n\\n function migrate(uint256 _projectId, IJBPaymentTerminal _to) external returns (uint256 balance);\\n\\n function processFees(uint256 _projectId) external;\\n\\n function setFee(uint256 _fee) external;\\n\\n function setFeeGauge(IJBFeeGauge _feeGauge) external;\\n\\n function setFeelessAddress(address _contract, bool _flag) external;\\n}\\n\",\"keccak256\":\"0xe823526fd535dc962784820cac32e6fdd56f2a5020dbf9883979b9ddfcc093fa\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPayoutTerminal3_1.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBPayoutTerminal3_1 {\\n function distributePayoutsOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n address _token,\\n uint256 _minReturnedTokens,\\n bytes calldata _metadata\\n ) external returns (uint256 netLeftoverDistributionAmount);\\n}\\n\",\"keccak256\":\"0x415707a4902f90945ecee641e96dd88c733b1d159c35c1184e665ca3509ffe49\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPriceFeed.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBPriceFeed {\\n function currentPrice(uint256 _targetDecimals) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x57c71282fec1b34b00cf991ffed2e36031c393e35bfa7ca5d723eb6572fb7122\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPrices.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBPriceFeed.sol';\\n\\ninterface IJBPrices {\\n event AddFeed(uint256 indexed currency, uint256 indexed base, IJBPriceFeed feed);\\n\\n function feedFor(uint256 _currency, uint256 _base) external view returns (IJBPriceFeed);\\n\\n function priceFor(\\n uint256 _currency,\\n uint256 _base,\\n uint256 _decimals\\n ) external view returns (uint256);\\n\\n function addFeedFor(\\n uint256 _currency,\\n uint256 _base,\\n IJBPriceFeed _priceFeed\\n ) external;\\n}\\n\",\"keccak256\":\"0x82a175b1f4b95b506c98406576cd59cbe04615e3df24f9cf3587b61b8ee323b1\",\"license\":\"MIT\"},\"contracts/interfaces/IJBProjects.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBTokenUriResolver.sol';\\n\\ninterface IJBProjects is IERC721 {\\n event Create(\\n uint256 indexed projectId,\\n address indexed owner,\\n JBProjectMetadata metadata,\\n address caller\\n );\\n\\n event SetMetadata(uint256 indexed projectId, JBProjectMetadata metadata, address caller);\\n\\n event SetTokenUriResolver(IJBTokenUriResolver indexed resolver, address caller);\\n\\n function count() external view returns (uint256);\\n\\n function metadataContentOf(uint256 _projectId, uint256 _domain)\\n external\\n view\\n returns (string memory);\\n\\n function tokenUriResolver() external view returns (IJBTokenUriResolver);\\n\\n function createFor(address _owner, JBProjectMetadata calldata _metadata)\\n external\\n returns (uint256 projectId);\\n\\n function setMetadataOf(uint256 _projectId, JBProjectMetadata calldata _metadata) external;\\n\\n function setTokenUriResolver(IJBTokenUriResolver _newResolver) external;\\n}\\n\",\"keccak256\":\"0x7cfc021d0bd7e73b1ba8f4845d7d35e3419d6a14d3d25ca3a8010e7f91062fe4\",\"license\":\"MIT\"},\"contracts/interfaces/IJBRedemptionDelegate.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBDidRedeemData.sol';\\n\\n/**\\n @title\\n Redemption delegate\\n\\n @notice\\n Delegate called after JBTerminal.redeemTokensOf(..) logic completion (if passed by the funding cycle datasource)\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n*/\\ninterface IJBRedemptionDelegate is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.redeemTokensOf(..), after the execution of its logic\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control\\n \\n @param _data the data passed by the terminal, as a JBDidRedeemData struct:\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 projectTokenCount;\\n JBTokenAmount reclaimedAmount;\\n JBTokenAmount forwardedAmount;\\n address payable beneficiary;\\n string memo;\\n bytes metadata;\\n */\\n function didRedeem(JBDidRedeemData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0x172d2c0be65e72e54f71ae521907067f0fa30e8ca05c4f88826903208aa437e2\",\"license\":\"MIT\"},\"contracts/interfaces/IJBRedemptionTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBRedemptionTerminal {\\n function redeemTokensOf(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n address _token,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external returns (uint256 reclaimAmount);\\n}\\n\",\"keccak256\":\"0xe26a6a03468401b802ae5328b39a266f53b9331a1c077fcbf7719d10ba74ff44\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSingleTokenPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBPaymentTerminal.sol';\\n\\ninterface IJBSingleTokenPaymentTerminal is IJBPaymentTerminal {\\n function token() external view returns (address);\\n\\n function currency() external view returns (uint256);\\n\\n function decimals() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xf6e78323caa9af7bbf024f44b2032a83fed0394e0b3a242a6346e73c85b2e46f\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSingleTokenPaymentTerminalStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBPayDelegateAllocation.sol';\\nimport './../structs/JBRedemptionDelegateAllocation.sol';\\nimport './../structs/JBTokenAmount.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBPrices.sol';\\nimport './IJBSingleTokenPaymentTerminal.sol';\\n\\ninterface IJBSingleTokenPaymentTerminalStore {\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function prices() external view returns (IJBPrices);\\n\\n function balanceOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\\n external\\n view\\n returns (uint256);\\n\\n function usedDistributionLimitOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _fundingCycleNumber\\n ) external view returns (uint256);\\n\\n function usedOverflowAllowanceOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _fundingCycleConfiguration\\n ) external view returns (uint256);\\n\\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\\n external\\n view\\n returns (uint256);\\n\\n function currentTotalOverflowOf(\\n uint256 _projectId,\\n uint256 _decimals,\\n uint256 _currency\\n ) external view returns (uint256);\\n\\n function currentReclaimableOverflowOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n bool _useTotalOverflow\\n ) external view returns (uint256);\\n\\n function currentReclaimableOverflowOf(\\n uint256 _projectId,\\n uint256 _tokenCount,\\n uint256 _totalSupply,\\n uint256 _overflow\\n ) external view returns (uint256);\\n\\n function recordPaymentFrom(\\n address _payer,\\n JBTokenAmount memory _amount,\\n uint256 _projectId,\\n uint256 _baseWeightCurrency,\\n address _beneficiary,\\n string calldata _memo,\\n bytes calldata _metadata\\n )\\n external\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 tokenCount,\\n JBPayDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n );\\n\\n function recordRedemptionFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n string calldata _memo,\\n bytes calldata _metadata\\n )\\n external\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 reclaimAmount,\\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n );\\n\\n function recordDistributionFor(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n ) external returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount);\\n\\n function recordUsedAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n ) external returns (JBFundingCycle memory fundingCycle, uint256 withdrawnAmount);\\n\\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external;\\n\\n function recordMigration(uint256 _projectId) external returns (uint256 balance);\\n}\\n\",\"keccak256\":\"0xd78929c9371fd7895b829ef5e4ad4b3786523c3580ac3f6f5f25d2b5941c0dd3\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSplitAllocator.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport '../structs/JBSplitAllocationData.sol';\\n\\n/**\\n @title\\n Split allocator\\n\\n @notice\\n Provide a way to process a single split with extra logic\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n\\n @dev\\n The contract address should be set as an allocator in the adequate split\\n*/\\ninterface IJBSplitAllocator is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.distributePayoutOf(..), during the processing of the split including it\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control. The token and/or eth are optimistically transfered\\n to the allocator for its logic.\\n \\n @param _data the data passed by the terminal, as a JBSplitAllocationData struct:\\n address token;\\n uint256 amount;\\n uint256 decimals;\\n uint256 projectId;\\n uint256 group;\\n JBSplit split;\\n */\\n function allocate(JBSplitAllocationData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0x5efb6f51fc161f42ff58989386ad99028e4039a0ba897d66f358c3dfcf686105\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSplitsStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBGroupedSplits.sol';\\nimport './../structs/JBSplit.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBProjects.sol';\\n\\ninterface IJBSplitsStore {\\n event SetSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n address caller\\n );\\n\\n function projects() external view returns (IJBProjects);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function splitsOf(\\n uint256 _projectId,\\n uint256 _domain,\\n uint256 _group\\n ) external view returns (JBSplit[] memory);\\n\\n function set(\\n uint256 _projectId,\\n uint256 _domain,\\n JBGroupedSplits[] memory _groupedSplits\\n ) external;\\n}\\n\",\"keccak256\":\"0x66dab3dd394e318b850401ca92c2963b906cc0ad5562fa5d4f6f850175d1c77a\",\"license\":\"MIT\"},\"contracts/interfaces/IJBToken.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBToken {\\n function projectId() external view returns (uint256);\\n\\n function decimals() external view returns (uint8);\\n\\n function totalSupply(uint256 _projectId) external view returns (uint256);\\n\\n function balanceOf(address _account, uint256 _projectId) external view returns (uint256);\\n\\n function mint(\\n uint256 _projectId,\\n address _account,\\n uint256 _amount\\n ) external;\\n\\n function burn(\\n uint256 _projectId,\\n address _account,\\n uint256 _amount\\n ) external;\\n\\n function approve(\\n uint256,\\n address _spender,\\n uint256 _amount\\n ) external;\\n\\n function transfer(\\n uint256 _projectId,\\n address _to,\\n uint256 _amount\\n ) external;\\n\\n function transferFrom(\\n uint256 _projectId,\\n address _from,\\n address _to,\\n uint256 _amount\\n ) external;\\n}\\n\",\"keccak256\":\"0xe8969210417736c85d71101bf1c0bd8ebbf9d1e62a93e758148bd5709a6c7097\",\"license\":\"MIT\"},\"contracts/interfaces/IJBTokenStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBProjects.sol';\\nimport './IJBToken.sol';\\n\\ninterface IJBTokenStore {\\n event Issue(\\n uint256 indexed projectId,\\n IJBToken indexed token,\\n string name,\\n string symbol,\\n address caller\\n );\\n\\n event Mint(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 amount,\\n bool tokensWereClaimed,\\n bool preferClaimedTokens,\\n address caller\\n );\\n\\n event Burn(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 amount,\\n uint256 initialUnclaimedBalance,\\n uint256 initialClaimedBalance,\\n bool preferClaimedTokens,\\n address caller\\n );\\n\\n event Claim(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 initialUnclaimedBalance,\\n uint256 amount,\\n address caller\\n );\\n\\n event Set(uint256 indexed projectId, IJBToken indexed newToken, address caller);\\n\\n event Transfer(\\n address indexed holder,\\n uint256 indexed projectId,\\n address indexed recipient,\\n uint256 amount,\\n address caller\\n );\\n\\n function tokenOf(uint256 _projectId) external view returns (IJBToken);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function unclaimedBalanceOf(address _holder, uint256 _projectId) external view returns (uint256);\\n\\n function unclaimedTotalSupplyOf(uint256 _projectId) external view returns (uint256);\\n\\n function totalSupplyOf(uint256 _projectId) external view returns (uint256);\\n\\n function balanceOf(address _holder, uint256 _projectId) external view returns (uint256 _result);\\n\\n function issueFor(\\n uint256 _projectId,\\n string calldata _name,\\n string calldata _symbol\\n ) external returns (IJBToken token);\\n\\n function setFor(uint256 _projectId, IJBToken _token) external;\\n\\n function burnFrom(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function mintFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function claimFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount\\n ) external;\\n\\n function transferFrom(\\n address _holder,\\n uint256 _projectId,\\n address _recipient,\\n uint256 _amount\\n ) external;\\n}\\n\",\"keccak256\":\"0x98459e3af050d41dfeffdc97f1c93330207ba450f8ff3613224b49a89eeca9c6\",\"license\":\"MIT\"},\"contracts/interfaces/IJBTokenUriResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBTokenUriResolver {\\n function getUri(uint256 _projectId) external view returns (string memory tokenUri);\\n}\\n\",\"keccak256\":\"0xd267fd8ca7c21c2c71794acdb9a98314c33a35fc559e0bf0897a6686d196d174\",\"license\":\"MIT\"},\"contracts/libraries/JBConstants.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/**\\n @notice\\n Global constants used across Juicebox contracts.\\n*/\\nlibrary JBConstants {\\n uint256 public constant MAX_RESERVED_RATE = 10_000;\\n uint256 public constant MAX_REDEMPTION_RATE = 10_000;\\n uint256 public constant MAX_DISCOUNT_RATE = 1_000_000_000;\\n uint256 public constant SPLITS_TOTAL_PERCENT = 1_000_000_000;\\n uint256 public constant MAX_FEE = 1_000_000_000;\\n uint256 public constant MAX_FEE_DISCOUNT = 1_000_000_000;\\n}\\n\",\"keccak256\":\"0x34362846a1cd428a8bdedf4ab6857e11402f345cb87b994b2e7fb6d2474b808d\",\"license\":\"MIT\"},\"contracts/libraries/JBCurrencies.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBCurrencies {\\n uint256 public constant ETH = 1;\\n uint256 public constant USD = 2;\\n}\\n\",\"keccak256\":\"0x7e417ff25c173608ee4fe6d9fc3dcd5e1458c78c889af12bac47b1189a436076\",\"license\":\"MIT\"},\"contracts/libraries/JBFixedPointNumber.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nlibrary JBFixedPointNumber {\\n function adjustDecimals(\\n uint256 _value,\\n uint256 _decimals,\\n uint256 _targetDecimals\\n ) internal pure returns (uint256) {\\n // If decimals need adjusting, multiply or divide the price by the decimal adjuster to get the normalized result.\\n if (_targetDecimals == _decimals) return _value;\\n else if (_targetDecimals > _decimals) return _value * 10**(_targetDecimals - _decimals);\\n else return _value / 10**(_decimals - _targetDecimals);\\n }\\n}\\n\",\"keccak256\":\"0x18efac48269f3a3bd7e9a1c770776f950e0afa86769e6f8b128002c3b8c6742c\",\"license\":\"MIT\"},\"contracts/libraries/JBFundingCycleMetadataResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBFundingCycleMetadata.sol';\\nimport './../structs/JBGlobalFundingCycleMetadata.sol';\\nimport './JBConstants.sol';\\nimport './JBGlobalFundingCycleMetadataResolver.sol';\\n\\nlibrary JBFundingCycleMetadataResolver {\\n function global(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (JBGlobalFundingCycleMetadata memory)\\n {\\n return JBGlobalFundingCycleMetadataResolver.expandMetadata(uint8(_fundingCycle.metadata >> 8));\\n }\\n\\n function reservedRate(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n return uint256(uint16(_fundingCycle.metadata >> 24));\\n }\\n\\n function redemptionRate(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n // Redemption rate is a number 0-10000. It's inverse was stored so the most common case of 100% results in no storage needs.\\n return JBConstants.MAX_REDEMPTION_RATE - uint256(uint16(_fundingCycle.metadata >> 40));\\n }\\n\\n function ballotRedemptionRate(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (uint256)\\n {\\n // Redemption rate is a number 0-10000. It's inverse was stored so the most common case of 100% results in no storage needs.\\n return JBConstants.MAX_REDEMPTION_RATE - uint256(uint16(_fundingCycle.metadata >> 56));\\n }\\n\\n function payPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 72) & 1) == 1;\\n }\\n\\n function distributionsPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 73) & 1) == 1;\\n }\\n\\n function redeemPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 74) & 1) == 1;\\n }\\n\\n function burnPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 75) & 1) == 1;\\n }\\n\\n function mintingAllowed(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 76) & 1) == 1;\\n }\\n\\n function terminalMigrationAllowed(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 77) & 1) == 1;\\n }\\n\\n function controllerMigrationAllowed(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 78) & 1) == 1;\\n }\\n\\n function shouldHoldFees(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 79) & 1) == 1;\\n }\\n\\n function preferClaimedTokenOverride(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 80) & 1) == 1;\\n }\\n\\n function useTotalOverflowForRedemptions(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 81) & 1) == 1;\\n }\\n\\n function useDataSourceForPay(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return (_fundingCycle.metadata >> 82) & 1 == 1;\\n }\\n\\n function useDataSourceForRedeem(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return (_fundingCycle.metadata >> 83) & 1 == 1;\\n }\\n\\n function dataSource(JBFundingCycle memory _fundingCycle) internal pure returns (address) {\\n return address(uint160(_fundingCycle.metadata >> 84));\\n }\\n\\n function metadata(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n return uint256(uint8(_fundingCycle.metadata >> 244));\\n }\\n\\n /**\\n @notice\\n Pack the funding cycle metadata.\\n\\n @param _metadata The metadata to validate and pack.\\n\\n @return packed The packed uint256 of all metadata params. The first 8 bits specify the version.\\n */\\n function packFundingCycleMetadata(JBFundingCycleMetadata memory _metadata)\\n internal\\n pure\\n returns (uint256 packed)\\n {\\n // version 1 in the bits 0-7 (8 bits).\\n packed = 1;\\n // global metadta in bits 8-23 (16 bits).\\n packed |=\\n JBGlobalFundingCycleMetadataResolver.packFundingCycleGlobalMetadata(_metadata.global) <<\\n 8;\\n // reserved rate in bits 24-39 (16 bits).\\n packed |= _metadata.reservedRate << 24;\\n // redemption rate in bits 40-55 (16 bits).\\n // redemption rate is a number 0-10000. Store the reverse so the most common case of 100% results in no storage needs.\\n packed |= (JBConstants.MAX_REDEMPTION_RATE - _metadata.redemptionRate) << 40;\\n // ballot redemption rate rate in bits 56-71 (16 bits).\\n // ballot redemption rate is a number 0-10000. Store the reverse so the most common case of 100% results in no storage needs.\\n packed |= (JBConstants.MAX_REDEMPTION_RATE - _metadata.ballotRedemptionRate) << 56;\\n // pause pay in bit 72.\\n if (_metadata.pausePay) packed |= 1 << 72;\\n // pause tap in bit 73.\\n if (_metadata.pauseDistributions) packed |= 1 << 73;\\n // pause redeem in bit 74.\\n if (_metadata.pauseRedeem) packed |= 1 << 74;\\n // pause burn in bit 75.\\n if (_metadata.pauseBurn) packed |= 1 << 75;\\n // allow minting in bit 76.\\n if (_metadata.allowMinting) packed |= 1 << 76;\\n // allow terminal migration in bit 77.\\n if (_metadata.allowTerminalMigration) packed |= 1 << 77;\\n // allow controller migration in bit 78.\\n if (_metadata.allowControllerMigration) packed |= 1 << 78;\\n // hold fees in bit 79.\\n if (_metadata.holdFees) packed |= 1 << 79;\\n // prefer claimed token override in bit 80.\\n if (_metadata.preferClaimedTokenOverride) packed |= 1 << 80;\\n // useTotalOverflowForRedemptions in bit 81.\\n if (_metadata.useTotalOverflowForRedemptions) packed |= 1 << 81;\\n // use pay data source in bit 82.\\n if (_metadata.useDataSourceForPay) packed |= 1 << 82;\\n // use redeem data source in bit 83.\\n if (_metadata.useDataSourceForRedeem) packed |= 1 << 83;\\n // data source address in bits 84-243.\\n packed |= uint256(uint160(address(_metadata.dataSource))) << 84;\\n // metadata in bits 244-252 (8 bits).\\n packed |= _metadata.metadata << 244;\\n }\\n\\n /**\\n @notice\\n Expand the funding cycle metadata.\\n\\n @param _fundingCycle The funding cycle having its metadata expanded.\\n\\n @return metadata The metadata object.\\n */\\n function expandMetadata(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (JBFundingCycleMetadata memory)\\n {\\n return\\n JBFundingCycleMetadata(\\n global(_fundingCycle),\\n reservedRate(_fundingCycle),\\n redemptionRate(_fundingCycle),\\n ballotRedemptionRate(_fundingCycle),\\n payPaused(_fundingCycle),\\n distributionsPaused(_fundingCycle),\\n redeemPaused(_fundingCycle),\\n burnPaused(_fundingCycle),\\n mintingAllowed(_fundingCycle),\\n terminalMigrationAllowed(_fundingCycle),\\n controllerMigrationAllowed(_fundingCycle),\\n shouldHoldFees(_fundingCycle),\\n preferClaimedTokenOverride(_fundingCycle),\\n useTotalOverflowForRedemptions(_fundingCycle),\\n useDataSourceForPay(_fundingCycle),\\n useDataSourceForRedeem(_fundingCycle),\\n dataSource(_fundingCycle),\\n metadata(_fundingCycle)\\n );\\n }\\n}\\n\",\"keccak256\":\"0x3d045c38593102cfb6ac67f3ddf2232e1ff5518d6d021423ae2681387599fbd3\",\"license\":\"MIT\"},\"contracts/libraries/JBGlobalFundingCycleMetadataResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport './../structs/JBFundingCycleMetadata.sol';\\n\\nlibrary JBGlobalFundingCycleMetadataResolver {\\n function setTerminalsAllowed(uint8 _data) internal pure returns (bool) {\\n return (_data & 1) == 1;\\n }\\n\\n function setControllerAllowed(uint8 _data) internal pure returns (bool) {\\n return ((_data >> 1) & 1) == 1;\\n }\\n\\n function transfersPaused(uint8 _data) internal pure returns (bool) {\\n return ((_data >> 2) & 1) == 1;\\n }\\n\\n /**\\n @notice\\n Pack the global funding cycle metadata.\\n\\n @param _metadata The metadata to validate and pack.\\n\\n @return packed The packed uint256 of all global metadata params. The first 8 bits specify the version.\\n */\\n function packFundingCycleGlobalMetadata(JBGlobalFundingCycleMetadata memory _metadata)\\n internal\\n pure\\n returns (uint256 packed)\\n {\\n // allow set terminals in bit 0.\\n if (_metadata.allowSetTerminals) packed |= 1;\\n // allow set controller in bit 1.\\n if (_metadata.allowSetController) packed |= 1 << 1;\\n // pause transfers in bit 2.\\n if (_metadata.pauseTransfers) packed |= 1 << 2;\\n }\\n\\n /**\\n @notice\\n Expand the global funding cycle metadata.\\n\\n @param _packedMetadata The packed metadata to expand.\\n\\n @return metadata The global metadata object.\\n */\\n function expandMetadata(uint8 _packedMetadata)\\n internal\\n pure\\n returns (JBGlobalFundingCycleMetadata memory metadata)\\n {\\n return\\n JBGlobalFundingCycleMetadata(\\n setTerminalsAllowed(_packedMetadata),\\n setControllerAllowed(_packedMetadata),\\n transfersPaused(_packedMetadata)\\n );\\n }\\n}\\n\",\"keccak256\":\"0x0d998f938026edeb755987a79421267cf860801161b5f171206a200b60f1061f\",\"license\":\"MIT\"},\"contracts/libraries/JBOperations.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBOperations {\\n uint256 public constant RECONFIGURE = 1;\\n uint256 public constant REDEEM = 2;\\n uint256 public constant MIGRATE_CONTROLLER = 3;\\n uint256 public constant MIGRATE_TERMINAL = 4;\\n uint256 public constant PROCESS_FEES = 5;\\n uint256 public constant SET_METADATA = 6;\\n uint256 public constant ISSUE = 7;\\n uint256 public constant SET_TOKEN = 8;\\n uint256 public constant MINT = 9;\\n uint256 public constant BURN = 10;\\n uint256 public constant CLAIM = 11;\\n uint256 public constant TRANSFER = 12;\\n uint256 public constant REQUIRE_CLAIM = 13; // unused in v3\\n uint256 public constant SET_CONTROLLER = 14;\\n uint256 public constant SET_TERMINALS = 15;\\n uint256 public constant SET_PRIMARY_TERMINAL = 16;\\n uint256 public constant USE_ALLOWANCE = 17;\\n uint256 public constant SET_SPLITS = 18;\\n}\\n\",\"keccak256\":\"0x7f8e501e6890297f4015b1c27cebdb44fadbf21204bea1f3162f5388c060f690\",\"license\":\"MIT\"},\"contracts/libraries/JBSplitsGroups.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBSplitsGroups {\\n uint256 public constant ETH_PAYOUT = 1;\\n uint256 public constant RESERVED_TOKENS = 2;\\n}\\n\",\"keccak256\":\"0x4183db6087bd8db645fc3a0d3d8afb0d6356e003650793f63c301ebbbae47269\",\"license\":\"MIT\"},\"contracts/libraries/JBTokens.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBTokens {\\n /** \\n @notice \\n The ETH token address in Juicebox is represented by 0x000000000000000000000000000000000000EEEe.\\n */\\n address public constant ETH = address(0x000000000000000000000000000000000000EEEe);\\n}\\n\",\"keccak256\":\"0xecf82992f7b827766aa55f16872517a646521eef414d8cc9786617ea377e5463\",\"license\":\"MIT\"},\"contracts/structs/JBDidPayData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member payer The address from which the payment originated.\\n @member projectId The ID of the project for which the payment was made.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the payment is being made.\\n @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.\\n @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.\\n @member projectTokenCount The number of project tokens minted for the beneficiary.\\n @member beneficiary The address to which the tokens were minted.\\n @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.\\n @member memo The memo that is being emitted alongside the payment.\\n @member metadata Extra data to send to the delegate.\\n*/\\nstruct JBDidPayData {\\n address payer;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n JBTokenAmount amount;\\n JBTokenAmount forwardedAmount;\\n uint256 projectTokenCount;\\n address beneficiary;\\n bool preferClaimedTokens;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0xf3c664309b37790f16047ae97b0459889ae0242dfcde7fc8902c8d10c7f8e6b6\",\"license\":\"MIT\"},\"contracts/structs/JBDidRedeemData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member holder The holder of the tokens being redeemed.\\n @member projectId The ID of the project with which the redeemed tokens are associated.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the redemption is being made.\\n @member projectTokenCount The number of project tokens being redeemed.\\n @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.\\n @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.\\n @member beneficiary The address to which the reclaimed amount will be sent.\\n @member memo The memo that is being emitted alongside the redemption.\\n @member metadata Extra data to send to the delegate.\\n*/\\nstruct JBDidRedeemData {\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 projectTokenCount;\\n JBTokenAmount reclaimedAmount;\\n JBTokenAmount forwardedAmount;\\n address payable beneficiary;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0xe2c401f39723a7ce915b8bef328744c66daaf57460843964b941456c2258a412\",\"license\":\"MIT\"},\"contracts/structs/JBFee.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member amount The total amount the fee was taken from, as a fixed point number with the same number of decimals as the terminal in which this struct was created.\\n @member fee The percent of the fee, out of MAX_FEE.\\n @member feeDiscount The discount of the fee.\\n @member beneficiary The address that will receive the tokens that are minted as a result of the fee payment.\\n*/\\nstruct JBFee {\\n uint256 amount;\\n uint32 fee;\\n uint32 feeDiscount;\\n address beneficiary;\\n}\\n\",\"keccak256\":\"0xf4759ff41fe7f1db0fd1ccc7b2a326b239389fd8d69df9b9ed5e1d5926f6fe38\",\"license\":\"MIT\"},\"contracts/structs/JBFundAccessConstraints.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBPaymentTerminal.sol';\\n\\n/** \\n @member terminal The terminal within which the distribution limit and the overflow allowance applies.\\n @member token The token for which the fund access constraints apply.\\n @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.\\n @member distributionLimitCurrency The currency of the distribution limit.\\n @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.\\n @member overflowAllowanceCurrency The currency of the overflow allowance.\\n*/\\nstruct JBFundAccessConstraints {\\n IJBPaymentTerminal terminal;\\n address token;\\n uint256 distributionLimit;\\n uint256 distributionLimitCurrency;\\n uint256 overflowAllowance;\\n uint256 overflowAllowanceCurrency;\\n}\\n\",\"keccak256\":\"0x85ebaa57b788cbdedc7a3d0eec4892eda5d79db7c1a6103797f10d0d989775b2\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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.\\n @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.\\n @member basedOn The `configuration` of the funding cycle that was active when this cycle was created.\\n @member start The timestamp marking the moment from which the funding cycle is considered active. It is a unix timestamp measured in seconds.\\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n @member metadata Extra data that can be associated with a funding cycle.\\n*/\\nstruct JBFundingCycle {\\n uint256 number;\\n uint256 configuration;\\n uint256 basedOn;\\n uint256 start;\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n uint256 metadata;\\n}\\n\",\"keccak256\":\"0xcdd3ac9b6fa67e62ada88d09b73bc35ade1cd77d43db712289266a788928b4c2\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycleData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n*/\\nstruct JBFundingCycleData {\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n}\\n\",\"keccak256\":\"0x2aa6368bf4dfc5797e8b02a978293de0c777fae2658de2c825a103587240f3b0\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycleMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBGlobalFundingCycleMetadata.sol';\\n\\n/** \\n @member global Data used globally in non-migratable ecosystem contracts.\\n @member reservedRate The reserved rate of the funding cycle. This number is a percentage calculated out of `JBConstants.MAX_RESERVED_RATE`.\\n @member redemptionRate The redemption rate of the funding cycle. This number is a percentage calculated out of `JBConstants.MAX_REDEMPTION_RATE`.\\n @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`.\\n @member pausePay A flag indicating if the pay functionality should be paused during the funding cycle.\\n @member pauseDistributions A flag indicating if the distribute functionality should be paused during the funding cycle.\\n @member pauseRedeem A flag indicating if the redeem functionality should be paused during the funding cycle.\\n @member pauseBurn A flag indicating if the burn functionality should be paused during the funding cycle.\\n @member allowMinting A flag indicating if minting tokens should be allowed during this funding cycle.\\n @member allowTerminalMigration A flag indicating if migrating terminals should be allowed during this funding cycle.\\n @member allowControllerMigration A flag indicating if migrating controllers should be allowed during this funding cycle.\\n @member holdFees A flag indicating if fees should be held during this funding cycle.\\n @member preferClaimedTokenOverride A flag indicating if claimed tokens should always be prefered to unclaimed tokens when minting.\\n @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.\\n @member useDataSourceForPay A flag indicating if the data source should be used for pay transactions during this funding cycle.\\n @member useDataSourceForRedeem A flag indicating if the data source should be used for redeem transactions during this funding cycle.\\n @member dataSource The data source to use during this funding cycle.\\n @member metadata Metadata of the metadata, up to uint8 in size.\\n*/\\nstruct JBFundingCycleMetadata {\\n JBGlobalFundingCycleMetadata global;\\n uint256 reservedRate;\\n uint256 redemptionRate;\\n uint256 ballotRedemptionRate;\\n bool pausePay;\\n bool pauseDistributions;\\n bool pauseRedeem;\\n bool pauseBurn;\\n bool allowMinting;\\n bool allowTerminalMigration;\\n bool allowControllerMigration;\\n bool holdFees;\\n bool preferClaimedTokenOverride;\\n bool useTotalOverflowForRedemptions;\\n bool useDataSourceForPay;\\n bool useDataSourceForRedeem;\\n address dataSource;\\n uint256 metadata;\\n}\\n\",\"keccak256\":\"0x783604440cac8d176332eab28166f188ee5c230378c08cfc95fea4f7187dc77d\",\"license\":\"MIT\"},\"contracts/structs/JBGlobalFundingCycleMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member allowSetTerminals A flag indicating if setting terminals should be allowed during this funding cycle.\\n @member allowSetController A flag indicating if setting a new controller should be allowed during this funding cycle.\\n @member pauseTransfers A flag indicating if the project token transfer functionality should be paused during the funding cycle.\\n*/\\nstruct JBGlobalFundingCycleMetadata {\\n bool allowSetTerminals;\\n bool allowSetController;\\n bool pauseTransfers;\\n}\\n\",\"keccak256\":\"0x05d85530305fec6d6eca54cdbc2cd9110cbda0146598032b0203aa4b622944ff\",\"license\":\"MIT\"},\"contracts/structs/JBGroupedSplits.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBSplit.sol';\\n\\n/** \\n @member group The group indentifier.\\n @member splits The splits to associate with the group.\\n*/\\nstruct JBGroupedSplits {\\n uint256 group;\\n JBSplit[] splits;\\n}\\n\",\"keccak256\":\"0x80be1b220da4ac04851ea540ebb94c1ec2b0442ec5bd1e88fdf78a56becd8b5a\",\"license\":\"MIT\"},\"contracts/structs/JBOperatorData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member operator The address of the operator.\\n @member domain The domain within which the operator is being given permissions. A domain of 0 is a wildcard domain, which gives an operator access to all domains.\\n @member permissionIndexes The indexes of the permissions the operator is being given.\\n*/\\nstruct JBOperatorData {\\n address operator;\\n uint256 domain;\\n uint256[] permissionIndexes;\\n}\\n\",\"keccak256\":\"0x3b85be7b69515976ee10770776283911666aceca820b0cf4e201ea4dbffeb6f0\",\"license\":\"MIT\"},\"contracts/structs/JBPayDelegateAllocation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '../interfaces/IJBPayDelegate.sol';\\n\\n/** \\n @member delegate A delegate contract to use for subsequent calls.\\n @member amount The amount to send to the delegate.\\n*/\\nstruct JBPayDelegateAllocation {\\n IJBPayDelegate delegate;\\n uint256 amount;\\n}\\n\",\"keccak256\":\"0xb4e558dc62231d89e9b48998012577d22c3e52b58e23401f22d9096827f6ea0c\",\"license\":\"MIT\"},\"contracts/structs/JBProjectMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member content The metadata content.\\n @member domain The domain within which the metadata applies.\\n*/\\nstruct JBProjectMetadata {\\n string content;\\n uint256 domain;\\n}\\n\",\"keccak256\":\"0x90ad7b1014c0a9f945fe7a2efde9d5de41e40574fa27969070b1d2ff52033ea0\",\"license\":\"MIT\"},\"contracts/structs/JBRedemptionDelegateAllocation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '../interfaces/IJBRedemptionDelegate.sol';\\n\\n/** \\n @member delegate A delegate contract to use for subsequent calls.\\n @member amount The amount to send to the delegate.\\n*/\\nstruct JBRedemptionDelegateAllocation {\\n IJBRedemptionDelegate delegate;\\n uint256 amount;\\n}\\n\",\"keccak256\":\"0x10c29d33dd0d875a0d4692a2b9a9355c2ebf433cc06a9a60253d4366b60d4d31\",\"license\":\"MIT\"},\"contracts/structs/JBSplit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBSplitAllocator.sol';\\n\\n/** \\n @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.\\n @member preferAddToBalance A flag indicating if a distribution to a project should prefer triggering it's addToBalance function instead of its pay function.\\n @member percent The percent of the whole group that this split occupies. This number is out of `JBConstants.SPLITS_TOTAL_PERCENT`.\\n @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.\\n @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.\\n @member lockedUntil Specifies if the split should be unchangeable until the specified time, with the exception of extending the locked period.\\n @member allocator If an allocator is specified, funds will be sent to the allocator contract along with all properties of this split.\\n*/\\nstruct JBSplit {\\n bool preferClaimed;\\n bool preferAddToBalance;\\n uint256 percent;\\n uint256 projectId;\\n address payable beneficiary;\\n uint256 lockedUntil;\\n IJBSplitAllocator allocator;\\n}\\n\",\"keccak256\":\"0xc80a16606da8abf76d0f73abc38aee041e24f29342c1939018f70c286e89f105\",\"license\":\"MIT\"},\"contracts/structs/JBSplitAllocationData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBSplit.sol';\\n\\n/** \\n @member token The token being sent to the split allocator.\\n @member amount The amount being sent to the split allocator, as a fixed point number.\\n @member decimals The number of decimals in the amount.\\n @member projectId The project to which the split belongs.\\n @member group The group to which the split belongs.\\n @member split The split that caused the allocation.\\n*/\\nstruct JBSplitAllocationData {\\n address token;\\n uint256 amount;\\n uint256 decimals;\\n uint256 projectId;\\n uint256 group;\\n JBSplit split;\\n}\\n\",\"keccak256\":\"0x39f5c41bd31d36774744698ac94484b6cab62d7038df2f29d947668959782e63\",\"license\":\"MIT\"},\"contracts/structs/JBTokenAmount.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/* \\n @member token The token the payment was made in.\\n @member value The amount of tokens that was paid, as a fixed point number.\\n @member decimals The number of decimals included in the value fixed point number.\\n @member currency The expected currency of the value.\\n**/\\nstruct JBTokenAmount {\\n address token;\\n uint256 value;\\n uint256 decimals;\\n uint256 currency;\\n}\\n\",\"keccak256\":\"0x4a778e779ba257ba5638c5469e07a4d21b55a3128d56db5a0fdfacb1f3301c51\",\"license\":\"MIT\"},\"prb-math/contracts/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivFixedPointOverflow(uint256 prod1);\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivOverflow(uint256 prod1, uint256 denominator);\\n\\n/// @notice Emitted when one of the inputs is type(int256).min.\\nerror PRBMath__MulDivSignedInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows int256.\\nerror PRBMath__MulDivSignedOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is MIN_SD59x18.\\nerror PRBMathSD59x18__AbsInputTooSmall();\\n\\n/// @notice Emitted when ceiling a number overflows SD59x18.\\nerror PRBMathSD59x18__CeilOverflow(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__DivInputTooSmall();\\n\\n/// @notice Emitted when one of the intermediary unsigned results overflows SD59x18.\\nerror PRBMathSD59x18__DivOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathSD59x18__ExpInputTooBig(int256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathSD59x18__Exp2InputTooBig(int256 x);\\n\\n/// @notice Emitted when flooring a number underflows SD59x18.\\nerror PRBMathSD59x18__FloorUnderflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format overflows SD59x18.\\nerror PRBMathSD59x18__FromIntOverflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format underflows SD59x18.\\nerror PRBMathSD59x18__FromIntUnderflow(int256 x);\\n\\n/// @notice Emitted when the product of the inputs is negative.\\nerror PRBMathSD59x18__GmNegativeProduct(int256 x, int256 y);\\n\\n/// @notice Emitted when multiplying the inputs overflows SD59x18.\\nerror PRBMathSD59x18__GmOverflow(int256 x, int256 y);\\n\\n/// @notice Emitted when the input is less than or equal to zero.\\nerror PRBMathSD59x18__LogInputTooSmall(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__MulInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__MulOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__PowuOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is negative.\\nerror PRBMathSD59x18__SqrtNegativeInput(int256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows SD59x18.\\nerror PRBMathSD59x18__SqrtOverflow(int256 x);\\n\\n/// @notice Emitted when addition overflows UD60x18.\\nerror PRBMathUD60x18__AddOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when ceiling a number overflows UD60x18.\\nerror PRBMathUD60x18__CeilOverflow(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathUD60x18__ExpInputTooBig(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathUD60x18__Exp2InputTooBig(uint256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format format overflows UD60x18.\\nerror PRBMathUD60x18__FromUintOverflow(uint256 x);\\n\\n/// @notice Emitted when multiplying the inputs overflows UD60x18.\\nerror PRBMathUD60x18__GmOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when the input is less than 1.\\nerror PRBMathUD60x18__LogInputTooSmall(uint256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows UD60x18.\\nerror PRBMathUD60x18__SqrtOverflow(uint256 x);\\n\\n/// @notice Emitted when subtraction underflows UD60x18.\\nerror PRBMathUD60x18__SubUnderflow(uint256 x, uint256 y);\\n\\n/// @dev Common mathematical functions used in both PRBMathSD59x18 and PRBMathUD60x18. Note that this shared library\\n/// does not always assume the signed 59.18-decimal fixed-point or the unsigned 60.18-decimal fixed-point\\n/// representation. When it does not, it is explicitly mentioned in the NatSpec documentation.\\nlibrary PRBMath {\\n /// STRUCTS ///\\n\\n struct SD59x18 {\\n int256 value;\\n }\\n\\n struct UD60x18 {\\n uint256 value;\\n }\\n\\n /// STORAGE ///\\n\\n /// @dev How many trailing decimals can be represented.\\n uint256 internal constant SCALE = 1e18;\\n\\n /// @dev Largest power of two divisor of SCALE.\\n uint256 internal constant SCALE_LPOTD = 262144;\\n\\n /// @dev SCALE inverted mod 2^256.\\n uint256 internal constant SCALE_INVERSE =\\n 78156646155174841979727994598816262306175212592076161876661_508869554232690281;\\n\\n /// FUNCTIONS ///\\n\\n /// @notice Calculates the binary exponent of x using the binary fraction method.\\n /// @dev Has to use 192.64-bit fixed-point numbers.\\n /// See https://ethereum.stackexchange.com/a/96594/24693.\\n /// @param x The exponent as an unsigned 192.64-bit fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp2(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n // Start from 0.5 in the 192.64-bit fixed-point format.\\n result = 0x800000000000000000000000000000000000000000000000;\\n\\n // Multiply the result by root(2, 2^-i) when the bit at position i is 1. None of the intermediary results overflows\\n // because the initial result is 2^191 and all magic factors are less than 2^65.\\n if (x & 0x8000000000000000 > 0) {\\n result = (result * 0x16A09E667F3BCC909) >> 64;\\n }\\n if (x & 0x4000000000000000 > 0) {\\n result = (result * 0x1306FE0A31B7152DF) >> 64;\\n }\\n if (x & 0x2000000000000000 > 0) {\\n result = (result * 0x1172B83C7D517ADCE) >> 64;\\n }\\n if (x & 0x1000000000000000 > 0) {\\n result = (result * 0x10B5586CF9890F62A) >> 64;\\n }\\n if (x & 0x800000000000000 > 0) {\\n result = (result * 0x1059B0D31585743AE) >> 64;\\n }\\n if (x & 0x400000000000000 > 0) {\\n result = (result * 0x102C9A3E778060EE7) >> 64;\\n }\\n if (x & 0x200000000000000 > 0) {\\n result = (result * 0x10163DA9FB33356D8) >> 64;\\n }\\n if (x & 0x100000000000000 > 0) {\\n result = (result * 0x100B1AFA5ABCBED61) >> 64;\\n }\\n if (x & 0x80000000000000 > 0) {\\n result = (result * 0x10058C86DA1C09EA2) >> 64;\\n }\\n if (x & 0x40000000000000 > 0) {\\n result = (result * 0x1002C605E2E8CEC50) >> 64;\\n }\\n if (x & 0x20000000000000 > 0) {\\n result = (result * 0x100162F3904051FA1) >> 64;\\n }\\n if (x & 0x10000000000000 > 0) {\\n result = (result * 0x1000B175EFFDC76BA) >> 64;\\n }\\n if (x & 0x8000000000000 > 0) {\\n result = (result * 0x100058BA01FB9F96D) >> 64;\\n }\\n if (x & 0x4000000000000 > 0) {\\n result = (result * 0x10002C5CC37DA9492) >> 64;\\n }\\n if (x & 0x2000000000000 > 0) {\\n result = (result * 0x1000162E525EE0547) >> 64;\\n }\\n if (x & 0x1000000000000 > 0) {\\n result = (result * 0x10000B17255775C04) >> 64;\\n }\\n if (x & 0x800000000000 > 0) {\\n result = (result * 0x1000058B91B5BC9AE) >> 64;\\n }\\n if (x & 0x400000000000 > 0) {\\n result = (result * 0x100002C5C89D5EC6D) >> 64;\\n }\\n if (x & 0x200000000000 > 0) {\\n result = (result * 0x10000162E43F4F831) >> 64;\\n }\\n if (x & 0x100000000000 > 0) {\\n result = (result * 0x100000B1721BCFC9A) >> 64;\\n }\\n if (x & 0x80000000000 > 0) {\\n result = (result * 0x10000058B90CF1E6E) >> 64;\\n }\\n if (x & 0x40000000000 > 0) {\\n result = (result * 0x1000002C5C863B73F) >> 64;\\n }\\n if (x & 0x20000000000 > 0) {\\n result = (result * 0x100000162E430E5A2) >> 64;\\n }\\n if (x & 0x10000000000 > 0) {\\n result = (result * 0x1000000B172183551) >> 64;\\n }\\n if (x & 0x8000000000 > 0) {\\n result = (result * 0x100000058B90C0B49) >> 64;\\n }\\n if (x & 0x4000000000 > 0) {\\n result = (result * 0x10000002C5C8601CC) >> 64;\\n }\\n if (x & 0x2000000000 > 0) {\\n result = (result * 0x1000000162E42FFF0) >> 64;\\n }\\n if (x & 0x1000000000 > 0) {\\n result = (result * 0x10000000B17217FBB) >> 64;\\n }\\n if (x & 0x800000000 > 0) {\\n result = (result * 0x1000000058B90BFCE) >> 64;\\n }\\n if (x & 0x400000000 > 0) {\\n result = (result * 0x100000002C5C85FE3) >> 64;\\n }\\n if (x & 0x200000000 > 0) {\\n result = (result * 0x10000000162E42FF1) >> 64;\\n }\\n if (x & 0x100000000 > 0) {\\n result = (result * 0x100000000B17217F8) >> 64;\\n }\\n if (x & 0x80000000 > 0) {\\n result = (result * 0x10000000058B90BFC) >> 64;\\n }\\n if (x & 0x40000000 > 0) {\\n result = (result * 0x1000000002C5C85FE) >> 64;\\n }\\n if (x & 0x20000000 > 0) {\\n result = (result * 0x100000000162E42FF) >> 64;\\n }\\n if (x & 0x10000000 > 0) {\\n result = (result * 0x1000000000B17217F) >> 64;\\n }\\n if (x & 0x8000000 > 0) {\\n result = (result * 0x100000000058B90C0) >> 64;\\n }\\n if (x & 0x4000000 > 0) {\\n result = (result * 0x10000000002C5C860) >> 64;\\n }\\n if (x & 0x2000000 > 0) {\\n result = (result * 0x1000000000162E430) >> 64;\\n }\\n if (x & 0x1000000 > 0) {\\n result = (result * 0x10000000000B17218) >> 64;\\n }\\n if (x & 0x800000 > 0) {\\n result = (result * 0x1000000000058B90C) >> 64;\\n }\\n if (x & 0x400000 > 0) {\\n result = (result * 0x100000000002C5C86) >> 64;\\n }\\n if (x & 0x200000 > 0) {\\n result = (result * 0x10000000000162E43) >> 64;\\n }\\n if (x & 0x100000 > 0) {\\n result = (result * 0x100000000000B1721) >> 64;\\n }\\n if (x & 0x80000 > 0) {\\n result = (result * 0x10000000000058B91) >> 64;\\n }\\n if (x & 0x40000 > 0) {\\n result = (result * 0x1000000000002C5C8) >> 64;\\n }\\n if (x & 0x20000 > 0) {\\n result = (result * 0x100000000000162E4) >> 64;\\n }\\n if (x & 0x10000 > 0) {\\n result = (result * 0x1000000000000B172) >> 64;\\n }\\n if (x & 0x8000 > 0) {\\n result = (result * 0x100000000000058B9) >> 64;\\n }\\n if (x & 0x4000 > 0) {\\n result = (result * 0x10000000000002C5D) >> 64;\\n }\\n if (x & 0x2000 > 0) {\\n result = (result * 0x1000000000000162E) >> 64;\\n }\\n if (x & 0x1000 > 0) {\\n result = (result * 0x10000000000000B17) >> 64;\\n }\\n if (x & 0x800 > 0) {\\n result = (result * 0x1000000000000058C) >> 64;\\n }\\n if (x & 0x400 > 0) {\\n result = (result * 0x100000000000002C6) >> 64;\\n }\\n if (x & 0x200 > 0) {\\n result = (result * 0x10000000000000163) >> 64;\\n }\\n if (x & 0x100 > 0) {\\n result = (result * 0x100000000000000B1) >> 64;\\n }\\n if (x & 0x80 > 0) {\\n result = (result * 0x10000000000000059) >> 64;\\n }\\n if (x & 0x40 > 0) {\\n result = (result * 0x1000000000000002C) >> 64;\\n }\\n if (x & 0x20 > 0) {\\n result = (result * 0x10000000000000016) >> 64;\\n }\\n if (x & 0x10 > 0) {\\n result = (result * 0x1000000000000000B) >> 64;\\n }\\n if (x & 0x8 > 0) {\\n result = (result * 0x10000000000000006) >> 64;\\n }\\n if (x & 0x4 > 0) {\\n result = (result * 0x10000000000000003) >> 64;\\n }\\n if (x & 0x2 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n if (x & 0x1 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n\\n // We're doing two things at the same time:\\n //\\n // 1. Multiply the result by 2^n + 1, where \\\"2^n\\\" is the integer part and the one is added to account for\\n // the fact that we initially set the result to 0.5. This is accomplished by subtracting from 191\\n // rather than 192.\\n // 2. Convert the result to the unsigned 60.18-decimal fixed-point format.\\n //\\n // This works because 2^(191-ip) = 2^ip / 2^191, where \\\"ip\\\" is the integer part \\\"2^n\\\".\\n result *= SCALE;\\n result >>= (191 - (x >> 64));\\n }\\n }\\n\\n /// @notice Finds the zero-based index of the first one in the binary representation of x.\\n /// @dev See the note on msb in the \\\"Find First Set\\\" Wikipedia article https://en.wikipedia.org/wiki/Find_first_set\\n /// @param x The uint256 number for which to find the index of the most significant bit.\\n /// @return msb The index of the most significant bit as an uint256.\\n function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\\n if (x >= 2**128) {\\n x >>= 128;\\n msb += 128;\\n }\\n if (x >= 2**64) {\\n x >>= 64;\\n msb += 64;\\n }\\n if (x >= 2**32) {\\n x >>= 32;\\n msb += 32;\\n }\\n if (x >= 2**16) {\\n x >>= 16;\\n msb += 16;\\n }\\n if (x >= 2**8) {\\n x >>= 8;\\n msb += 8;\\n }\\n if (x >= 2**4) {\\n x >>= 4;\\n msb += 4;\\n }\\n if (x >= 2**2) {\\n x >>= 2;\\n msb += 2;\\n }\\n if (x >= 2**1) {\\n // No need to shift x any more.\\n msb += 1;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.\\n ///\\n /// Requirements:\\n /// - The denominator cannot be zero.\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The multiplicand as an uint256.\\n /// @param y The multiplier as an uint256.\\n /// @param denominator The divisor as an uint256.\\n /// @return result The result as an uint256.\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n unchecked {\\n result = prod0 / denominator;\\n }\\n return result;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n if (prod1 >= denominator) {\\n revert PRBMath__MulDivOverflow(prod1, denominator);\\n }\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n unchecked {\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 lpotdod = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by lpotdod.\\n denominator := div(denominator, lpotdod)\\n\\n // Divide [prod1 prod0] by lpotdod.\\n prod0 := div(prod0, lpotdod)\\n\\n // Flip lpotdod such that it is 2^256 / lpotdod. If lpotdod is zero, then it becomes one.\\n lpotdod := add(div(sub(0, lpotdod), lpotdod), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * lpotdod;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f71e18) with full precision.\\n ///\\n /// @dev Variant of \\\"mulDiv\\\" with constant folding, i.e. in which the denominator is always 1e18. Before returning the\\n /// final result, we add 1 if (x * y) % SCALE >= HALF_SCALE. Without this, 6.6e-19 would be truncated to 0 instead of\\n /// being rounded to 1e-18. See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717.\\n ///\\n /// Requirements:\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - The body is purposely left uncommented; see the NatSpec comments in \\\"PRBMath.mulDiv\\\" to understand how this works.\\n /// - It is assumed that the result can never be type(uint256).max when x and y solve the following two equations:\\n /// 1. x * y = type(uint256).max * SCALE\\n /// 2. (x * y) % SCALE >= SCALE / 2\\n ///\\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function mulDivFixedPoint(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n uint256 prod0;\\n uint256 prod1;\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n if (prod1 >= SCALE) {\\n revert PRBMath__MulDivFixedPointOverflow(prod1);\\n }\\n\\n uint256 remainder;\\n uint256 roundUpUnit;\\n assembly {\\n remainder := mulmod(x, y, SCALE)\\n roundUpUnit := gt(remainder, 499999999999999999)\\n }\\n\\n if (prod1 == 0) {\\n unchecked {\\n result = (prod0 / SCALE) + roundUpUnit;\\n return result;\\n }\\n }\\n\\n assembly {\\n result := add(\\n mul(\\n or(\\n div(sub(prod0, remainder), SCALE_LPOTD),\\n mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, SCALE_LPOTD), SCALE_LPOTD), 1))\\n ),\\n SCALE_INVERSE\\n ),\\n roundUpUnit\\n )\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev An extension of \\\"mulDiv\\\" for signed numbers. Works by computing the signs and the absolute values separately.\\n ///\\n /// Requirements:\\n /// - None of the inputs can be type(int256).min.\\n /// - The result must fit within int256.\\n ///\\n /// @param x The multiplicand as an int256.\\n /// @param y The multiplier as an int256.\\n /// @param denominator The divisor as an int256.\\n /// @return result The result as an int256.\\n function mulDivSigned(\\n int256 x,\\n int256 y,\\n int256 denominator\\n ) internal pure returns (int256 result) {\\n if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {\\n revert PRBMath__MulDivSignedInputTooSmall();\\n }\\n\\n // Get hold of the absolute values of x, y and the denominator.\\n uint256 ax;\\n uint256 ay;\\n uint256 ad;\\n unchecked {\\n ax = x < 0 ? uint256(-x) : uint256(x);\\n ay = y < 0 ? uint256(-y) : uint256(y);\\n ad = denominator < 0 ? uint256(-denominator) : uint256(denominator);\\n }\\n\\n // Compute the absolute value of (x*y)\\u00f7denominator. The result must fit within int256.\\n uint256 rAbs = mulDiv(ax, ay, ad);\\n if (rAbs > uint256(type(int256).max)) {\\n revert PRBMath__MulDivSignedOverflow(rAbs);\\n }\\n\\n // Get the signs of x, y and the denominator.\\n uint256 sx;\\n uint256 sy;\\n uint256 sd;\\n assembly {\\n sx := sgt(x, sub(0, 1))\\n sy := sgt(y, sub(0, 1))\\n sd := sgt(denominator, sub(0, 1))\\n }\\n\\n // XOR over sx, sy and sd. This is checking whether there are one or three negative signs in the inputs.\\n // If yes, the result should be negative.\\n result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs);\\n }\\n\\n /// @notice Calculates the square root of x, rounding down.\\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The uint256 number for which to calculate the square root.\\n /// @return result The result as an uint256.\\n function sqrt(uint256 x) internal pure returns (uint256 result) {\\n if (x == 0) {\\n return 0;\\n }\\n\\n // Set the initial guess to the closest power of two that is higher than x.\\n uint256 xAux = uint256(x);\\n result = 1;\\n if (xAux >= 0x100000000000000000000000000000000) {\\n xAux >>= 128;\\n result <<= 64;\\n }\\n if (xAux >= 0x10000000000000000) {\\n xAux >>= 64;\\n result <<= 32;\\n }\\n if (xAux >= 0x100000000) {\\n xAux >>= 32;\\n result <<= 16;\\n }\\n if (xAux >= 0x10000) {\\n xAux >>= 16;\\n result <<= 8;\\n }\\n if (xAux >= 0x100) {\\n xAux >>= 8;\\n result <<= 4;\\n }\\n if (xAux >= 0x10) {\\n xAux >>= 4;\\n result <<= 2;\\n }\\n if (xAux >= 0x8) {\\n result <<= 1;\\n }\\n\\n // The operations can never overflow because the result is max 2^127 when it enters this block.\\n unchecked {\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1; // Seven iterations should be enough\\n uint256 roundedDownResult = x / result;\\n return result >= roundedDownResult ? roundedDownResult : result;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x62cbabae4910e168e99b9c2c3e3b5c9c7ad5e7abd961dcc63b7ea3d83d8ea87e\",\"license\":\"Unlicense\"}},\"version\":1}", "bytecode": "0x6101e060405263017d78406002553480156200001a57600080fd5b5060405162006294380380620062948339810160408190526200003d916200020a565b61eeee6080819052601260a0819052600160c08190526001600160a01b038a1660e0528a818b8b8b8b8b8b8b6200007433620000cf565b6101a08990526101c08890526001600160a01b0380871661010052858116610120528481166101405283811661016052821661018052620000b5816200011f565b5050505050505050505050505050505050505050620002bf565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000546001600160a01b031633146200017f5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b6001600160a01b038116620001e65760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840162000176565b620001f181620000cf565b50565b6001600160a01b0381168114620001f157600080fd5b600080600080600080600080610100898b0312156200022857600080fd5b8851975060208901516200023c81620001f4565b60408a01519097506200024f81620001f4565b60608a01519096506200026281620001f4565b60808a01519095506200027581620001f4565b60a08a01519094506200028881620001f4565b60c08a01519093506200029b81620001f4565b60e08a0151909250620002ae81620001f4565b809150509295985092959890939650565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c051615d5d62000537600039600081816103ef015261246d0152600081816103270152611c9901526000818161051701528181610d08015281816115e001528181611c670152818161231b015281816129ba01528181612ab801528181612e1801528181612fb30152818161419a015261457b015260008181610676015261177e0152600081816102db01526137c601526000818161062f015281816108f6015281816109ca0152818161182301528181611d4a015281816127c5015281816130970152818161364201526142cc0152600081816104c501528181610b78015281816111ab015281816114fc015281816123c70152612b6e01526000818161058b0152818161219d01528181612244015281816125fe01526126a50152600081816102860152818161072e015281816116b00152818161172b01528181611c4101528181611f1d0152818161321601526132d501526000818161035b015281816105fb015281816116510152818161167d015281816116dd0152818161175801528181611c1b01528181611ef7015281816131f0015281816132af0152613f950152600081816106ec0152818161078201528181610a5401528181610c2901528181610d8901528181610e15015281816118b501528181611be601528181611ec201528181611fdd0152818161279a01528181612838015281816128fd015281816131ba0152818161327a015281816133570152818161361501528181613f6001528181614023015281816142f90152818161447e015281816144bc0152818161464501526146890152615d5d6000f3fe6080604052600436106102195760003560e01c80638da5cb5b1161011d578063c715967a116100b0578063df21a7dd1161007f578063f2fde38b11610064578063f2fde38b14610750578063fc0c546a14610770578063fe663f0f146107a457600080fd5b8063df21a7dd146106ce578063e5a6b10f1461071c57600080fd5b8063c715967a14610651578063d3419bf314610664578063d6dacc5314610698578063ddca3f43146106b857600080fd5b8063ad007d63116100ec578063ad007d6314610579578063b631b500146105ad578063b7bad1b1146105dd578063c41c2f241461061d57600080fd5b80638da5cb5b146104e7578063975057e714610505578063a02f801c14610539578063a32e1e961461055957600080fd5b80634a4305c0116101b0578063715018a61161017f57806389701db51161016457806389701db5146104665780638af56094146104865780638b79543c146104b357600080fd5b8063715018a6146104315780637258002c1461044657600080fd5b80634a4305c01461039d578063637913ac146103bd57806366248b86146103dd57806369fe0e2d1461041157600080fd5b80632bdfe004116101ec5780632bdfe004146102c95780632d1a590314610315578063313ce56714610349578063405b84fa1461037d57600080fd5b806301ffc9a71461021e5780630cf8e858146102535780631982d679146102685780631ebc263f146102b6575b600080fd5b34801561022a57600080fd5b5061023e61023936600461494e565b6107c4565b60405190151581526020015b60405180910390f35b6102666102613660046149d6565b6108d8565b005b34801561027457600080fd5b506102a8610283366004614a6c565b507f000000000000000000000000000000000000000000000000000000000000000090565b60405190815260200161024a565b6102a86102c4366004614a97565b6109a1565b3480156102d557600080fd5b506102fd7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161024a565b34801561032157600080fd5b506102a87f000000000000000000000000000000000000000000000000000000000000000081565b34801561035557600080fd5b506102a87f000000000000000000000000000000000000000000000000000000000000000081565b34801561038957600080fd5b506102a8610398366004614b5f565b610b5f565b3480156103a957600080fd5b506102a86103b8366004614b8f565b610ebf565b3480156103c957600080fd5b506102666103d8366004614a6c565b610edb565b3480156103e957600080fd5b506102a87f000000000000000000000000000000000000000000000000000000000000000081565b34801561041d57600080fd5b5061026661042c366004614bf9565b610f9b565b34801561043d57600080fd5b50610266611073565b34801561045257600080fd5b50610266610461366004614c12565b6110d9565b34801561047257600080fd5b50610266610481366004614bf9565b611195565b34801561049257600080fd5b506104a66104a1366004614bf9565b611431565b60405161024a9190614c40565b3480156104bf57600080fd5b506102fd7f000000000000000000000000000000000000000000000000000000000000000081565b3480156104f357600080fd5b506000546001600160a01b03166102fd565b34801561051157600080fd5b506102fd7f000000000000000000000000000000000000000000000000000000000000000081565b34801561054557600080fd5b506102a8610554366004614deb565b6114e3565b34801561056557600080fd5b506102a8610574366004614bf9565b61159e565b34801561058557600080fd5b506102fd7f000000000000000000000000000000000000000000000000000000000000000081565b3480156105b957600080fd5b5061023e6105c8366004614a6c565b60046020526000908152604090205460ff1681565b3480156105e957600080fd5b506102a86105f8366004614a6c565b507f000000000000000000000000000000000000000000000000000000000000000090565b34801561062957600080fd5b506102fd7f000000000000000000000000000000000000000000000000000000000000000081565b61026661065f366004614ea4565b611805565b34801561067057600080fd5b506102fd7f000000000000000000000000000000000000000000000000000000000000000081565b3480156106a457600080fd5b506003546102fd906001600160a01b031681565b3480156106c457600080fd5b506102a860025481565b3480156106da57600080fd5b5061023e6106e9366004614f4c565b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161490565b34801561072857600080fd5b506102a87f000000000000000000000000000000000000000000000000000000000000000081565b34801561075c57600080fd5b5061026661076b366004614a6c565b6119a7565b34801561077c57600080fd5b506102fd7f000000000000000000000000000000000000000000000000000000000000000081565b3480156107b057600080fd5b506102a86107bf366004614f78565b611a89565b60006001600160e01b031982167fedb527eb00000000000000000000000000000000000000000000000000000000148061082757506001600160e01b031982167f4a4305c000000000000000000000000000000000000000000000000000000000145b8061085b57506001600160e01b031982167fa02f801c00000000000000000000000000000000000000000000000000000000145b8061088f57506001600160e01b031982167ffe663f0f00000000000000000000000000000000000000000000000000000000145b806108c357506001600160e01b031982167fad007d6300000000000000000000000000000000000000000000000000000000145b806108d257506108d282611aa9565b92915050565b604051636e49181f60e01b81526004810188905230602482015287907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636e49181f90604401602060405180830381865afa158015610945573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109699190615031565b61098657604051631b1d5a5960e31b815260040160405180910390fd5b610997888888600089898989611805565b5050505050505050565b604051636e49181f60e01b8152600481018b90523060248201526000908b906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636e49181f90604401602060405180830381865afa158015610a11573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a359190615031565b610a5257604051631b1d5a5960e31b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661eeee14610ac1573415610aa357604051635e7e9adf60e11b815260040160405180910390fd5b47610aaf33308e611b2b565b610ab98147615064565b9b5050610ac5565b349a505b610b4f8b338e8c8c8c8c8c8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611b3a92505050565b9c9b505050505050505050505050565b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610bc7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610beb9190615077565b836004610bf9838383612156565b6040517fdf21a7dd0000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301526024820188905286169063df21a7dd90604401602060405180830381865afa158015610c7f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ca39190615031565b610cd9576040517f581010ed00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f6bb6a5ad000000000000000000000000000000000000000000000000000000008152600481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636bb6a5ad906024016020604051808303816000875af1158015610d59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d7d9190615094565b93508315610e715760007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661eeee14610dc0576000610dc2565b845b604080516020810182526000815290517f0cf8e8580000000000000000000000000000000000000000000000000000000081529192506001600160a01b03881691630cf8e858918491610e3d918c918b917f0000000000000000000000000000000000000000000000000000000000000000916004016150fd565b6000604051808303818588803b158015610e5657600080fd5b505af1158015610e6a573d6000803e3d6000fd5b5050505050505b604080518581523360208201526001600160a01b0387169188917fa7519e5f94697b7f53e97c5eb46a0c730a296ab686ab8fd333835c5f735784eb910160405180910390a350505092915050565b6000610ecf8888888787876122cf565b98975050505050505050565b6000546001600160a01b03163314610f3a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b6003805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040513381527f0a9a80fe9716605b3e52abb3d792d6a4e7816d6afc02a5a4ef023081feaf9f609060200160405180910390a250565b6000546001600160a01b03163314610ff55760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610f31565b6302faf080811115611033576040517f45fbd9c100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002819055604080518281523360208201527fd7414e590e1cb532989ab2a34c8f4c2c17f7ab6f006efeeaef2e87cd5008c202910160405180910390a150565b6000546001600160a01b031633146110cd5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610f31565b6110d76000612550565b565b6000546001600160a01b031633146111335760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610f31565b6001600160a01b038216600081815260046020908152604091829020805460ff191685151590811790915591513381529192917fa2653e25a502c023a5830d0de847ef6f458387865b1f4f575d7594f9f2c0d71e910160405180910390a35050565b6040516331a9108f60e11b8152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa1580156111fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061121e9190615077565b8160056112336000546001600160a01b031690565b6001600160a01b0316336001600160a01b031614611253848484846125ad565b600085815260016020908152604080832080548251818502810185019093528083529192909190849084015b828210156112f157600084815260209081902060408051608081018252600286029092018054835260019081015463ffffffff8082168587015264010000000082041692840192909252680100000000000000009091046001600160a01b03166060830152908352909201910161127f565b5050506000888152600160205260408120929350611310929150614907565b805160005b8181101561099757600061138d84838151811061133457611334615139565b60200260200101516000015185848151811061135257611352615139565b60200260200101516020015163ffffffff1686858151811061137657611376615139565b60200260200101516040015163ffffffff16612736565b90506113b7818584815181106113a5576113a5615139565b6020026020010151606001518b61277c565b60011515818a7fcf0c92a2c6d7c42f488326b0cb900104b99984b6b218db81cd29371364a352518786815181106113f0576113f0615139565b602002602001015160600151336040516114209291906001600160a01b0392831681529116602082015260400190565b60405180910390a450600101611315565b606060016000838152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b828210156114d857600084815260209081902060408051608081018252600286029092018054835260019081015463ffffffff8082168587015264010000000082041692840192909252680100000000000000009091046001600160a01b031660608301529083529092019101611466565b505050509050919050565b6040516331a9108f60e11b8152600481018a90526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa15801561154b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061156f9190615077565b8a601161157d838383612156565b61158d8d8d8d8c8c8c8c8c612a6c565b9d9c50505050505050505050505050565b6040517fd49031c00000000000000000000000000000000000000000000000000000000081523060048201526024810182905260009081906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063d49031c090604401602060405180830381865afa158015611627573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061164b9190615094565b905060007f00000000000000000000000000000000000000000000000000000000000000006012146116a8576116a3827f00000000000000000000000000000000000000000000000000000000000000006012612cb1565b6116aa565b815b905060017f0000000000000000000000000000000000000000000000000000000000000000146117fb576117f6816117037f0000000000000000000000000000000000000000000000000000000000000000600a615233565b6040517fa4d0caf20000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152600160248201527f000000000000000000000000000000000000000000000000000000000000000060448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a4d0caf290606401602060405180830381865afa1580156117cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117f19190615094565b612d0e565b6117fd565b805b949350505050565b604051636e49181f60e01b81526004810189905230602482015288907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636e49181f90604401602060405180830381865afa158015611872573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118969190615031565b6118b357604051631b1d5a5960e31b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661eeee1461192257341561190457604051635e7e9adf60e11b815260040160405180910390fd5b4761191033308b611b2b565b61191a8147615064565b985050611926565b3497505b61199c89898888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8c018190048102820181019092528a815292508a9150899081908401838280828437600092019190915250612df492505050565b505050505050505050565b6000546001600160a01b03163314611a015760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610f31565b6001600160a01b038116611a7d5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610f31565b611a8681612550565b50565b600088886002611a9a838383612156565b610b4f8c8c8c8b8b8b8b612ee6565b60006001600160e01b031982167fc07370e4000000000000000000000000000000000000000000000000000000001480611b0c57506001600160e01b031982167f2896000200000000000000000000000000000000000000000000000000000000145b806108d257506301ffc9a760e01b6001600160e01b03198316146108d2565b611b3582826134de565b505050565b60006001600160a01b038616611b7c576040517fa762251300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611bd46040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b606060008060405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020018e81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000000000000000000000000000000000000000000081525090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632fa1b3918d838e7f00000000000000000000000000000000000000000000000000000000000000008f8d8d6040518863ffffffff1660e01b8152600401611cdd979695949392919061523f565b6000604051808303816000875af1158015611cfc573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611d2491908101906153cc565b995091955090935091508115611e7257604051632eec7b5560e11b8152600481018c90527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635dd8f6aa90602401602060405180830381865afa158015611d99573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dbd9190615077565b6040517f8ae9c07b000000000000000000000000000000000000000000000000000000008152600481018d9052602481018490526001600160a01b038c8116604483015260c06064830152600060c48301528a15156084830152600160a48301529190911690638ae9c07b9060e4016020604051808303816000875af1158015611e4b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e6f9190615094565b94505b88851015611eac576040517f7b94612600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8251156120f857600060405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020018f81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f0000000000000000000000000000000000000000000000000000000000000000815250905060006040518061014001604052808f6001600160a01b031681526020018e8152602001876020015181526020018481526020018381526020018881526020018d6001600160a01b031681526020018b151581526020018a815260200189815250905060008551905060005b818110156120f3576000878281518110611fc857611fc8615139565b60209081029190910101519050600061eeed197f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031601612011575060208101515b60208083015160808701519091015281516040517fda9ee8b70000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063da9ee8b790839061206a9089906004016155c8565b6000604051808303818588803b15801561208357600080fd5b505af1158015612097573d6000803e3d6000fd5b505050505081600001516001600160a01b03167f16112c26e14efc4be6c690149aa5a1ba75160de245f60d2273e28adb277b9e12868460200151336040516120e1939291906155db565b60405180910390a25050600101611fac565b505050505b50505087816000015182602001517f133161f1c9161488f777ab9a26aae91d47c0d9a3fafb398960f138db02c737978c8b8f888b8b33604051612141979695949392919061560d565b60405180910390a45098975050505050505050565b336001600160a01b0384161480159061220a575060405163c161c93f60e01b81523360048201526001600160a01b03848116602483015260448201849052606482018390527f0000000000000000000000000000000000000000000000000000000000000000169063c161c93f90608401602060405180830381865afa1580156121e4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122089190615031565b155b80156122b1575060405163c161c93f60e01b81523360048201526001600160a01b03848116602483015260006044830152606482018390527f0000000000000000000000000000000000000000000000000000000000000000169063c161c93f90608401602060405180830381865afa15801561228b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122af9190615031565b155b15611b355760405163075fd2b160e01b815260040160405180910390fd5b6040517fc6644597000000000000000000000000000000000000000000000000000000008152600481018790526024810186905260448101859052600090819081906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c664459790606401610140604051808303816000875af1158015612365573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612389919061566e565b91509150858110156123ae5760405163b01493c160e01b815260040160405180910390fd5b6040516331a9108f60e11b8152600481018a90526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015612416573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061243a9190615077565b9050600080600254600014612457576124528c6135f7565b61245d565b633b9aca005b90506000806124938e88602001517f0000000000000000000000000000000000000000000000000000000000000000898761377c565b92509050633b9aca0083146124a757908101905b816000036124b65760006124c3565b6124c38e8884888761393d565b935080156124ef576124d88160025485612736565b6124e29082615064565b97506124ef30868a611b2b565b5050508a846000015185602001517fc41a8d26c70cfcf1b9ea10f82482ac947b8be5bea2750bc729af844bbfde1e28858e88878c8f8f3360405161253a9897969594939291906156c6565b60405180910390a4505050509695505050505050565b600080546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b801580156125c45750336001600160a01b03851614155b801561266b575060405163c161c93f60e01b81523360048201526001600160a01b03858116602483015260448201859052606482018490527f0000000000000000000000000000000000000000000000000000000000000000169063c161c93f90608401602060405180830381865afa158015612645573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126699190615031565b155b8015612712575060405163c161c93f60e01b81523360048201526001600160a01b03858116602483015260006044830152606482018490527f0000000000000000000000000000000000000000000000000000000000000000169063c161c93f90608401602060405180830381865afa1580156126ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127109190615031565b155b156127305760405163075fd2b160e01b815260040160405180910390fd5b50505050565b6000806127488484633b9aca00612d0e565b6127529085615064565b905061276785633b9aca006117f1818561571a565b6127719086615064565b9150505b9392505050565b604051630862026560e41b8152600160048201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660248301526000917f000000000000000000000000000000000000000000000000000000000000000090911690638620265090604401602060405180830381865afa15801561280e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128329190615077565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661eeee1461286f576000612871565b845b60408051602080825281830190925291925060009190602082018180368337019050509050836040516020016128a991815260200190565b60408051808303601f19018152908290527f1ebc263f00000000000000000000000000000000000000000000000000000000825291506001600160a01b03841690631ebc263f90849061292e906001908b907f0000000000000000000000000000000000000000000000000000000000000000908c9060009081908b9060040161572d565b60206040518083038185885af193505050508015612969575060408051601f3d908101601f1916820190925261296691810190615094565b60015b612a62573d808015612997576040519150601f19603f3d011682016040523d82523d6000602084013e61299c565b606091505b5060405163e7c8e3e360e01b815260048101869052602481018890527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7c8e3e390604401600060405180830381600087803b158015612a0657600080fd5b505af1158015612a1a573d6000803e3d6000fd5b505050506001857f80a889d08f0d59eb962335b57fb1d5b29e86e3d23f15087b5541fddf15422bbe898433604051612a5493929190615784565b60405180910390a350612a64565b505b505050505050565b6040517f25386715000000000000000000000000000000000000000000000000000000008152600481018990526024810188905260448101879052600090819081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632538671590606401610140604051808303816000875af1158015612b02573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b26919061566e565b9150915087811015612b4b5760405163b01493c160e01b815260040160405180910390fd5b6040516331a9108f60e11b8152600481018c905260009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015612bb5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bd99190615077565b9050600060025460001480612bfd57503360009081526004602052604090205460ff165b612c0f57612c0a8e6135f7565b612c15565b633b9aca005b9050633b9aca008114612c3457612c2f8e8686858561393d565b612c37565b60005b80850396509250838314612c5057612c50308b88611b2b565b5050508a826000015183602001517f2eeee47c6d8d31c3523c3aa07b4c3e3795db36be4c04546ef3e30a5102f568e18a8e86898d8d8d33604051612c9b9897969594939291906157b6565b60405180910390a4505098975050505050505050565b6000828203612cc1575082612775565b82821115612cef57612cd38383615064565b612cde90600a615233565b612ce89085615817565b9050612775565b612cf98284615064565b612d0490600a615233565b612ce8908561584c565b6000808060001985870985870292508281108382030391505080600003612d4857838281612d3e57612d3e615836565b0492505050612775565b838110612d8b576040517f773cc18c0000000000000000000000000000000000000000000000000000000081526004810182905260248101859052604401610f31565b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b600083612e02576000612e0c565b612e0c8686613ae6565b90506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663e7c8e3e387612e48848961571a565b6040516001600160e01b031960e085901b16815260048101929092526024820152604401600060405180830381600087803b158015612e8657600080fd5b505af1158015612e9a573d6000803e3d6000fd5b50505050857f9ecaf7fc3dfffd6867c175d6e684b1f1e3aef019398ba8db2c1ffab4a09db2538683868633604051612ed695949392919061586e565b60405180910390a2505050505050565b60006001600160a01b038416612f28576040517ff74a1b6600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612f806040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b6040517fa2df1f950000000000000000000000000000000000000000000000000000000081526060906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a2df1f9590612ff0908d908d908d908b908b906004016158bb565b6000604051808303816000875af115801561300f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261303791908101906158fb565b975090945090925090508683101561307b576040517ff896960b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87156131a457604051632eec7b5560e11b8152600481018a90527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635dd8f6aa90602401602060405180830381865afa1580156130e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061310a9190615077565b6040517f1665bc0f0000000000000000000000000000000000000000000000000000000081526001600160a01b038c81166004830152602482018c9052604482018b905260a06064830152600060a4830181905260848301529190911690631665bc0f9060c401600060405180830381600087803b15801561318b57600080fd5b505af115801561319f573d6000803e3d6000fd5b505050505b80511561347257600060405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602001600081526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f0000000000000000000000000000000000000000000000000000000000000000815250905060006040518061012001604052808d6001600160a01b031681526020018c8152602001856020015181526020018b815260200160405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020018881526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000008152508152602001838152602001896001600160a01b0316815260200188815260200187815250905060008351905060005b8181101561346d57600085828151811061334257613342615139565b60209081029190910101519050600061eeed197f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03160161338b575060208101515b60208083015160a08701519091015281516040517f2b13c58f0000000000000000000000000000000000000000000000000000000081526001600160a01b0390911690632b13c58f9083906133e4908990600401615abe565b6000604051808303818588803b1580156133fd57600080fd5b505af1158015613411573d6000803e3d6000fd5b505050505081600001516001600160a01b03167f54b3744c489f40987dd2726ca12131243334e8292f567389f761c5a432d813e48684602001513360405161345b93929190615ad1565b60405180910390a25050600101613326565b505050505b50811561348457613484308684611b2b565b87816000015182602001517f2be10f2a0203c77d0fcaa9fd6484a8a1d6904de31cd820587f60c1c8c338c8148c898c888b8b336040516134ca979695949392919061560d565b60405180910390a450979650505050505050565b8047101561352e5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401610f31565b6000826001600160a01b03168260405160006040518083038185875af1925050503d806000811461357b576040519150601f19603f3d011682016040523d82523d6000602084013e613580565b606091505b5050905080611b355760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401610f31565b604051630862026560e41b8152600160048201526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116602483015260009182917f00000000000000000000000000000000000000000000000000000000000000001690638620265090604401602060405180830381865afa158015613689573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136ad9190615077565b6001600160a01b0316036136c65750633b9aca00919050565b6003546001600160a01b031615613774576003546040517f77695896000000000000000000000000000000000000000000000000000000008152600481018490526001600160a01b0390911690637769589690602401602060405180830381865afa925050508015613755575060408051601f3d908101601f1916820190925261375291810190615094565b60015b61376157506000919050565b633b9aca0081116137725792915050565b505b506000919050565b6040517f69e11cc50000000000000000000000000000000000000000000000000000000081526004810186905260248101859052604481018490528290600090633b9aca009082907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906369e11cc590606401600060405180830381865afa158015613815573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261383d9190810190615ae4565b905060005b815181101561393057600082828151811061385f5761385f615139565b6020026020010151905060008482604001511461388e57613889898360400151633b9aca00612d0e565b613890565b865b90508160400151856138a29190615064565b945060006138b3838e8d858d613eef565b905080158015906138c45750818114155b156138d6576138d3828861571a565b96505b81156138e25781880397505b8a8c8e7f0d31ab573f6daa4b1edba8d31973b4ba9f98fbfecc47010c1533eeefd2a1225a8686863360405161391a9493929190615bee565b60405180910390a4836001019350505050613842565b5050509550959350505050565b600061394c8460025484612736565b610100860151909150604f1c600190811603613a8957600086815260016020818152604080842081516080810183528981526002805463ffffffff9081168387019081528a82168487019081526001600160a01b03808e16606087019081528754808c018955978c5298909a209451958402909401948555519390960180549251955190971668010000000000000000027fffffffff0000000000000000000000000000000000000000ffffffffffffffff9587166401000000000267ffffffffffffffff19909316939096169290921717929092169290921790925590549051859088907f77813be0661650ddc1a5193ff2837df4162b251cb432651e2c060c3fc39756be90613a7c908790899033909283526001600160a01b03918216602084015216604082015260600190565b60405180910390a4613add565b613a9481848861277c565b604080516001600160a01b0385168152336020820152600091839189917fcf0c92a2c6d7c42f488326b0cb900104b99984b6b218db81cd29371364a35251910160405180910390a45b95945050505050565b600082815260016020908152604080832080548251818502810185019093528083528493849084015b82821015613b8157600084815260209081902060408051608081018252600286029092018054835260019081015463ffffffff8082168587015264010000000082041692840192909252680100000000000000009091046001600160a01b031660608301529083529092019101613b0f565b5050506000868152600160205260408120929350613ba0929150614907565b8051839060005b81811015613ea75782600003613c805760008781526001602052604090208451859083908110613bd957613bd9615139565b60209081029190910181015182546001818101855560009485529383902082516002909202019081559181015191909201805460408401516060909401516001600160a01b031668010000000000000000027fffffffff0000000000000000000000000000000000000000ffffffffffffffff63ffffffff9586166401000000000267ffffffffffffffff1990931695909416949094171791909116919091179055613e9f565b838181518110613c9257613c92615139565b6020026020010151600001518310613d2657838181518110613cb657613cb6615139565b60200260200101516000015183039250613d1d848281518110613cdb57613cdb615139565b602002602001015160000151858381518110613cf957613cf9615139565b60200260200101516020015163ffffffff1686848151811061137657611376615139565b85019450613e9f565b60016000888152602001908152602001600020604051806080016040528085878581518110613d5757613d57615139565b602002602001015160000151038152602001868481518110613d7b57613d7b615139565b60200260200101516020015163ffffffff168152602001868481518110613da457613da4615139565b60200260200101516040015163ffffffff168152602001868481518110613dcd57613dcd615139565b6020908102919091018101516060908101516001600160a01b039081169093528454600181810187556000968752958390208551600290920201908155918401519190940180546040850151949095015190921668010000000000000000027fffffffff0000000000000000000000000000000000000000ffffffffffffffff63ffffffff9485166401000000000267ffffffffffffffff19909616949092169390931793909317929092161790558351613e96908490869084908110613cf957613cf9615139565b85019450600092505b600101613ba7565b50604080518381523360208201528591879189917f59860d79d97c1fce2be7f987915c631471f4b08f671200463cc40a3380194ffb910160405180910390a450505092915050565b60c08501516000906001600160a01b0316156142a357633b9aca00821480613f33575060c08601516001600160a01b031660009081526004602052604090205460ff165b15613f3f575081613f51565b613f4c8360025484612736565b830390505b60006040518060c001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020018381526020017f0000000000000000000000000000000000000000000000000000000000000000815260200187815260200186815260200188815250905060006060613ffd8960c001517f9d740bfa000000000000000000000000000000000000000000000000000000006147ba565b1561416e578860c001516001600160a01b0316639d740bfa61eeee6001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614614057576000614059565b855b604080516001600160e01b031960e085901b16815287516001600160a01b0390811660048301526020808a01516024840152838a015160448401526060808b015160648501526080808c0151608486015260a0808d01518051151560a488015293840151151560c48701529583015160e48601529082015161010485015281015182166101248401529283015161014483015260c090920151909116610164820152610184016000604051808303818588803b15801561411857600080fd5b505af19350505050801561412a575060015b614169573d808015614158576040519150601f19603f3d011682016040523d82523d6000602084013e61415d565b606091505b50600192509050614173565b614173565b600291505b811561429b5760405163e7c8e3e360e01b81526004810189905260248101879052600094507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7c8e3e390604401600060405180830381600087803b1580156141e657600080fd5b505af11580156141fa573d6000803e3d6000fd5b50505050877f290b5df59e172593762964e4f8ed2b4a9192d3197bfd2be4bae123908f8007968a888560011461427f5760405160200161426b906020808252600c908201527f49455243313635206661696c0000000000000000000000000000000000000000604082015260600190565b604051602081830303815290604052614281565b845b336040516142929493929190615c75565b60405180910390a25b505050613add565b60608601511561475d576060860151604051630862026560e41b81526000916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691638620265091614333917f0000000000000000000000000000000000000000000000000000000000000000906004019182526001600160a01b0316602082015260400190565b602060405180830381865afa158015614350573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143749190615077565b90506001600160a01b0381166143b6576040517f6921234300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b0381163014806143d05750633b9aca0083145b806143f357506001600160a01b03811660009081526004602052604090205460ff165b1561440057839150614412565b61440d8460025485612736565b840391505b6040805160208082528183019092526000916020820181803683370190505090508660405160200161444691815260200190565b604051602081830303815290604052905087602001511561462857816001600160a01b0316630cf8e85861eeee6001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316146144b25760006144b4565b845b8a60600151867f0000000000000000000000000000000000000000000000000000000000000000866040518663ffffffff1660e01b81526004016144fb94939291906150fd565b6000604051808303818588803b15801561451457600080fd5b505af193505050508015614526575060015b614623573d808015614554576040519150601f19603f3d011682016040523d82523d6000602084013e614559565b606091505b5060405163e7c8e3e360e01b81526004810189905260248101879052600094507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7c8e3e390604401600060405180830381600087803b1580156145c757600080fd5b505af11580156145db573d6000803e3d6000fd5b50505050877f290b5df59e172593762964e4f8ed2b4a9192d3197bfd2be4bae123908f8007968a8884336040516146159493929190615c75565b60405180910390a250614756565b614756565b816001600160a01b0316631ebc263f61eeee6001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161461467957600061467b565b845b60608b015160808c015187907f0000000000000000000000000000000000000000000000000000000000000000906001600160a01b03166146bc57336146c2565b8d608001515b8e516040516001600160e01b031960e089901b1681526146ed95949392916000918b9060040161572d565b60206040518083038185885af193505050508015614728575060408051601f3d908101601f1916820190925261472591810190615094565b60015b61429b573d808015614554576040519150601f19603f3d011682016040523d82523d6000602084013e614559565b5050613add565b60808601516000906001600160a01b0316614778573361477e565b86608001515b9050633b9aca008303614793578391506147a5565b6147a08460025485612736565b840391505b6147b0308284611b2b565b5095945050505050565b60006147c5836147d6565b801561277557506127758383614809565b60006147e9826301ffc9a760e01b614809565b80156108d25750614802826001600160e01b0319614809565b1592915050565b604080516001600160e01b0319831660248083019190915282518083039091018152604490910182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166301ffc9a760e01b179052905160009190829081906001600160a01b0387169061753090614885908690615d0b565b6000604051808303818686fa925050503d80600081146148c1576040519150601f19603f3d011682016040523d82523d6000602084013e6148c6565b606091505b50915091506020815110156148e157600093505050506108d2565b8180156148fd5750808060200190518101906148fd9190615031565b9695505050505050565b5080546000825560020290600052602060002090810190611a8691905b8082111561494a57600081556001810180546001600160e01b0319169055600201614924565b5090565b60006020828403121561496057600080fd5b81356001600160e01b03198116811461277557600080fd5b6001600160a01b0381168114611a8657600080fd5b60008083601f84011261499f57600080fd5b50813567ffffffffffffffff8111156149b757600080fd5b6020830191508360208285010111156149cf57600080fd5b9250929050565b600080600080600080600060a0888a0312156149f157600080fd5b87359650602088013595506040880135614a0a81614978565b9450606088013567ffffffffffffffff80821115614a2757600080fd5b614a338b838c0161498d565b909650945060808a0135915080821115614a4c57600080fd5b50614a598a828b0161498d565b989b979a50959850939692959293505050565b600060208284031215614a7e57600080fd5b813561277581614978565b8015158114611a8657600080fd5b6000806000806000806000806000806101008b8d031215614ab757600080fd5b8a35995060208b0135985060408b0135614ad081614978565b975060608b0135614ae081614978565b965060808b0135955060a08b0135614af781614a89565b945060c08b013567ffffffffffffffff80821115614b1457600080fd5b614b208e838f0161498d565b909650945060e08d0135915080821115614b3957600080fd5b50614b468d828e0161498d565b915080935050809150509295989b9194979a5092959850565b60008060408385031215614b7257600080fd5b823591506020830135614b8481614978565b809150509250929050565b600080600080600080600060c0888a031215614baa57600080fd5b8735965060208801359550604088013594506060880135614bca81614978565b93506080880135925060a088013567ffffffffffffffff811115614bed57600080fd5b614a598a828b0161498d565b600060208284031215614c0b57600080fd5b5035919050565b60008060408385031215614c2557600080fd5b8235614c3081614978565b91506020830135614b8481614a89565b602080825282518282018190526000919060409081850190868401855b82811015614ca9578151805185528681015163ffffffff908116888701528682015116868601526060908101516001600160a01b03169085015260809093019290850190600101614c5d565b5091979650505050505050565b634e487b7160e01b600052604160045260246000fd5b604051610120810167ffffffffffffffff81118282101715614cf057614cf0614cb6565b60405290565b6040805190810167ffffffffffffffff81118282101715614cf057614cf0614cb6565b60405160e0810167ffffffffffffffff81118282101715614cf057614cf0614cb6565b604051601f8201601f1916810167ffffffffffffffff81118282101715614d6557614d65614cb6565b604052919050565b600067ffffffffffffffff821115614d8757614d87614cb6565b50601f01601f191660200190565b600082601f830112614da657600080fd5b8135614db9614db482614d6d565b614d3c565b818152846020838601011115614dce57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060008060006101008a8c031215614e0a57600080fd5b8935985060208a0135975060408a0135965060608a0135614e2a81614978565b955060808a0135945060a08a0135614e4181614978565b935060c08a013567ffffffffffffffff80821115614e5e57600080fd5b614e6a8d838e01614d95565b945060e08c0135915080821115614e8057600080fd5b50614e8d8c828d0161498d565b915080935050809150509295985092959850929598565b60008060008060008060008060c0898b031215614ec057600080fd5b88359750602089013596506040890135614ed981614978565b95506060890135614ee981614a89565b9450608089013567ffffffffffffffff80821115614f0657600080fd5b614f128c838d0161498d565b909650945060a08b0135915080821115614f2b57600080fd5b50614f388b828c0161498d565b999c989b5096995094979396929594505050565b60008060408385031215614f5f57600080fd5b8235614f6a81614978565b946020939093013593505050565b600080600080600080600080610100898b031215614f9557600080fd5b8835614fa081614978565b975060208901359650604089013595506060890135614fbe81614978565b94506080890135935060a0890135614fd581614978565b925060c089013567ffffffffffffffff80821115614ff257600080fd5b614ffe8c838d01614d95565b935060e08b013591508082111561501457600080fd5b506150218b828c01614d95565b9150509295985092959890939650565b60006020828403121561504357600080fd5b815161277581614a89565b634e487b7160e01b600052601160045260246000fd5b818103818111156108d2576108d261504e565b60006020828403121561508957600080fd5b815161277581614978565b6000602082840312156150a657600080fd5b5051919050565b60005b838110156150c85781810151838201526020016150b0565b50506000910152565b600081518084526150e98160208601602086016150ad565b601f01601f19169290920160200192915050565b8481528360208201526001600160a01b038316604082015260a06060820152600060a082015260c0608082015260006148fd60c08301846150d1565b634e487b7160e01b600052603260045260246000fd5b600181815b8085111561518a5781600019048211156151705761517061504e565b8085161561517d57918102915b93841c9390800290615154565b509250929050565b6000826151a1575060016108d2565b816151ae575060006108d2565b81600181146151c457600281146151ce576151ea565b60019150506108d2565b60ff8411156151df576151df61504e565b50506001821b6108d2565b5060208310610133831016604e8410600b841016171561520d575081810a6108d2565b615217838361514f565b806000190482111561522b5761522b61504e565b029392505050565b60006127758383615192565b60006101406001600160a01b03808b168452615288602085018b6001600160a01b0381511682526020810151602083015260408101516040830152606081015160608301525050565b8860a08501528760c085015280871660e085015250806101008401526152b0818401866150d1565b90508281036101208401526152c581856150d1565b9a9950505050505050505050565b80516152de81614978565b919050565b600061012082840312156152f657600080fd5b6152fe614ccc565b9050815181526020820151602082015260408201516040820152606082015160608201526080820151608082015260a082015160a082015260c082015160c082015261534c60e083016152d3565b60e082015261010080830151818301525092915050565b600067ffffffffffffffff82111561537d5761537d614cb6565b5060051b60200190565b600082601f83011261539857600080fd5b81516153a6614db482614d6d565b8181528460208386010111156153bb57600080fd5b6117fd8260208301602087016150ad565b60008060008061018085870312156153e357600080fd5b6153ed86866152e3565b9350610120850151925061014085015167ffffffffffffffff8082111561541357600080fd5b818701915087601f83011261542757600080fd5b81516020615437614db483615363565b82815260069290921b8401810191818101908b84111561545657600080fd5b948201945b838610156154a2576040868d0312156154745760008081fd5b61547c614cf6565b865161548781614978565b8152868401518482015282526040909501949082019061545b565b6101608b01519097509450505050808211156154bd57600080fd5b506154ca87828801615387565b91505092959194509250565b80516001600160a01b031682526000610200602083810151858201526040808501518187015260608086015180516001600160a01b0316828901529283015160808801529082015160a087015281015160c086015250608083015180516001600160a01b031660e08601526020810151610100860152604081015161012086015260608101516101408601525060a083015161016085015260c08301516001600160a01b0381166101808601525060e08301518015156101a086015250610100830151816101c08601526155ac828601826150d1565b9150506101208301518482036101e0860152613add82826150d1565b60208152600061277560208301846154d6565b6060815260006155ee60608301866154d6565b90508360208301526001600160a01b0383166040830152949350505050565b60006001600160a01b03808a168352808916602084015287604084015286606084015260e0608084015261564460e08401876150d1565b83810360a085015261565681876150d1565b92505080841660c08401525098975050505050505050565b600080610140838503121561568257600080fd5b61568c84846152e3565b915061012083015190509250929050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60006001600160a01b03808b16835289602084015288604084015287606084015286608084015260e060a084015261570260e08401868861569d565b915080841660c0840152509998505050505050505050565b808201808211156108d2576108d261504e565b60006101008983528860208401526001600160a01b03808916604085015280881660608501525085608084015284151560a08401528060c0840152600081840152506101208060e08401526152c5818401856150d1565b83815260606020820152600061579d60608301856150d1565b90506001600160a01b0383166040830152949350505050565b60006001600160a01b03808b16835289602084015288604084015287606084015260e060808401526157eb60e08401886150d1565b83810360a08501526157fe81878961569d565b92505080841660c0840152509998505050505050505050565b60008160001904831182151516156158315761583161504e565b500290565b634e487b7160e01b600052601260045260246000fd5b60008261586957634e487b7160e01b600052601260045260246000fd5b500490565b85815284602082015260a06040820152600061588d60a08301866150d1565b828103606084015261589f81866150d1565b9150506001600160a01b03831660808301529695505050505050565b6001600160a01b038616815284602082015283604082015260a0606082015260006158e960a08301856150d1565b8281036080840152610ecf81856150d1565b600080600080610180858703121561591257600080fd5b61591c86866152e3565b9350610120850151925061014085015167ffffffffffffffff8082111561594257600080fd5b818701915087601f83011261595657600080fd5b81516020615966614db483615363565b82815260069290921b8401810191818101908b84111561598557600080fd5b948201945b838610156154a2576040868d0312156159a35760008081fd5b6159ab614cf6565b86516159b681614978565b8152868401518482015282526040909501949082019061598a565b80516001600160a01b0316825260006101e06020830151602085015260408301516040850152606083015160608501526080830151615a3d60808601826001600160a01b0381511682526020810151602083015260408101516040830152606081015160608301525050565b5060a083015180516001600160a01b03908116610100878101919091526020830151610120880152604083015161014088015260609092015161016087015260c08501511661018086015260e08401516101a0860183905290615aa2838701836150d1565b9250808501519150508482036101c0860152613add82826150d1565b60208152600061277560208301846159d1565b6060815260006155ee60608301866159d1565b60006020808385031215615af757600080fd5b825167ffffffffffffffff811115615b0e57600080fd5b8301601f81018513615b1f57600080fd5b8051615b2d614db482615363565b81815260e09182028301840191848201919088841115615b4c57600080fd5b938501935b83851015615be25780858a031215615b695760008081fd5b615b71614d19565b8551615b7c81614a89565b815285870151615b8b81614a89565b818801526040868101519082015260608087015190820152608080870151615bb281614978565b9082015260a0868101519082015260c080870151615bcf81614978565b9082015283529384019391850191615b51565b50979650505050505050565b6101408101615c4f8287805115158252602081015115156020830152604081015160408301526060810151606083015260808101516001600160a01b03808216608085015260a083015160a08501528060c08401511660c085015250505050565b8460e0830152836101008301526001600160a01b03831661012083015295945050505050565b6000610140615cd68388805115158252602081015115156020830152604081015160408301526060810151606083015260808101516001600160a01b03808216608085015260a083015160a08501528060c08401511660c085015250505050565b8560e084015280610100840152615cef818401866150d1565b9150506001600160a01b03831661012083015295945050505050565b60008251615d1d8184602087016150ad565b919091019291505056fea2646970667358221220fd8d04f3b3bf048a392c4449e52316e1254a93b3c05809d0cda55460ad15b53764736f6c63430008100033", "deployedBytecode": "0x6080604052600436106102195760003560e01c80638da5cb5b1161011d578063c715967a116100b0578063df21a7dd1161007f578063f2fde38b11610064578063f2fde38b14610750578063fc0c546a14610770578063fe663f0f146107a457600080fd5b8063df21a7dd146106ce578063e5a6b10f1461071c57600080fd5b8063c715967a14610651578063d3419bf314610664578063d6dacc5314610698578063ddca3f43146106b857600080fd5b8063ad007d63116100ec578063ad007d6314610579578063b631b500146105ad578063b7bad1b1146105dd578063c41c2f241461061d57600080fd5b80638da5cb5b146104e7578063975057e714610505578063a02f801c14610539578063a32e1e961461055957600080fd5b80634a4305c0116101b0578063715018a61161017f57806389701db51161016457806389701db5146104665780638af56094146104865780638b79543c146104b357600080fd5b8063715018a6146104315780637258002c1461044657600080fd5b80634a4305c01461039d578063637913ac146103bd57806366248b86146103dd57806369fe0e2d1461041157600080fd5b80632bdfe004116101ec5780632bdfe004146102c95780632d1a590314610315578063313ce56714610349578063405b84fa1461037d57600080fd5b806301ffc9a71461021e5780630cf8e858146102535780631982d679146102685780631ebc263f146102b6575b600080fd5b34801561022a57600080fd5b5061023e61023936600461494e565b6107c4565b60405190151581526020015b60405180910390f35b6102666102613660046149d6565b6108d8565b005b34801561027457600080fd5b506102a8610283366004614a6c565b507f000000000000000000000000000000000000000000000000000000000000000090565b60405190815260200161024a565b6102a86102c4366004614a97565b6109a1565b3480156102d557600080fd5b506102fd7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161024a565b34801561032157600080fd5b506102a87f000000000000000000000000000000000000000000000000000000000000000081565b34801561035557600080fd5b506102a87f000000000000000000000000000000000000000000000000000000000000000081565b34801561038957600080fd5b506102a8610398366004614b5f565b610b5f565b3480156103a957600080fd5b506102a86103b8366004614b8f565b610ebf565b3480156103c957600080fd5b506102666103d8366004614a6c565b610edb565b3480156103e957600080fd5b506102a87f000000000000000000000000000000000000000000000000000000000000000081565b34801561041d57600080fd5b5061026661042c366004614bf9565b610f9b565b34801561043d57600080fd5b50610266611073565b34801561045257600080fd5b50610266610461366004614c12565b6110d9565b34801561047257600080fd5b50610266610481366004614bf9565b611195565b34801561049257600080fd5b506104a66104a1366004614bf9565b611431565b60405161024a9190614c40565b3480156104bf57600080fd5b506102fd7f000000000000000000000000000000000000000000000000000000000000000081565b3480156104f357600080fd5b506000546001600160a01b03166102fd565b34801561051157600080fd5b506102fd7f000000000000000000000000000000000000000000000000000000000000000081565b34801561054557600080fd5b506102a8610554366004614deb565b6114e3565b34801561056557600080fd5b506102a8610574366004614bf9565b61159e565b34801561058557600080fd5b506102fd7f000000000000000000000000000000000000000000000000000000000000000081565b3480156105b957600080fd5b5061023e6105c8366004614a6c565b60046020526000908152604090205460ff1681565b3480156105e957600080fd5b506102a86105f8366004614a6c565b507f000000000000000000000000000000000000000000000000000000000000000090565b34801561062957600080fd5b506102fd7f000000000000000000000000000000000000000000000000000000000000000081565b61026661065f366004614ea4565b611805565b34801561067057600080fd5b506102fd7f000000000000000000000000000000000000000000000000000000000000000081565b3480156106a457600080fd5b506003546102fd906001600160a01b031681565b3480156106c457600080fd5b506102a860025481565b3480156106da57600080fd5b5061023e6106e9366004614f4c565b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161490565b34801561072857600080fd5b506102a87f000000000000000000000000000000000000000000000000000000000000000081565b34801561075c57600080fd5b5061026661076b366004614a6c565b6119a7565b34801561077c57600080fd5b506102fd7f000000000000000000000000000000000000000000000000000000000000000081565b3480156107b057600080fd5b506102a86107bf366004614f78565b611a89565b60006001600160e01b031982167fedb527eb00000000000000000000000000000000000000000000000000000000148061082757506001600160e01b031982167f4a4305c000000000000000000000000000000000000000000000000000000000145b8061085b57506001600160e01b031982167fa02f801c00000000000000000000000000000000000000000000000000000000145b8061088f57506001600160e01b031982167ffe663f0f00000000000000000000000000000000000000000000000000000000145b806108c357506001600160e01b031982167fad007d6300000000000000000000000000000000000000000000000000000000145b806108d257506108d282611aa9565b92915050565b604051636e49181f60e01b81526004810188905230602482015287907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636e49181f90604401602060405180830381865afa158015610945573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109699190615031565b61098657604051631b1d5a5960e31b815260040160405180910390fd5b610997888888600089898989611805565b5050505050505050565b604051636e49181f60e01b8152600481018b90523060248201526000908b906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636e49181f90604401602060405180830381865afa158015610a11573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a359190615031565b610a5257604051631b1d5a5960e31b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661eeee14610ac1573415610aa357604051635e7e9adf60e11b815260040160405180910390fd5b47610aaf33308e611b2b565b610ab98147615064565b9b5050610ac5565b349a505b610b4f8b338e8c8c8c8c8c8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611b3a92505050565b9c9b505050505050505050505050565b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610bc7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610beb9190615077565b836004610bf9838383612156565b6040517fdf21a7dd0000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301526024820188905286169063df21a7dd90604401602060405180830381865afa158015610c7f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ca39190615031565b610cd9576040517f581010ed00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f6bb6a5ad000000000000000000000000000000000000000000000000000000008152600481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636bb6a5ad906024016020604051808303816000875af1158015610d59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d7d9190615094565b93508315610e715760007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661eeee14610dc0576000610dc2565b845b604080516020810182526000815290517f0cf8e8580000000000000000000000000000000000000000000000000000000081529192506001600160a01b03881691630cf8e858918491610e3d918c918b917f0000000000000000000000000000000000000000000000000000000000000000916004016150fd565b6000604051808303818588803b158015610e5657600080fd5b505af1158015610e6a573d6000803e3d6000fd5b5050505050505b604080518581523360208201526001600160a01b0387169188917fa7519e5f94697b7f53e97c5eb46a0c730a296ab686ab8fd333835c5f735784eb910160405180910390a350505092915050565b6000610ecf8888888787876122cf565b98975050505050505050565b6000546001600160a01b03163314610f3a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b6003805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383169081179091556040513381527f0a9a80fe9716605b3e52abb3d792d6a4e7816d6afc02a5a4ef023081feaf9f609060200160405180910390a250565b6000546001600160a01b03163314610ff55760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610f31565b6302faf080811115611033576040517f45fbd9c100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002819055604080518281523360208201527fd7414e590e1cb532989ab2a34c8f4c2c17f7ab6f006efeeaef2e87cd5008c202910160405180910390a150565b6000546001600160a01b031633146110cd5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610f31565b6110d76000612550565b565b6000546001600160a01b031633146111335760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610f31565b6001600160a01b038216600081815260046020908152604091829020805460ff191685151590811790915591513381529192917fa2653e25a502c023a5830d0de847ef6f458387865b1f4f575d7594f9f2c0d71e910160405180910390a35050565b6040516331a9108f60e11b8152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa1580156111fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061121e9190615077565b8160056112336000546001600160a01b031690565b6001600160a01b0316336001600160a01b031614611253848484846125ad565b600085815260016020908152604080832080548251818502810185019093528083529192909190849084015b828210156112f157600084815260209081902060408051608081018252600286029092018054835260019081015463ffffffff8082168587015264010000000082041692840192909252680100000000000000009091046001600160a01b03166060830152908352909201910161127f565b5050506000888152600160205260408120929350611310929150614907565b805160005b8181101561099757600061138d84838151811061133457611334615139565b60200260200101516000015185848151811061135257611352615139565b60200260200101516020015163ffffffff1686858151811061137657611376615139565b60200260200101516040015163ffffffff16612736565b90506113b7818584815181106113a5576113a5615139565b6020026020010151606001518b61277c565b60011515818a7fcf0c92a2c6d7c42f488326b0cb900104b99984b6b218db81cd29371364a352518786815181106113f0576113f0615139565b602002602001015160600151336040516114209291906001600160a01b0392831681529116602082015260400190565b60405180910390a450600101611315565b606060016000838152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b828210156114d857600084815260209081902060408051608081018252600286029092018054835260019081015463ffffffff8082168587015264010000000082041692840192909252680100000000000000009091046001600160a01b031660608301529083529092019101611466565b505050509050919050565b6040516331a9108f60e11b8152600481018a90526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa15801561154b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061156f9190615077565b8a601161157d838383612156565b61158d8d8d8d8c8c8c8c8c612a6c565b9d9c50505050505050505050505050565b6040517fd49031c00000000000000000000000000000000000000000000000000000000081523060048201526024810182905260009081906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063d49031c090604401602060405180830381865afa158015611627573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061164b9190615094565b905060007f00000000000000000000000000000000000000000000000000000000000000006012146116a8576116a3827f00000000000000000000000000000000000000000000000000000000000000006012612cb1565b6116aa565b815b905060017f0000000000000000000000000000000000000000000000000000000000000000146117fb576117f6816117037f0000000000000000000000000000000000000000000000000000000000000000600a615233565b6040517fa4d0caf20000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152600160248201527f000000000000000000000000000000000000000000000000000000000000000060448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a4d0caf290606401602060405180830381865afa1580156117cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117f19190615094565b612d0e565b6117fd565b805b949350505050565b604051636e49181f60e01b81526004810189905230602482015288907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636e49181f90604401602060405180830381865afa158015611872573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118969190615031565b6118b357604051631b1d5a5960e31b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661eeee1461192257341561190457604051635e7e9adf60e11b815260040160405180910390fd5b4761191033308b611b2b565b61191a8147615064565b985050611926565b3497505b61199c89898888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8c018190048102820181019092528a815292508a9150899081908401838280828437600092019190915250612df492505050565b505050505050505050565b6000546001600160a01b03163314611a015760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610f31565b6001600160a01b038116611a7d5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610f31565b611a8681612550565b50565b600088886002611a9a838383612156565b610b4f8c8c8c8b8b8b8b612ee6565b60006001600160e01b031982167fc07370e4000000000000000000000000000000000000000000000000000000001480611b0c57506001600160e01b031982167f2896000200000000000000000000000000000000000000000000000000000000145b806108d257506301ffc9a760e01b6001600160e01b03198316146108d2565b611b3582826134de565b505050565b60006001600160a01b038616611b7c576040517fa762251300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611bd46040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b606060008060405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020018e81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000000000000000000000000000000000000000000081525090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632fa1b3918d838e7f00000000000000000000000000000000000000000000000000000000000000008f8d8d6040518863ffffffff1660e01b8152600401611cdd979695949392919061523f565b6000604051808303816000875af1158015611cfc573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611d2491908101906153cc565b995091955090935091508115611e7257604051632eec7b5560e11b8152600481018c90527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635dd8f6aa90602401602060405180830381865afa158015611d99573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dbd9190615077565b6040517f8ae9c07b000000000000000000000000000000000000000000000000000000008152600481018d9052602481018490526001600160a01b038c8116604483015260c06064830152600060c48301528a15156084830152600160a48301529190911690638ae9c07b9060e4016020604051808303816000875af1158015611e4b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e6f9190615094565b94505b88851015611eac576040517f7b94612600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8251156120f857600060405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020018f81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f0000000000000000000000000000000000000000000000000000000000000000815250905060006040518061014001604052808f6001600160a01b031681526020018e8152602001876020015181526020018481526020018381526020018881526020018d6001600160a01b031681526020018b151581526020018a815260200189815250905060008551905060005b818110156120f3576000878281518110611fc857611fc8615139565b60209081029190910101519050600061eeed197f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031601612011575060208101515b60208083015160808701519091015281516040517fda9ee8b70000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063da9ee8b790839061206a9089906004016155c8565b6000604051808303818588803b15801561208357600080fd5b505af1158015612097573d6000803e3d6000fd5b505050505081600001516001600160a01b03167f16112c26e14efc4be6c690149aa5a1ba75160de245f60d2273e28adb277b9e12868460200151336040516120e1939291906155db565b60405180910390a25050600101611fac565b505050505b50505087816000015182602001517f133161f1c9161488f777ab9a26aae91d47c0d9a3fafb398960f138db02c737978c8b8f888b8b33604051612141979695949392919061560d565b60405180910390a45098975050505050505050565b336001600160a01b0384161480159061220a575060405163c161c93f60e01b81523360048201526001600160a01b03848116602483015260448201849052606482018390527f0000000000000000000000000000000000000000000000000000000000000000169063c161c93f90608401602060405180830381865afa1580156121e4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122089190615031565b155b80156122b1575060405163c161c93f60e01b81523360048201526001600160a01b03848116602483015260006044830152606482018390527f0000000000000000000000000000000000000000000000000000000000000000169063c161c93f90608401602060405180830381865afa15801561228b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122af9190615031565b155b15611b355760405163075fd2b160e01b815260040160405180910390fd5b6040517fc6644597000000000000000000000000000000000000000000000000000000008152600481018790526024810186905260448101859052600090819081906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c664459790606401610140604051808303816000875af1158015612365573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612389919061566e565b91509150858110156123ae5760405163b01493c160e01b815260040160405180910390fd5b6040516331a9108f60e11b8152600481018a90526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015612416573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061243a9190615077565b9050600080600254600014612457576124528c6135f7565b61245d565b633b9aca005b90506000806124938e88602001517f0000000000000000000000000000000000000000000000000000000000000000898761377c565b92509050633b9aca0083146124a757908101905b816000036124b65760006124c3565b6124c38e8884888761393d565b935080156124ef576124d88160025485612736565b6124e29082615064565b97506124ef30868a611b2b565b5050508a846000015185602001517fc41a8d26c70cfcf1b9ea10f82482ac947b8be5bea2750bc729af844bbfde1e28858e88878c8f8f3360405161253a9897969594939291906156c6565b60405180910390a4505050509695505050505050565b600080546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b801580156125c45750336001600160a01b03851614155b801561266b575060405163c161c93f60e01b81523360048201526001600160a01b03858116602483015260448201859052606482018490527f0000000000000000000000000000000000000000000000000000000000000000169063c161c93f90608401602060405180830381865afa158015612645573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126699190615031565b155b8015612712575060405163c161c93f60e01b81523360048201526001600160a01b03858116602483015260006044830152606482018490527f0000000000000000000000000000000000000000000000000000000000000000169063c161c93f90608401602060405180830381865afa1580156126ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127109190615031565b155b156127305760405163075fd2b160e01b815260040160405180910390fd5b50505050565b6000806127488484633b9aca00612d0e565b6127529085615064565b905061276785633b9aca006117f1818561571a565b6127719086615064565b9150505b9392505050565b604051630862026560e41b8152600160048201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660248301526000917f000000000000000000000000000000000000000000000000000000000000000090911690638620265090604401602060405180830381865afa15801561280e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128329190615077565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661eeee1461286f576000612871565b845b60408051602080825281830190925291925060009190602082018180368337019050509050836040516020016128a991815260200190565b60408051808303601f19018152908290527f1ebc263f00000000000000000000000000000000000000000000000000000000825291506001600160a01b03841690631ebc263f90849061292e906001908b907f0000000000000000000000000000000000000000000000000000000000000000908c9060009081908b9060040161572d565b60206040518083038185885af193505050508015612969575060408051601f3d908101601f1916820190925261296691810190615094565b60015b612a62573d808015612997576040519150601f19603f3d011682016040523d82523d6000602084013e61299c565b606091505b5060405163e7c8e3e360e01b815260048101869052602481018890527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7c8e3e390604401600060405180830381600087803b158015612a0657600080fd5b505af1158015612a1a573d6000803e3d6000fd5b505050506001857f80a889d08f0d59eb962335b57fb1d5b29e86e3d23f15087b5541fddf15422bbe898433604051612a5493929190615784565b60405180910390a350612a64565b505b505050505050565b6040517f25386715000000000000000000000000000000000000000000000000000000008152600481018990526024810188905260448101879052600090819081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632538671590606401610140604051808303816000875af1158015612b02573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b26919061566e565b9150915087811015612b4b5760405163b01493c160e01b815260040160405180910390fd5b6040516331a9108f60e11b8152600481018c905260009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa158015612bb5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bd99190615077565b9050600060025460001480612bfd57503360009081526004602052604090205460ff165b612c0f57612c0a8e6135f7565b612c15565b633b9aca005b9050633b9aca008114612c3457612c2f8e8686858561393d565b612c37565b60005b80850396509250838314612c5057612c50308b88611b2b565b5050508a826000015183602001517f2eeee47c6d8d31c3523c3aa07b4c3e3795db36be4c04546ef3e30a5102f568e18a8e86898d8d8d33604051612c9b9897969594939291906157b6565b60405180910390a4505098975050505050505050565b6000828203612cc1575082612775565b82821115612cef57612cd38383615064565b612cde90600a615233565b612ce89085615817565b9050612775565b612cf98284615064565b612d0490600a615233565b612ce8908561584c565b6000808060001985870985870292508281108382030391505080600003612d4857838281612d3e57612d3e615836565b0492505050612775565b838110612d8b576040517f773cc18c0000000000000000000000000000000000000000000000000000000081526004810182905260248101859052604401610f31565b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b600083612e02576000612e0c565b612e0c8686613ae6565b90506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663e7c8e3e387612e48848961571a565b6040516001600160e01b031960e085901b16815260048101929092526024820152604401600060405180830381600087803b158015612e8657600080fd5b505af1158015612e9a573d6000803e3d6000fd5b50505050857f9ecaf7fc3dfffd6867c175d6e684b1f1e3aef019398ba8db2c1ffab4a09db2538683868633604051612ed695949392919061586e565b60405180910390a2505050505050565b60006001600160a01b038416612f28576040517ff74a1b6600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612f806040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b6040517fa2df1f950000000000000000000000000000000000000000000000000000000081526060906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a2df1f9590612ff0908d908d908d908b908b906004016158bb565b6000604051808303816000875af115801561300f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261303791908101906158fb565b975090945090925090508683101561307b576040517ff896960b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87156131a457604051632eec7b5560e11b8152600481018a90527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635dd8f6aa90602401602060405180830381865afa1580156130e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061310a9190615077565b6040517f1665bc0f0000000000000000000000000000000000000000000000000000000081526001600160a01b038c81166004830152602482018c9052604482018b905260a06064830152600060a4830181905260848301529190911690631665bc0f9060c401600060405180830381600087803b15801561318b57600080fd5b505af115801561319f573d6000803e3d6000fd5b505050505b80511561347257600060405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602001600081526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f0000000000000000000000000000000000000000000000000000000000000000815250905060006040518061012001604052808d6001600160a01b031681526020018c8152602001856020015181526020018b815260200160405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020018881526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000008152508152602001838152602001896001600160a01b0316815260200188815260200187815250905060008351905060005b8181101561346d57600085828151811061334257613342615139565b60209081029190910101519050600061eeed197f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03160161338b575060208101515b60208083015160a08701519091015281516040517f2b13c58f0000000000000000000000000000000000000000000000000000000081526001600160a01b0390911690632b13c58f9083906133e4908990600401615abe565b6000604051808303818588803b1580156133fd57600080fd5b505af1158015613411573d6000803e3d6000fd5b505050505081600001516001600160a01b03167f54b3744c489f40987dd2726ca12131243334e8292f567389f761c5a432d813e48684602001513360405161345b93929190615ad1565b60405180910390a25050600101613326565b505050505b50811561348457613484308684611b2b565b87816000015182602001517f2be10f2a0203c77d0fcaa9fd6484a8a1d6904de31cd820587f60c1c8c338c8148c898c888b8b336040516134ca979695949392919061560d565b60405180910390a450979650505050505050565b8047101561352e5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401610f31565b6000826001600160a01b03168260405160006040518083038185875af1925050503d806000811461357b576040519150601f19603f3d011682016040523d82523d6000602084013e613580565b606091505b5050905080611b355760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401610f31565b604051630862026560e41b8152600160048201526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116602483015260009182917f00000000000000000000000000000000000000000000000000000000000000001690638620265090604401602060405180830381865afa158015613689573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136ad9190615077565b6001600160a01b0316036136c65750633b9aca00919050565b6003546001600160a01b031615613774576003546040517f77695896000000000000000000000000000000000000000000000000000000008152600481018490526001600160a01b0390911690637769589690602401602060405180830381865afa925050508015613755575060408051601f3d908101601f1916820190925261375291810190615094565b60015b61376157506000919050565b633b9aca0081116137725792915050565b505b506000919050565b6040517f69e11cc50000000000000000000000000000000000000000000000000000000081526004810186905260248101859052604481018490528290600090633b9aca009082907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906369e11cc590606401600060405180830381865afa158015613815573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261383d9190810190615ae4565b905060005b815181101561393057600082828151811061385f5761385f615139565b6020026020010151905060008482604001511461388e57613889898360400151633b9aca00612d0e565b613890565b865b90508160400151856138a29190615064565b945060006138b3838e8d858d613eef565b905080158015906138c45750818114155b156138d6576138d3828861571a565b96505b81156138e25781880397505b8a8c8e7f0d31ab573f6daa4b1edba8d31973b4ba9f98fbfecc47010c1533eeefd2a1225a8686863360405161391a9493929190615bee565b60405180910390a4836001019350505050613842565b5050509550959350505050565b600061394c8460025484612736565b610100860151909150604f1c600190811603613a8957600086815260016020818152604080842081516080810183528981526002805463ffffffff9081168387019081528a82168487019081526001600160a01b03808e16606087019081528754808c018955978c5298909a209451958402909401948555519390960180549251955190971668010000000000000000027fffffffff0000000000000000000000000000000000000000ffffffffffffffff9587166401000000000267ffffffffffffffff19909316939096169290921717929092169290921790925590549051859088907f77813be0661650ddc1a5193ff2837df4162b251cb432651e2c060c3fc39756be90613a7c908790899033909283526001600160a01b03918216602084015216604082015260600190565b60405180910390a4613add565b613a9481848861277c565b604080516001600160a01b0385168152336020820152600091839189917fcf0c92a2c6d7c42f488326b0cb900104b99984b6b218db81cd29371364a35251910160405180910390a45b95945050505050565b600082815260016020908152604080832080548251818502810185019093528083528493849084015b82821015613b8157600084815260209081902060408051608081018252600286029092018054835260019081015463ffffffff8082168587015264010000000082041692840192909252680100000000000000009091046001600160a01b031660608301529083529092019101613b0f565b5050506000868152600160205260408120929350613ba0929150614907565b8051839060005b81811015613ea75782600003613c805760008781526001602052604090208451859083908110613bd957613bd9615139565b60209081029190910181015182546001818101855560009485529383902082516002909202019081559181015191909201805460408401516060909401516001600160a01b031668010000000000000000027fffffffff0000000000000000000000000000000000000000ffffffffffffffff63ffffffff9586166401000000000267ffffffffffffffff1990931695909416949094171791909116919091179055613e9f565b838181518110613c9257613c92615139565b6020026020010151600001518310613d2657838181518110613cb657613cb6615139565b60200260200101516000015183039250613d1d848281518110613cdb57613cdb615139565b602002602001015160000151858381518110613cf957613cf9615139565b60200260200101516020015163ffffffff1686848151811061137657611376615139565b85019450613e9f565b60016000888152602001908152602001600020604051806080016040528085878581518110613d5757613d57615139565b602002602001015160000151038152602001868481518110613d7b57613d7b615139565b60200260200101516020015163ffffffff168152602001868481518110613da457613da4615139565b60200260200101516040015163ffffffff168152602001868481518110613dcd57613dcd615139565b6020908102919091018101516060908101516001600160a01b039081169093528454600181810187556000968752958390208551600290920201908155918401519190940180546040850151949095015190921668010000000000000000027fffffffff0000000000000000000000000000000000000000ffffffffffffffff63ffffffff9485166401000000000267ffffffffffffffff19909616949092169390931793909317929092161790558351613e96908490869084908110613cf957613cf9615139565b85019450600092505b600101613ba7565b50604080518381523360208201528591879189917f59860d79d97c1fce2be7f987915c631471f4b08f671200463cc40a3380194ffb910160405180910390a450505092915050565b60c08501516000906001600160a01b0316156142a357633b9aca00821480613f33575060c08601516001600160a01b031660009081526004602052604090205460ff165b15613f3f575081613f51565b613f4c8360025484612736565b830390505b60006040518060c001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020018381526020017f0000000000000000000000000000000000000000000000000000000000000000815260200187815260200186815260200188815250905060006060613ffd8960c001517f9d740bfa000000000000000000000000000000000000000000000000000000006147ba565b1561416e578860c001516001600160a01b0316639d740bfa61eeee6001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614614057576000614059565b855b604080516001600160e01b031960e085901b16815287516001600160a01b0390811660048301526020808a01516024840152838a015160448401526060808b015160648501526080808c0151608486015260a0808d01518051151560a488015293840151151560c48701529583015160e48601529082015161010485015281015182166101248401529283015161014483015260c090920151909116610164820152610184016000604051808303818588803b15801561411857600080fd5b505af19350505050801561412a575060015b614169573d808015614158576040519150601f19603f3d011682016040523d82523d6000602084013e61415d565b606091505b50600192509050614173565b614173565b600291505b811561429b5760405163e7c8e3e360e01b81526004810189905260248101879052600094507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7c8e3e390604401600060405180830381600087803b1580156141e657600080fd5b505af11580156141fa573d6000803e3d6000fd5b50505050877f290b5df59e172593762964e4f8ed2b4a9192d3197bfd2be4bae123908f8007968a888560011461427f5760405160200161426b906020808252600c908201527f49455243313635206661696c0000000000000000000000000000000000000000604082015260600190565b604051602081830303815290604052614281565b845b336040516142929493929190615c75565b60405180910390a25b505050613add565b60608601511561475d576060860151604051630862026560e41b81526000916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691638620265091614333917f0000000000000000000000000000000000000000000000000000000000000000906004019182526001600160a01b0316602082015260400190565b602060405180830381865afa158015614350573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143749190615077565b90506001600160a01b0381166143b6576040517f6921234300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b0381163014806143d05750633b9aca0083145b806143f357506001600160a01b03811660009081526004602052604090205460ff165b1561440057839150614412565b61440d8460025485612736565b840391505b6040805160208082528183019092526000916020820181803683370190505090508660405160200161444691815260200190565b604051602081830303815290604052905087602001511561462857816001600160a01b0316630cf8e85861eeee6001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316146144b25760006144b4565b845b8a60600151867f0000000000000000000000000000000000000000000000000000000000000000866040518663ffffffff1660e01b81526004016144fb94939291906150fd565b6000604051808303818588803b15801561451457600080fd5b505af193505050508015614526575060015b614623573d808015614554576040519150601f19603f3d011682016040523d82523d6000602084013e614559565b606091505b5060405163e7c8e3e360e01b81526004810189905260248101879052600094507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7c8e3e390604401600060405180830381600087803b1580156145c757600080fd5b505af11580156145db573d6000803e3d6000fd5b50505050877f290b5df59e172593762964e4f8ed2b4a9192d3197bfd2be4bae123908f8007968a8884336040516146159493929190615c75565b60405180910390a250614756565b614756565b816001600160a01b0316631ebc263f61eeee6001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161461467957600061467b565b845b60608b015160808c015187907f0000000000000000000000000000000000000000000000000000000000000000906001600160a01b03166146bc57336146c2565b8d608001515b8e516040516001600160e01b031960e089901b1681526146ed95949392916000918b9060040161572d565b60206040518083038185885af193505050508015614728575060408051601f3d908101601f1916820190925261472591810190615094565b60015b61429b573d808015614554576040519150601f19603f3d011682016040523d82523d6000602084013e614559565b5050613add565b60808601516000906001600160a01b0316614778573361477e565b86608001515b9050633b9aca008303614793578391506147a5565b6147a08460025485612736565b840391505b6147b0308284611b2b565b5095945050505050565b60006147c5836147d6565b801561277557506127758383614809565b60006147e9826301ffc9a760e01b614809565b80156108d25750614802826001600160e01b0319614809565b1592915050565b604080516001600160e01b0319831660248083019190915282518083039091018152604490910182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166301ffc9a760e01b179052905160009190829081906001600160a01b0387169061753090614885908690615d0b565b6000604051808303818686fa925050503d80600081146148c1576040519150601f19603f3d011682016040523d82523d6000602084013e6148c6565b606091505b50915091506020815110156148e157600093505050506108d2565b8180156148fd5750808060200190518101906148fd9190615031565b9695505050505050565b5080546000825560020290600052602060002090810190611a8691905b8082111561494a57600081556001810180546001600160e01b0319169055600201614924565b5090565b60006020828403121561496057600080fd5b81356001600160e01b03198116811461277557600080fd5b6001600160a01b0381168114611a8657600080fd5b60008083601f84011261499f57600080fd5b50813567ffffffffffffffff8111156149b757600080fd5b6020830191508360208285010111156149cf57600080fd5b9250929050565b600080600080600080600060a0888a0312156149f157600080fd5b87359650602088013595506040880135614a0a81614978565b9450606088013567ffffffffffffffff80821115614a2757600080fd5b614a338b838c0161498d565b909650945060808a0135915080821115614a4c57600080fd5b50614a598a828b0161498d565b989b979a50959850939692959293505050565b600060208284031215614a7e57600080fd5b813561277581614978565b8015158114611a8657600080fd5b6000806000806000806000806000806101008b8d031215614ab757600080fd5b8a35995060208b0135985060408b0135614ad081614978565b975060608b0135614ae081614978565b965060808b0135955060a08b0135614af781614a89565b945060c08b013567ffffffffffffffff80821115614b1457600080fd5b614b208e838f0161498d565b909650945060e08d0135915080821115614b3957600080fd5b50614b468d828e0161498d565b915080935050809150509295989b9194979a5092959850565b60008060408385031215614b7257600080fd5b823591506020830135614b8481614978565b809150509250929050565b600080600080600080600060c0888a031215614baa57600080fd5b8735965060208801359550604088013594506060880135614bca81614978565b93506080880135925060a088013567ffffffffffffffff811115614bed57600080fd5b614a598a828b0161498d565b600060208284031215614c0b57600080fd5b5035919050565b60008060408385031215614c2557600080fd5b8235614c3081614978565b91506020830135614b8481614a89565b602080825282518282018190526000919060409081850190868401855b82811015614ca9578151805185528681015163ffffffff908116888701528682015116868601526060908101516001600160a01b03169085015260809093019290850190600101614c5d565b5091979650505050505050565b634e487b7160e01b600052604160045260246000fd5b604051610120810167ffffffffffffffff81118282101715614cf057614cf0614cb6565b60405290565b6040805190810167ffffffffffffffff81118282101715614cf057614cf0614cb6565b60405160e0810167ffffffffffffffff81118282101715614cf057614cf0614cb6565b604051601f8201601f1916810167ffffffffffffffff81118282101715614d6557614d65614cb6565b604052919050565b600067ffffffffffffffff821115614d8757614d87614cb6565b50601f01601f191660200190565b600082601f830112614da657600080fd5b8135614db9614db482614d6d565b614d3c565b818152846020838601011115614dce57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060008060006101008a8c031215614e0a57600080fd5b8935985060208a0135975060408a0135965060608a0135614e2a81614978565b955060808a0135945060a08a0135614e4181614978565b935060c08a013567ffffffffffffffff80821115614e5e57600080fd5b614e6a8d838e01614d95565b945060e08c0135915080821115614e8057600080fd5b50614e8d8c828d0161498d565b915080935050809150509295985092959850929598565b60008060008060008060008060c0898b031215614ec057600080fd5b88359750602089013596506040890135614ed981614978565b95506060890135614ee981614a89565b9450608089013567ffffffffffffffff80821115614f0657600080fd5b614f128c838d0161498d565b909650945060a08b0135915080821115614f2b57600080fd5b50614f388b828c0161498d565b999c989b5096995094979396929594505050565b60008060408385031215614f5f57600080fd5b8235614f6a81614978565b946020939093013593505050565b600080600080600080600080610100898b031215614f9557600080fd5b8835614fa081614978565b975060208901359650604089013595506060890135614fbe81614978565b94506080890135935060a0890135614fd581614978565b925060c089013567ffffffffffffffff80821115614ff257600080fd5b614ffe8c838d01614d95565b935060e08b013591508082111561501457600080fd5b506150218b828c01614d95565b9150509295985092959890939650565b60006020828403121561504357600080fd5b815161277581614a89565b634e487b7160e01b600052601160045260246000fd5b818103818111156108d2576108d261504e565b60006020828403121561508957600080fd5b815161277581614978565b6000602082840312156150a657600080fd5b5051919050565b60005b838110156150c85781810151838201526020016150b0565b50506000910152565b600081518084526150e98160208601602086016150ad565b601f01601f19169290920160200192915050565b8481528360208201526001600160a01b038316604082015260a06060820152600060a082015260c0608082015260006148fd60c08301846150d1565b634e487b7160e01b600052603260045260246000fd5b600181815b8085111561518a5781600019048211156151705761517061504e565b8085161561517d57918102915b93841c9390800290615154565b509250929050565b6000826151a1575060016108d2565b816151ae575060006108d2565b81600181146151c457600281146151ce576151ea565b60019150506108d2565b60ff8411156151df576151df61504e565b50506001821b6108d2565b5060208310610133831016604e8410600b841016171561520d575081810a6108d2565b615217838361514f565b806000190482111561522b5761522b61504e565b029392505050565b60006127758383615192565b60006101406001600160a01b03808b168452615288602085018b6001600160a01b0381511682526020810151602083015260408101516040830152606081015160608301525050565b8860a08501528760c085015280871660e085015250806101008401526152b0818401866150d1565b90508281036101208401526152c581856150d1565b9a9950505050505050505050565b80516152de81614978565b919050565b600061012082840312156152f657600080fd5b6152fe614ccc565b9050815181526020820151602082015260408201516040820152606082015160608201526080820151608082015260a082015160a082015260c082015160c082015261534c60e083016152d3565b60e082015261010080830151818301525092915050565b600067ffffffffffffffff82111561537d5761537d614cb6565b5060051b60200190565b600082601f83011261539857600080fd5b81516153a6614db482614d6d565b8181528460208386010111156153bb57600080fd5b6117fd8260208301602087016150ad565b60008060008061018085870312156153e357600080fd5b6153ed86866152e3565b9350610120850151925061014085015167ffffffffffffffff8082111561541357600080fd5b818701915087601f83011261542757600080fd5b81516020615437614db483615363565b82815260069290921b8401810191818101908b84111561545657600080fd5b948201945b838610156154a2576040868d0312156154745760008081fd5b61547c614cf6565b865161548781614978565b8152868401518482015282526040909501949082019061545b565b6101608b01519097509450505050808211156154bd57600080fd5b506154ca87828801615387565b91505092959194509250565b80516001600160a01b031682526000610200602083810151858201526040808501518187015260608086015180516001600160a01b0316828901529283015160808801529082015160a087015281015160c086015250608083015180516001600160a01b031660e08601526020810151610100860152604081015161012086015260608101516101408601525060a083015161016085015260c08301516001600160a01b0381166101808601525060e08301518015156101a086015250610100830151816101c08601526155ac828601826150d1565b9150506101208301518482036101e0860152613add82826150d1565b60208152600061277560208301846154d6565b6060815260006155ee60608301866154d6565b90508360208301526001600160a01b0383166040830152949350505050565b60006001600160a01b03808a168352808916602084015287604084015286606084015260e0608084015261564460e08401876150d1565b83810360a085015261565681876150d1565b92505080841660c08401525098975050505050505050565b600080610140838503121561568257600080fd5b61568c84846152e3565b915061012083015190509250929050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60006001600160a01b03808b16835289602084015288604084015287606084015286608084015260e060a084015261570260e08401868861569d565b915080841660c0840152509998505050505050505050565b808201808211156108d2576108d261504e565b60006101008983528860208401526001600160a01b03808916604085015280881660608501525085608084015284151560a08401528060c0840152600081840152506101208060e08401526152c5818401856150d1565b83815260606020820152600061579d60608301856150d1565b90506001600160a01b0383166040830152949350505050565b60006001600160a01b03808b16835289602084015288604084015287606084015260e060808401526157eb60e08401886150d1565b83810360a08501526157fe81878961569d565b92505080841660c0840152509998505050505050505050565b60008160001904831182151516156158315761583161504e565b500290565b634e487b7160e01b600052601260045260246000fd5b60008261586957634e487b7160e01b600052601260045260246000fd5b500490565b85815284602082015260a06040820152600061588d60a08301866150d1565b828103606084015261589f81866150d1565b9150506001600160a01b03831660808301529695505050505050565b6001600160a01b038616815284602082015283604082015260a0606082015260006158e960a08301856150d1565b8281036080840152610ecf81856150d1565b600080600080610180858703121561591257600080fd5b61591c86866152e3565b9350610120850151925061014085015167ffffffffffffffff8082111561594257600080fd5b818701915087601f83011261595657600080fd5b81516020615966614db483615363565b82815260069290921b8401810191818101908b84111561598557600080fd5b948201945b838610156154a2576040868d0312156159a35760008081fd5b6159ab614cf6565b86516159b681614978565b8152868401518482015282526040909501949082019061598a565b80516001600160a01b0316825260006101e06020830151602085015260408301516040850152606083015160608501526080830151615a3d60808601826001600160a01b0381511682526020810151602083015260408101516040830152606081015160608301525050565b5060a083015180516001600160a01b03908116610100878101919091526020830151610120880152604083015161014088015260609092015161016087015260c08501511661018086015260e08401516101a0860183905290615aa2838701836150d1565b9250808501519150508482036101c0860152613add82826150d1565b60208152600061277560208301846159d1565b6060815260006155ee60608301866159d1565b60006020808385031215615af757600080fd5b825167ffffffffffffffff811115615b0e57600080fd5b8301601f81018513615b1f57600080fd5b8051615b2d614db482615363565b81815260e09182028301840191848201919088841115615b4c57600080fd5b938501935b83851015615be25780858a031215615b695760008081fd5b615b71614d19565b8551615b7c81614a89565b815285870151615b8b81614a89565b818801526040868101519082015260608087015190820152608080870151615bb281614978565b9082015260a0868101519082015260c080870151615bcf81614978565b9082015283529384019391850191615b51565b50979650505050505050565b6101408101615c4f8287805115158252602081015115156020830152604081015160408301526060810151606083015260808101516001600160a01b03808216608085015260a083015160a08501528060c08401511660c085015250505050565b8460e0830152836101008301526001600160a01b03831661012083015295945050505050565b6000610140615cd68388805115158252602081015115156020830152604081015160408301526060810151606083015260808101516001600160a01b03808216608085015260a083015160a08501528060c08401511660c085015250505050565b8560e084015280610100840152615cef818401866150d1565b9150506001600160a01b03831661012083015295945050505050565b60008251615d1d8184602087016150ad565b919091019291505056fea2646970667358221220fd8d04f3b3bf048a392c4449e52316e1254a93b3c05809d0cda55460ad15b53764736f6c63430008100033", "devdoc": { diff --git a/deployments/goerli/JBSingleTokenPaymentTerminalStore.json b/deployments/goerli/JBSingleTokenPaymentTerminalStore.json index 1bee49efe..48a094336 100644 --- a/deployments/goerli/JBSingleTokenPaymentTerminalStore.json +++ b/deployments/goerli/JBSingleTokenPaymentTerminalStore.json @@ -816,7 +816,7 @@ ], "numDeployments": 1, "solcInputHash": "7f5ae5369c2a685c882e67f75315b841", - "metadata": "{\"compiler\":{\"version\":\"0.8.16+commit.07a7930e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IJBDirectory\",\"name\":\"_directory\",\"type\":\"address\"},{\"internalType\":\"contract IJBFundingCycleStore\",\"name\":\"_fundingCycleStore\",\"type\":\"address\"},{\"internalType\":\"contract IJBPrices\",\"name\":\"_prices\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CURRENCY_MISMATCH\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DISTRIBUTION_AMOUNT_LIMIT_REACHED\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FUNDING_CYCLE_DISTRIBUTION_PAUSED\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FUNDING_CYCLE_PAYMENT_PAUSED\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FUNDING_CYCLE_REDEEM_PAUSED\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INADEQUATE_CONTROLLER_ALLOWANCE\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INSUFFICIENT_TOKENS\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INVALID_AMOUNT_TO_SEND_DELEGATE\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INVALID_FUNDING_CYCLE\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"prod1\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"denominator\",\"type\":\"uint256\"}],\"name\":\"PRBMath__MulDivOverflow\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminal\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminal\",\"name\":\"_terminal\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"}],\"name\":\"currentOverflowOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_tokenCount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_overflow\",\"type\":\"uint256\"}],\"name\":\"currentReclaimableOverflowOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminal\",\"name\":\"_terminal\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_tokenCount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"_useTotalOverflow\",\"type\":\"bool\"}],\"name\":\"currentReclaimableOverflowOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_decimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_currency\",\"type\":\"uint256\"}],\"name\":\"currentTotalOverflowOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"directory\",\"outputs\":[{\"internalType\":\"contract IJBDirectory\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fundingCycleStore\",\"outputs\":[{\"internalType\":\"contract IJBFundingCycleStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"prices\",\"outputs\":[{\"internalType\":\"contract IJBPrices\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"recordAddedBalanceFor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_currency\",\"type\":\"uint256\"}],\"name\":\"recordDistributionFor\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"configuration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"basedOn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"discountRate\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBFundingCycleBallot\",\"name\":\"ballot\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"metadata\",\"type\":\"uint256\"}],\"internalType\":\"struct JBFundingCycle\",\"name\":\"fundingCycle\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"distributedAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"}],\"name\":\"recordMigration\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_payer\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"decimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"currency\",\"type\":\"uint256\"}],\"internalType\":\"struct JBTokenAmount\",\"name\":\"_amount\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_baseWeightCurrency\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"recordPaymentFrom\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"configuration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"basedOn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"discountRate\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBFundingCycleBallot\",\"name\":\"ballot\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"metadata\",\"type\":\"uint256\"}],\"internalType\":\"struct JBFundingCycle\",\"name\":\"fundingCycle\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"tokenCount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"contract IJBPayDelegate\",\"name\":\"delegate\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"struct JBPayDelegateAllocation[]\",\"name\":\"delegateAllocations\",\"type\":\"tuple[]\"},{\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_holder\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_tokenCount\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"recordRedemptionFor\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"configuration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"basedOn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"discountRate\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBFundingCycleBallot\",\"name\":\"ballot\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"metadata\",\"type\":\"uint256\"}],\"internalType\":\"struct JBFundingCycle\",\"name\":\"fundingCycle\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"reclaimAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"contract IJBRedemptionDelegate\",\"name\":\"delegate\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"struct JBRedemptionDelegateAllocation[]\",\"name\":\"delegateAllocations\",\"type\":\"tuple[]\"},{\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_currency\",\"type\":\"uint256\"}],\"name\":\"recordUsedAllowanceOf\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"configuration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"basedOn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"discountRate\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBFundingCycleBallot\",\"name\":\"ballot\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"metadata\",\"type\":\"uint256\"}],\"internalType\":\"struct JBFundingCycle\",\"name\":\"fundingCycle\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"usedAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminal\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"usedDistributionLimitOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminal\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"usedOverflowAllowanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Adheres to: IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.Inherits from - ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_directory\":\"A contract storing directories of terminals and controllers for each project.\",\"_fundingCycleStore\":\"A contract storing all funding cycle configurations.\",\"_prices\":\"A contract that exposes price feeds.\"}},\"currentOverflowOf(address,uint256)\":{\"details\":\"The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\",\"params\":{\"_projectId\":\"The ID of the project to get overflow for.\",\"_terminal\":\"The terminal for which the overflow is being calculated.\"},\"returns\":{\"_0\":\"The current amount of overflow that project has in the specified terminal.\"}},\"currentReclaimableOverflowOf(address,uint256,uint256,bool)\":{\"details\":\" If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.The current reclaimable overflow is returned in terms of the specified terminal's currency.The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\",\"params\":{\"_projectId\":\"The ID of the project to get the reclaimable overflow amount for.\",\"_terminal\":\"The terminal from which the reclaimable amount would come.\",\"_tokenCount\":\"The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\",\"_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`.\"},\"returns\":{\"_0\":\"The amount of overflowed tokens that can be reclaimed, as a fixed point number with the same number of decimals as the provided `_terminal`.\"}},\"currentReclaimableOverflowOf(uint256,uint256,uint256,uint256)\":{\"details\":\" If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\",\"params\":{\"_overflow\":\"The amount of overflow to make the calculation with, as a fixed point number.\",\"_projectId\":\"The ID of the project to get the reclaimable overflow amount for.\",\"_tokenCount\":\"The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\",\"_totalSupply\":\"The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\"},\"returns\":{\"_0\":\"The amount of overflowed tokens that can be reclaimed, as a fixed point number with the same number of decimals as the provided `_overflow`.\"}},\"currentTotalOverflowOf(uint256,uint256,uint256)\":{\"params\":{\"_currency\":\"The currency that the total overflow should be in terms of.\",\"_decimals\":\"The number of decimals that the fixed point overflow should include.\",\"_projectId\":\"The ID of the project to get total overflow for.\"},\"returns\":{\"_0\":\"The current total amount of overflow that project has across all terminals.\"}},\"recordAddedBalanceFor(uint256,uint256)\":{\"details\":\"The msg.sender must be an IJBSingleTokenPaymentTerminal. \",\"params\":{\"_amount\":\"The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\",\"_projectId\":\"The ID of the project to which the funds being added belong.\"}},\"recordDistributionFor(uint256,uint256,uint256)\":{\"details\":\"The msg.sender must be an IJBSingleTokenPaymentTerminal. \",\"params\":{\"_amount\":\"The amount to use from the distribution limit, as a fixed point number.\",\"_currency\":\"The currency of the `_amount`. This must match the project's current funding cycle's currency.\",\"_projectId\":\"The ID of the project that is having funds distributed.\"},\"returns\":{\"distributedAmount\":\"The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\",\"fundingCycle\":\"The funding cycle during which the distribution was made.\"}},\"recordMigration(uint256)\":{\"details\":\"The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\",\"params\":{\"_projectId\":\"The ID of the project being migrated.\"},\"returns\":{\"balance\":\"The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\"}},\"recordPaymentFrom(address,(address,uint256,uint256,uint256),uint256,uint256,address,string,bytes)\":{\"details\":\"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.The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\",\"params\":{\"_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.\",\"_baseWeightCurrency\":\"The currency to base token issuance on.\",\"_beneficiary\":\"The specified address that should be the beneficiary of anything that results from the payment.\",\"_memo\":\"A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\",\"_metadata\":\"Bytes to send along to the data source, if one is provided.\",\"_payer\":\"The original address that sent the payment to the terminal.\",\"_projectId\":\"The ID of the project being paid.\"},\"returns\":{\"delegateAllocations\":\"The amount to send to delegates instead of adding to the local balance.\",\"fundingCycle\":\"The project's funding cycle during which payment was made.\",\"memo\":\"A memo that should be passed along to the emitted event.\",\"tokenCount\":\"The number of project tokens that were minted, as a fixed point number with 18 decimals.\"}},\"recordRedemptionFor(address,uint256,uint256,string,bytes)\":{\"details\":\"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.The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\",\"params\":{\"_holder\":\"The account that is having its tokens redeemed.\",\"_memo\":\"A memo to pass along to the emitted event.\",\"_metadata\":\"Bytes to send along to the data source, if one is provided.\",\"_projectId\":\"The ID of the project to which the tokens being redeemed belong.\",\"_tokenCount\":\"The number of project tokens to redeem, as a fixed point number with 18 decimals.\"},\"returns\":{\"delegateAllocations\":\"The amount to send to delegates instead of sending to the beneficiary.\",\"fundingCycle\":\"The funding cycle during which the redemption was made.\",\"memo\":\"A memo that should be passed along to the emitted event.\",\"reclaimAmount\":\"The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\"}},\"recordUsedAllowanceOf(uint256,uint256,uint256)\":{\"details\":\"The msg.sender must be an IJBSingleTokenPaymentTerminal. \",\"params\":{\"_amount\":\"The amount to use from the allowance, as a fixed point number. \",\"_currency\":\"The currency of the `_amount`. Must match the currency of the overflow allowance.\",\"_projectId\":\"The ID of the project to use the allowance of.\"},\"returns\":{\"fundingCycle\":\"The funding cycle during which the overflow allowance is being used.\",\"usedAmount\":\"The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\"}}},\"stateVariables\":{\"balanceOf\":{\"details\":\"The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal. _terminal The terminal to which the balance applies. _projectId The ID of the project to get the balance of.\"},\"usedDistributionLimitOf\":{\"details\":\"Increases as projects use their preconfigured distribution limits.The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal. _terminal The terminal to which the used distribution limit applies. _projectId The ID of the project to get the used distribution limit of. _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\"},\"usedOverflowAllowanceOf\":{\"details\":\"Increases as projects use their allowance.The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal. _terminal The terminal to which the overflow allowance applies. _projectId The ID of the project to get the used overflow allowance of. _configuration The configuration of the during which the allowance was used.\"}},\"version\":1},\"userdoc\":{\"errors\":{\"PRBMath__MulDivOverflow(uint256,uint256)\":[{\"notice\":\"Emitted when the result overflows uint256.\"}]},\"kind\":\"user\",\"methods\":{\"balanceOf(address,uint256)\":{\"notice\":\"The amount of tokens that each project has for each terminal, in terms of the terminal's token.\"},\"currentOverflowOf(address,uint256)\":{\"notice\":\"Gets the current overflowed amount in a terminal for a specified project.\"},\"currentReclaimableOverflowOf(address,uint256,uint256,bool)\":{\"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.\"},\"currentReclaimableOverflowOf(uint256,uint256,uint256,uint256)\":{\"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.\"},\"currentTotalOverflowOf(uint256,uint256,uint256)\":{\"notice\":\"Gets the current overflowed amount for a specified project across all terminals.\"},\"directory()\":{\"notice\":\"The directory of terminals and controllers for projects.\"},\"fundingCycleStore()\":{\"notice\":\"The contract storing all funding cycle configurations.\"},\"prices()\":{\"notice\":\"The contract that exposes price feeds.\"},\"recordAddedBalanceFor(uint256,uint256)\":{\"notice\":\"Records newly added funds for the project.\"},\"recordDistributionFor(uint256,uint256,uint256)\":{\"notice\":\"Records newly distributed funds for a project.\"},\"recordMigration(uint256)\":{\"notice\":\"Records the migration of funds from this store.\"},\"recordPaymentFrom(address,(address,uint256,uint256,uint256),uint256,uint256,address,string,bytes)\":{\"notice\":\"Records newly contributed tokens to a project.\"},\"recordRedemptionFor(address,uint256,uint256,string,bytes)\":{\"notice\":\"Records newly redeemed tokens of a project.\"},\"recordUsedAllowanceOf(uint256,uint256,uint256)\":{\"notice\":\"Records newly used allowance funds of a project.\"},\"usedDistributionLimitOf(address,uint256,uint256)\":{\"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.\"},\"usedOverflowAllowanceOf(address,uint256,uint256)\":{\"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.\"}},\"notice\":\"Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/JBSingleTokenPaymentTerminalStore.sol\":\"JBSingleTokenPaymentTerminalStore\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/security/ReentrancyGuard.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuard {\\n // Booleans are more expensive than uint256 or any type that takes up a full\\n // word because each write operation emits an extra SLOAD to first read the\\n // slot's contents, replace the bits taken up by the boolean, and then write\\n // back. This is the compiler's defense against contract upgrades and\\n // pointer aliasing, and it cannot be disabled.\\n\\n // The values being non-zero value makes deployment a bit more expensive,\\n // but in exchange the refund on every call to nonReentrant will be lower in\\n // amount. Since refunds are capped to a percentage of the total\\n // transaction's gas, it is best to keep them low in cases like this one, to\\n // increase the likelihood of the full refund coming into effect.\\n uint256 private constant _NOT_ENTERED = 1;\\n uint256 private constant _ENTERED = 2;\\n\\n uint256 private _status;\\n\\n constructor() {\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and making it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n // On the first call to nonReentrant, _notEntered will be true\\n require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n _status = _ENTERED;\\n\\n _;\\n\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n _status = _NOT_ENTERED;\\n }\\n}\\n\",\"keccak256\":\"0x0e9621f60b2faabe65549f7ed0f24e8853a45c1b7990d47e8160e523683f3935\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool _approved) external;\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x516a22876c1fab47f49b1bc22b4614491cd05338af8bd2e7b382da090a079990\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"@paulrberg/contracts/math/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\nimport \\\"prb-math/contracts/PRBMath.sol\\\";\\n\",\"keccak256\":\"0x42821345981bc0434a90ba2268a2f5278dfe9e38166981d72fc7f3b776a29495\",\"license\":\"Unlicense\"},\"contracts/JBSingleTokenPaymentTerminalStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\\nimport '@paulrberg/contracts/math/PRBMath.sol';\\nimport './interfaces/IJBController.sol';\\nimport './interfaces/IJBFundingCycleDataSource.sol';\\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\\nimport './libraries/JBConstants.sol';\\nimport './libraries/JBCurrencies.sol';\\nimport './libraries/JBFixedPointNumber.sol';\\nimport './libraries/JBFundingCycleMetadataResolver.sol';\\nimport './structs/JBPayDelegateAllocation.sol';\\nimport './structs/JBPayParamsData.sol';\\n\\n/**\\n @notice\\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\\n\\n @dev\\n Adheres to:\\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n\\n @dev\\n Inherits from -\\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\\n*/\\ncontract JBSingleTokenPaymentTerminalStore is ReentrancyGuard, IJBSingleTokenPaymentTerminalStore {\\n // A library that parses the packed funding cycle metadata into a friendlier format.\\n using JBFundingCycleMetadataResolver for JBFundingCycle;\\n\\n //*********************************************************************//\\n // --------------------------- custom errors ------------------------- //\\n //*********************************************************************//\\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\\n error CURRENCY_MISMATCH();\\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\\n error FUNDING_CYCLE_PAYMENT_PAUSED();\\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\\n error FUNDING_CYCLE_REDEEM_PAUSED();\\n error INADEQUATE_CONTROLLER_ALLOWANCE();\\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\\n error INSUFFICIENT_TOKENS();\\n error INVALID_FUNDING_CYCLE();\\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\\n\\n //*********************************************************************//\\n // -------------------------- private constants ---------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \\n */\\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\\n\\n //*********************************************************************//\\n // ---------------- public immutable stored properties --------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The directory of terminals and controllers for projects.\\n */\\n IJBDirectory public immutable override directory;\\n\\n /**\\n @notice\\n The contract storing all funding cycle configurations.\\n */\\n IJBFundingCycleStore public immutable override fundingCycleStore;\\n\\n /**\\n @notice\\n The contract that exposes price feeds.\\n */\\n IJBPrices public immutable override prices;\\n\\n //*********************************************************************//\\n // --------------------- public stored properties -------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\\n\\n @dev\\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\\n\\n _terminal The terminal to which the balance applies.\\n _projectId The ID of the project to get the balance of.\\n */\\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\\n\\n /**\\n @notice\\n 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.\\n\\n @dev\\n Increases as projects use their preconfigured distribution limits.\\n\\n @dev\\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\\n\\n _terminal The terminal to which the used distribution limit applies.\\n _projectId The ID of the project to get the used distribution limit of.\\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\\n */\\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\\n public\\n override usedDistributionLimitOf;\\n\\n /**\\n @notice\\n 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.\\n\\n @dev\\n Increases as projects use their allowance.\\n\\n @dev\\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\\n\\n _terminal The terminal to which the overflow allowance applies.\\n _projectId The ID of the project to get the used overflow allowance of.\\n _configuration The configuration of the during which the allowance was used.\\n */\\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\\n public\\n override usedOverflowAllowanceOf;\\n\\n //*********************************************************************//\\n // ------------------------- external views -------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Gets the current overflowed amount in a terminal for a specified project.\\n\\n @dev\\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\\n\\n @param _terminal The terminal for which the overflow is being calculated.\\n @param _projectId The ID of the project to get overflow for.\\n\\n @return The current amount of overflow that project has in the specified terminal.\\n */\\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\\n external\\n view\\n override\\n returns (uint256)\\n {\\n // Return the overflow during the project's current funding cycle.\\n return\\n _overflowDuring(\\n _terminal,\\n _projectId,\\n fundingCycleStore.currentOf(_projectId),\\n _terminal.currency()\\n );\\n }\\n\\n /**\\n @notice\\n Gets the current overflowed amount for a specified project across all terminals.\\n\\n @param _projectId The ID of the project to get total overflow for.\\n @param _decimals The number of decimals that the fixed point overflow should include.\\n @param _currency The currency that the total overflow should be in terms of.\\n\\n @return The current total amount of overflow that project has across all terminals.\\n */\\n function currentTotalOverflowOf(\\n uint256 _projectId,\\n uint256 _decimals,\\n uint256 _currency\\n ) external view override returns (uint256) {\\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\\n }\\n\\n /**\\n @notice\\n 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.\\n\\n @dev \\n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\\n\\n @dev\\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\\n\\n @dev\\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\\n\\n @param _terminal The terminal from which the reclaimable amount would come.\\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\\n @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`.\\n\\n @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`.\\n */\\n function currentReclaimableOverflowOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n bool _useTotalOverflow\\n ) external view override returns (uint256) {\\n // Get a reference to the project's current funding cycle.\\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // Get the amount of current overflow.\\n // 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.\\n uint256 _currentOverflow = _useTotalOverflow\\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\\n\\n // If there's no overflow, there's no reclaimable overflow.\\n if (_currentOverflow == 0) return 0;\\n\\n // Get the number of outstanding tokens the project has.\\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\\n\\n // Can't redeem more tokens that is in the supply.\\n if (_tokenCount > _totalSupply) return 0;\\n\\n // Return the reclaimable overflow amount.\\n return\\n _reclaimableOverflowDuring(\\n _projectId,\\n _fundingCycle,\\n _tokenCount,\\n _totalSupply,\\n _currentOverflow\\n );\\n }\\n\\n /**\\n @notice\\n 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.\\n\\n @dev \\n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\\n\\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\\n\\n @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`.\\n */\\n function currentReclaimableOverflowOf(\\n uint256 _projectId,\\n uint256 _tokenCount,\\n uint256 _totalSupply,\\n uint256 _overflow\\n ) external view override returns (uint256) {\\n // If there's no overflow, there's no reclaimable overflow.\\n if (_overflow == 0) return 0;\\n\\n // Can't redeem more tokens that is in the supply.\\n if (_tokenCount > _totalSupply) return 0;\\n\\n // Get a reference to the project's current funding cycle.\\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // Return the reclaimable overflow amount.\\n return\\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\\n }\\n\\n //*********************************************************************//\\n // -------------------------- constructor ---------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @param _directory A contract storing directories of terminals and controllers for each project.\\n @param _fundingCycleStore A contract storing all funding cycle configurations.\\n @param _prices A contract that exposes price feeds.\\n */\\n constructor(\\n IJBDirectory _directory,\\n IJBFundingCycleStore _fundingCycleStore,\\n IJBPrices _prices\\n ) {\\n directory = _directory;\\n fundingCycleStore = _fundingCycleStore;\\n prices = _prices;\\n }\\n\\n //*********************************************************************//\\n // ---------------------- external transactions ---------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Records newly contributed tokens to a project.\\n\\n @dev\\n 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.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\\n\\n @param _payer The original address that sent the payment to the terminal.\\n @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.\\n @param _projectId The ID of the project being paid.\\n @param _baseWeightCurrency The currency to base token issuance on.\\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\\n @param _metadata Bytes to send along to the data source, if one is provided.\\n\\n @return fundingCycle The project's funding cycle during which payment was made.\\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\\n @return memo A memo that should be passed along to the emitted event.\\n */\\n function recordPaymentFrom(\\n address _payer,\\n JBTokenAmount calldata _amount,\\n uint256 _projectId,\\n uint256 _baseWeightCurrency,\\n address _beneficiary,\\n string calldata _memo,\\n bytes memory _metadata\\n )\\n external\\n override\\n nonReentrant\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 tokenCount,\\n JBPayDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n )\\n {\\n // Get a reference to the current funding cycle for the project.\\n fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // The project must have a funding cycle configured.\\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\\n\\n // Must not be paused.\\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\\n\\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\\n uint256 _weight;\\n\\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\\n // Create the params that'll be sent to the data source.\\n JBPayParamsData memory _data = JBPayParamsData(\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n _payer,\\n _amount,\\n _projectId,\\n fundingCycle.configuration,\\n _beneficiary,\\n fundingCycle.weight,\\n fundingCycle.reservedRate(),\\n _memo,\\n _metadata\\n );\\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\\n .payParams(_data);\\n }\\n // Otherwise use the funding cycle's weight\\n else {\\n _weight = fundingCycle.weight;\\n memo = _memo;\\n }\\n\\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\\n {\\n // Keep a reference to the amount that should be added to the project's balance.\\n uint256 _balanceDiff = _amount.value;\\n\\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\\n if (delegateAllocations.length != 0) {\\n for (uint256 _i; _i < delegateAllocations.length; ) {\\n // Get a reference to the amount to be delegated.\\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\\n\\n // Validate if non-zero.\\n if (_delegatedAmount != 0) {\\n // Can't delegate more than was paid.\\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\\n\\n // Decrement the total amount being added to the balance.\\n _balanceDiff = _balanceDiff - _delegatedAmount;\\n }\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n\\n // If there's no amount being recorded, there's nothing left to do.\\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\\n\\n // Add the correct balance difference to the token balance of the project.\\n if (_balanceDiff != 0)\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\\n _balanceDiff;\\n }\\n\\n // If there's no weight, token count must be 0 so there's nothing left to do.\\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\\n\\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\\n uint256 _decimals = _amount.decimals;\\n\\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\\n // 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`.\\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\\n ? 10**_decimals\\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\\n\\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\\n }\\n\\n /**\\n @notice\\n Records newly redeemed tokens of a project.\\n\\n @dev\\n 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.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\\n\\n @param _holder The account that is having its tokens redeemed.\\n @param _projectId The ID of the project to which the tokens being redeemed belong.\\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Bytes to send along to the data source, if one is provided.\\n\\n @return fundingCycle The funding cycle during which the redemption was made.\\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\\n @return memo A memo that should be passed along to the emitted event.\\n */\\n function recordRedemptionFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n string memory _memo,\\n bytes memory _metadata\\n )\\n external\\n override\\n nonReentrant\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 reclaimAmount,\\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n )\\n {\\n // Get a reference to the project's current funding cycle.\\n fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // The current funding cycle must not be paused.\\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\\n\\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\\n {\\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\\n JBTokenAmount memory _reclaimedTokenAmount;\\n uint256 _currentOverflow;\\n uint256 _totalSupply;\\n\\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\\n {\\n // Get a reference to the terminal's tokens.\\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\\n\\n // Get a reference to the terminal's decimals.\\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\\n\\n // Get areference to the terminal's currency.\\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\\n\\n // Get the amount of current overflow.\\n // 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.\\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\\n : _overflowDuring(\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n _projectId,\\n fundingCycle,\\n _currency\\n );\\n\\n // Get the number of outstanding tokens the project has.\\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\\n _projectId,\\n fundingCycle.reservedRate()\\n );\\n\\n // Can't redeem more tokens that is in the supply.\\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\\n\\n if (_currentOverflow != 0)\\n // Calculate reclaim amount using the current overflow amount.\\n reclaimAmount = _reclaimableOverflowDuring(\\n _projectId,\\n fundingCycle,\\n _tokenCount,\\n _totalSupply,\\n _currentOverflow\\n );\\n\\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\\n }\\n\\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\\n {\\n // Get a reference to the ballot state.\\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\\n\\n // Create the params that'll be sent to the data source.\\n JBRedeemParamsData memory _data = JBRedeemParamsData(\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n _holder,\\n _projectId,\\n fundingCycle.configuration,\\n _tokenCount,\\n _totalSupply,\\n _currentOverflow,\\n _reclaimedTokenAmount,\\n fundingCycle.useTotalOverflowForRedemptions(),\\n _state == JBBallotState.Active\\n ? fundingCycle.ballotRedemptionRate()\\n : fundingCycle.redemptionRate(),\\n _memo,\\n _metadata\\n );\\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\\n fundingCycle.dataSource()\\n ).redeemParams(_data);\\n }\\n } else {\\n memo = _memo;\\n }\\n }\\n\\n // Keep a reference to the amount that should be subtracted from the project's balance.\\n uint256 _balanceDiff = reclaimAmount;\\n\\n if (delegateAllocations.length != 0) {\\n // Validate all delegated amounts.\\n for (uint256 _i; _i < delegateAllocations.length; ) {\\n // Get a reference to the amount to be delegated.\\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\\n\\n // Validate if non-zero.\\n if (_delegatedAmount != 0)\\n // Increment the total amount being subtracted from the balance.\\n _balanceDiff = _balanceDiff + _delegatedAmount;\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n\\n // The amount being reclaimed must be within the project's balance.\\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\\n\\n // Remove the reclaimed funds from the project's balance.\\n if (_balanceDiff != 0) {\\n unchecked {\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\\n _balanceDiff;\\n }\\n }\\n }\\n\\n /**\\n @notice\\n Records newly distributed funds for a project.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \\n\\n @param _projectId The ID of the project that is having funds distributed.\\n @param _amount The amount to use from the distribution limit, as a fixed point number.\\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\\n\\n @return fundingCycle The funding cycle during which the distribution was made.\\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\\n */\\n function recordDistributionFor(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n )\\n external\\n override\\n nonReentrant\\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\\n {\\n // Get a reference to the project's current funding cycle.\\n fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // The funding cycle must not be configured to have distributions paused.\\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\\n\\n // The new total amount that has been distributed during this funding cycle.\\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\\n IJBSingleTokenPaymentTerminal(msg.sender)\\n ][_projectId][fundingCycle.number] + _amount;\\n\\n // Amount must be within what is still distributable.\\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\\n directory.controllerOf(_projectId)\\n ).distributionLimitOf(\\n _projectId,\\n fundingCycle.configuration,\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n IJBSingleTokenPaymentTerminal(msg.sender).token()\\n );\\n\\n // Make sure the new used amount is within the distribution limit.\\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\\n\\n // Make sure the currencies match.\\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\\n\\n // Get a reference to the terminal's currency.\\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\\n\\n // Convert the amount to the balance's currency.\\n distributedAmount = (_currency == _balanceCurrency)\\n ? _amount\\n : PRBMath.mulDiv(\\n _amount,\\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\\n );\\n\\n // The amount being distributed must be available.\\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\\n\\n // Store the new amount.\\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\\n fundingCycle.number\\n ] = _newUsedDistributionLimitOf;\\n\\n // Removed the distributed funds from the project's token balance.\\n unchecked {\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\\n distributedAmount;\\n }\\n }\\n\\n /**\\n @notice\\n Records newly used allowance funds of a project.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \\n\\n @param _projectId The ID of the project to use the allowance of.\\n @param _amount The amount to use from the allowance, as a fixed point number. \\n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\\n\\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\\n */\\n function recordUsedAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n )\\n external\\n override\\n nonReentrant\\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\\n {\\n // Get a reference to the project's current funding cycle.\\n fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\\n IJBSingleTokenPaymentTerminal(msg.sender)\\n ][_projectId][fundingCycle.configuration] + _amount;\\n\\n // There must be sufficient allowance available.\\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\\n directory.controllerOf(_projectId)\\n ).overflowAllowanceOf(\\n _projectId,\\n fundingCycle.configuration,\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n IJBSingleTokenPaymentTerminal(msg.sender).token()\\n );\\n\\n // Make sure the new used amount is within the allowance.\\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\\n\\n // Make sure the currencies match.\\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\\n\\n // Get a reference to the terminal's currency.\\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\\n\\n // Convert the amount to this store's terminal's token.\\n usedAmount = (_currency == _balanceCurrency)\\n ? _amount\\n : PRBMath.mulDiv(\\n _amount,\\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\\n );\\n\\n // The amount being distributed must be available in the overflow.\\n if (\\n usedAmount >\\n _overflowDuring(\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n _projectId,\\n fundingCycle,\\n _balanceCurrency\\n )\\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\\n\\n // Store the incremented value.\\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\\n fundingCycle.configuration\\n ] = _newUsedOverflowAllowanceOf;\\n\\n // Update the project's balance.\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\\n usedAmount;\\n }\\n\\n /**\\n @notice\\n Records newly added funds for the project.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \\n\\n @param _projectId The ID of the project to which the funds being added belong.\\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\\n */\\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\\n // Increment the balance.\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\\n _amount;\\n }\\n\\n /**\\n @notice\\n Records the migration of funds from this store.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\\n\\n @param _projectId The ID of the project being migrated.\\n\\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\\n */\\n function recordMigration(uint256 _projectId)\\n external\\n override\\n nonReentrant\\n returns (uint256 balance)\\n {\\n // Get a reference to the project's current funding cycle.\\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // Migration must be allowed.\\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\\n\\n // Return the current balance.\\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\\n\\n // Set the balance to 0.\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\\n }\\n\\n //*********************************************************************//\\n // --------------------- private helper functions -------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\\n\\n @dev \\n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\\n\\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\\n @param _overflow The amount of overflow to make the calculation with.\\n\\n @return The amount of overflowed tokens that can be reclaimed.\\n */\\n function _reclaimableOverflowDuring(\\n uint256 _projectId,\\n JBFundingCycle memory _fundingCycle,\\n uint256 _tokenCount,\\n uint256 _totalSupply,\\n uint256 _overflow\\n ) private view returns (uint256) {\\n // If the amount being redeemed is the total supply, return the rest of the overflow.\\n if (_tokenCount == _totalSupply) return _overflow;\\n\\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\\n JBBallotState.Active\\n ? _fundingCycle.ballotRedemptionRate()\\n : _fundingCycle.redemptionRate();\\n\\n // If the redemption rate is 0, nothing is claimable.\\n if (_redemptionRate == 0) return 0;\\n\\n // Get a reference to the linear proportion.\\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\\n\\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\\n\\n return\\n PRBMath.mulDiv(\\n _base,\\n _redemptionRate +\\n PRBMath.mulDiv(\\n _tokenCount,\\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\\n _totalSupply\\n ),\\n JBConstants.MAX_REDEMPTION_RATE\\n );\\n }\\n\\n /**\\n @notice\\n Gets the amount that is overflowing when measured from the specified funding cycle.\\n\\n @dev\\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\\n\\n @param _terminal The terminal for which the overflow is being calculated.\\n @param _projectId The ID of the project to get overflow for.\\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\\n\\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\\n */\\n function _overflowDuring(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n JBFundingCycle memory _fundingCycle,\\n uint256 _balanceCurrency\\n ) private view returns (uint256) {\\n // Get the current balance of the project.\\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\\n\\n // If there's no balance, there's no overflow.\\n if (_balanceOf == 0) return 0;\\n\\n // Get a reference to the distribution limit during the funding cycle.\\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\\n directory.controllerOf(_projectId)\\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\\n\\n // Get a reference to the amount still distributable during the funding cycle.\\n uint256 _distributionLimitRemaining = _distributionLimit -\\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\\n\\n // Convert the _distributionRemaining to be in terms of the provided currency.\\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\\n _distributionLimitRemaining = PRBMath.mulDiv(\\n _distributionLimitRemaining,\\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\\n );\\n\\n // Overflow is the balance of this project minus the amount that can still be distributed.\\n unchecked {\\n return\\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\\n }\\n }\\n\\n /**\\n @notice\\n Gets the amount that is currently overflowing across all of a project's terminals. \\n\\n @dev\\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\\n\\n @param _projectId The ID of the project to get the total overflow for.\\n @param _decimals The number of decimals that the fixed point overflow should include.\\n @param _currency The currency that the overflow should be in terms of.\\n\\n @return overflow The total overflow of a project's funds.\\n */\\n function _currentTotalOverflowOf(\\n uint256 _projectId,\\n uint256 _decimals,\\n uint256 _currency\\n ) private view returns (uint256) {\\n // Get a reference to the project's terminals.\\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\\n\\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\\n uint256 _ethOverflow;\\n\\n // Add the current ETH overflow for each terminal.\\n for (uint256 _i; _i < _terminals.length; ) {\\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\\n unchecked {\\n ++_i;\\n }\\n }\\n\\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.ETH\\n ? _ethOverflow\\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.ETH, _currency, 18));\\n\\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\\n return\\n (_decimals == 18)\\n ? _totalOverflow18Decimal\\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\\n }\\n}\\n\",\"keccak256\":\"0x17c0330168982f5da39eb12537ff22871b2d73220ca1012c1ad59d6999db7dd6\",\"license\":\"MIT\"},\"contracts/enums/JBBallotState.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nenum JBBallotState {\\n Active,\\n Approved,\\n Failed\\n}\\n\",\"keccak256\":\"0x891fcac63470398b3a11239da7feba6b07d640809fcefd2404303b823d7378f8\",\"license\":\"MIT\"},\"contracts/interfaces/IJBController.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBFundAccessConstraints.sol';\\nimport './../structs/JBFundingCycleData.sol';\\nimport './../structs/JBFundingCycleMetadata.sol';\\nimport './../structs/JBGroupedSplits.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBMigratable.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBSplitsStore.sol';\\nimport './IJBTokenStore.sol';\\n\\ninterface IJBController is IERC165 {\\n event LaunchProject(uint256 configuration, uint256 projectId, string memo, address caller);\\n\\n event LaunchFundingCycles(uint256 configuration, uint256 projectId, string memo, address caller);\\n\\n event ReconfigureFundingCycles(\\n uint256 configuration,\\n uint256 projectId,\\n string memo,\\n address caller\\n );\\n\\n event SetFundAccessConstraints(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n JBFundAccessConstraints constraints,\\n address caller\\n );\\n\\n event DistributeReservedTokens(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address beneficiary,\\n uint256 tokenCount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n address caller\\n );\\n\\n event DistributeToReservedTokenSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n uint256 tokenCount,\\n address caller\\n );\\n\\n event MintTokens(\\n address indexed beneficiary,\\n uint256 indexed projectId,\\n uint256 tokenCount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n uint256 reservedRate,\\n address caller\\n );\\n\\n event BurnTokens(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 tokenCount,\\n string memo,\\n address caller\\n );\\n\\n event Migrate(uint256 indexed projectId, IJBMigratable to, address caller);\\n\\n event PrepMigration(uint256 indexed projectId, address from, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function tokenStore() external view returns (IJBTokenStore);\\n\\n function splitsStore() external view returns (IJBSplitsStore);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function reservedTokenBalanceOf(uint256 _projectId, uint256 _reservedRate)\\n external\\n view\\n returns (uint256);\\n\\n function distributionLimitOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n IJBPaymentTerminal _terminal,\\n address _token\\n ) external view returns (uint256 distributionLimit, uint256 distributionLimitCurrency);\\n\\n function overflowAllowanceOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n IJBPaymentTerminal _terminal,\\n address _token\\n ) external view returns (uint256 overflowAllowance, uint256 overflowAllowanceCurrency);\\n\\n function totalOutstandingTokensOf(uint256 _projectId, uint256 _reservedRate)\\n external\\n view\\n returns (uint256);\\n\\n function getFundingCycleOf(uint256 _projectId, uint256 _configuration)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function latestConfiguredFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (\\n JBFundingCycle memory,\\n JBFundingCycleMetadata memory metadata,\\n JBBallotState\\n );\\n\\n function currentFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function queuedFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function launchProjectFor(\\n address _owner,\\n JBProjectMetadata calldata _projectMetadata,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n IJBPaymentTerminal[] memory _terminals,\\n string calldata _memo\\n ) external returns (uint256 projectId);\\n\\n function launchFundingCyclesFor(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n IJBPaymentTerminal[] memory _terminals,\\n string calldata _memo\\n ) external returns (uint256 configuration);\\n\\n function reconfigureFundingCyclesOf(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n string calldata _memo\\n ) external returns (uint256);\\n\\n function mintTokensOf(\\n uint256 _projectId,\\n uint256 _tokenCount,\\n address _beneficiary,\\n string calldata _memo,\\n bool _preferClaimedTokens,\\n bool _useReservedRate\\n ) external returns (uint256 beneficiaryTokenCount);\\n\\n function burnTokensOf(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n string calldata _memo,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function distributeReservedTokensOf(uint256 _projectId, string memory _memo)\\n external\\n returns (uint256);\\n\\n function migrate(uint256 _projectId, IJBMigratable _to) external;\\n}\\n\",\"keccak256\":\"0xb1ee4b41f2a06f28f69c74cb729b8964f2e75f3c545a68f85bd9082b5575bc85\",\"license\":\"MIT\"},\"contracts/interfaces/IJBDirectory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBProjects.sol';\\n\\ninterface IJBDirectory {\\n event SetController(uint256 indexed projectId, address indexed controller, address caller);\\n\\n event AddTerminal(uint256 indexed projectId, IJBPaymentTerminal indexed terminal, address caller);\\n\\n event SetTerminals(uint256 indexed projectId, IJBPaymentTerminal[] terminals, address caller);\\n\\n event SetPrimaryTerminal(\\n uint256 indexed projectId,\\n address indexed token,\\n IJBPaymentTerminal indexed terminal,\\n address caller\\n );\\n\\n event SetIsAllowedToSetFirstController(address indexed addr, bool indexed flag, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function controllerOf(uint256 _projectId) external view returns (address);\\n\\n function isAllowedToSetFirstController(address _address) external view returns (bool);\\n\\n function terminalsOf(uint256 _projectId) external view returns (IJBPaymentTerminal[] memory);\\n\\n function isTerminalOf(uint256 _projectId, IJBPaymentTerminal _terminal)\\n external\\n view\\n returns (bool);\\n\\n function primaryTerminalOf(uint256 _projectId, address _token)\\n external\\n view\\n returns (IJBPaymentTerminal);\\n\\n function setControllerOf(uint256 _projectId, address _controller) external;\\n\\n function setTerminalsOf(uint256 _projectId, IJBPaymentTerminal[] calldata _terminals) external;\\n\\n function setPrimaryTerminalOf(\\n uint256 _projectId,\\n address _token,\\n IJBPaymentTerminal _terminal\\n ) external;\\n\\n function setIsAllowedToSetFirstController(address _address, bool _flag) external;\\n}\\n\",\"keccak256\":\"0x715321646db00514d1355ed43c40cd3f01e94959552fd07797b315d9c49cdb1d\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleBallot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../enums/JBBallotState.sol';\\n\\ninterface IJBFundingCycleBallot is IERC165 {\\n function duration() external view returns (uint256);\\n\\n function stateOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n uint256 _start\\n ) external view returns (JBBallotState);\\n}\\n\",\"keccak256\":\"0x49553a56209237846bc400cf27f260824a6bd06fd8094a7eb5abb9de75779598\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleDataSource.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBPayDelegateAllocation.sol';\\nimport './../structs/JBPayParamsData.sol';\\nimport './../structs/JBRedeemParamsData.sol';\\nimport './../structs/JBRedemptionDelegateAllocation.sol';\\n\\n/**\\n @title\\n Datasource\\n\\n @notice\\n The datasource is called by JBPaymentTerminal on pay and redemption, and provide an extra layer of logic to use \\n a custom weight, a custom memo and/or a pay/redeem delegate\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n*/\\ninterface IJBFundingCycleDataSource is IERC165 {\\n /**\\n @notice\\n The datasource implementation for JBPaymentTerminal.pay(..)\\n\\n @param _data the data passed to the data source in terminal.pay(..), as a JBPayParamsData struct:\\n IJBPaymentTerminal terminal;\\n address payer;\\n JBTokenAmount amount;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n address beneficiary;\\n uint256 weight;\\n uint256 reservedRate;\\n string memo;\\n bytes metadata;\\n\\n @return weight the weight to use to override the funding cycle weight\\n @return memo the memo to override the pay(..) memo\\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\\n */\\n function payParams(JBPayParamsData calldata _data)\\n external\\n returns (\\n uint256 weight,\\n string memory memo,\\n JBPayDelegateAllocation[] memory delegateAllocations\\n );\\n\\n /**\\n @notice\\n The datasource implementation for JBPaymentTerminal.redeemTokensOf(..)\\n\\n @param _data the data passed to the data source in terminal.redeemTokensOf(..), as a JBRedeemParamsData struct:\\n IJBPaymentTerminal terminal;\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 tokenCount;\\n uint256 totalSupply;\\n uint256 overflow;\\n JBTokenAmount reclaimAmount;\\n bool useTotalOverflow;\\n uint256 redemptionRate;\\n uint256 ballotRedemptionRate;\\n string memo;\\n bytes metadata;\\n\\n @return reclaimAmount The amount to claim, overriding the terminal logic.\\n @return memo The memo to override the redeemTokensOf(..) memo.\\n @return delegateAllocations The amount to send to delegates instead of adding to the beneficiary.\\n */\\n function redeemParams(JBRedeemParamsData calldata _data)\\n external\\n returns (\\n uint256 reclaimAmount,\\n string memory memo,\\n JBRedemptionDelegateAllocation[] memory delegateAllocations\\n );\\n}\\n\",\"keccak256\":\"0xa424abc146a61b69db83e511c064492da6fab6d8226e13d1580bc9fbc50d6738\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../enums/JBBallotState.sol';\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBFundingCycleData.sol';\\n\\ninterface IJBFundingCycleStore {\\n event Configure(\\n uint256 indexed configuration,\\n uint256 indexed projectId,\\n JBFundingCycleData data,\\n uint256 metadata,\\n uint256 mustStartAtOrAfter,\\n address caller\\n );\\n\\n event Init(uint256 indexed configuration, uint256 indexed projectId, uint256 indexed basedOn);\\n\\n function latestConfigurationOf(uint256 _projectId) external view returns (uint256);\\n\\n function get(uint256 _projectId, uint256 _configuration)\\n external\\n view\\n returns (JBFundingCycle memory);\\n\\n function latestConfiguredOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBBallotState ballotState);\\n\\n function queuedOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentBallotStateOf(uint256 _projectId) external view returns (JBBallotState);\\n\\n function configureFor(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n uint256 _metadata,\\n uint256 _mustStartAtOrAfter\\n ) external returns (JBFundingCycle memory fundingCycle);\\n}\\n\",\"keccak256\":\"0xaead823851433be0c2ddc8f8086813e6cd647de3a1bc0f7570a5d6b38c378b5a\",\"license\":\"MIT\"},\"contracts/interfaces/IJBMigratable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBMigratable {\\n function prepForMigrationOf(uint256 _projectId, address _from) external;\\n}\\n\",\"keccak256\":\"0xc81053e4b4754fc510aa04fecd3ab1460f01e3e27761e7a8c94f631a978ae127\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPayDelegate.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBDidPayData.sol';\\n\\n/**\\n @title\\n Pay delegate\\n\\n @notice\\n Delegate called after JBTerminal.pay(..) logic completion (if passed by the funding cycle datasource)\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n*/\\ninterface IJBPayDelegate is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.pay(..), after the execution of its logic\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control\\n \\n @param _data the data passed by the terminal, as a JBDidPayData struct:\\n address payer;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n JBTokenAmount amount;\\n JBTokenAmount forwardedAmount;\\n uint256 projectTokenCount;\\n address beneficiary;\\n bool preferClaimedTokens;\\n string memo;\\n bytes metadata;\\n */\\n function didPay(JBDidPayData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0xa797de18b69eceba117e1f0b3810cf3cc2d2791417d580a5bdc510d1b868ab26\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\n\\ninterface IJBPaymentTerminal is IERC165 {\\n function acceptsToken(address _token, uint256 _projectId) external view returns (bool);\\n\\n function currencyForToken(address _token) external view returns (uint256);\\n\\n function decimalsForToken(address _token) external view returns (uint256);\\n\\n // Return value must be a fixed point number with 18 decimals.\\n function currentEthOverflowOf(uint256 _projectId) external view returns (uint256);\\n\\n function pay(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable returns (uint256 beneficiaryTokenCount);\\n\\n function addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable;\\n}\\n\",\"keccak256\":\"0xb7826f5ed609359ce322c09e83236c47ba385df1c3cad3607e56fd0a2e00eee2\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPriceFeed.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBPriceFeed {\\n function currentPrice(uint256 _targetDecimals) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x57c71282fec1b34b00cf991ffed2e36031c393e35bfa7ca5d723eb6572fb7122\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPrices.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBPriceFeed.sol';\\n\\ninterface IJBPrices {\\n event AddFeed(uint256 indexed currency, uint256 indexed base, IJBPriceFeed feed);\\n\\n function feedFor(uint256 _currency, uint256 _base) external view returns (IJBPriceFeed);\\n\\n function priceFor(\\n uint256 _currency,\\n uint256 _base,\\n uint256 _decimals\\n ) external view returns (uint256);\\n\\n function addFeedFor(\\n uint256 _currency,\\n uint256 _base,\\n IJBPriceFeed _priceFeed\\n ) external;\\n}\\n\",\"keccak256\":\"0x82a175b1f4b95b506c98406576cd59cbe04615e3df24f9cf3587b61b8ee323b1\",\"license\":\"MIT\"},\"contracts/interfaces/IJBProjects.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBTokenUriResolver.sol';\\n\\ninterface IJBProjects is IERC721 {\\n event Create(\\n uint256 indexed projectId,\\n address indexed owner,\\n JBProjectMetadata metadata,\\n address caller\\n );\\n\\n event SetMetadata(uint256 indexed projectId, JBProjectMetadata metadata, address caller);\\n\\n event SetTokenUriResolver(IJBTokenUriResolver indexed resolver, address caller);\\n\\n function count() external view returns (uint256);\\n\\n function metadataContentOf(uint256 _projectId, uint256 _domain)\\n external\\n view\\n returns (string memory);\\n\\n function tokenUriResolver() external view returns (IJBTokenUriResolver);\\n\\n function createFor(address _owner, JBProjectMetadata calldata _metadata)\\n external\\n returns (uint256 projectId);\\n\\n function setMetadataOf(uint256 _projectId, JBProjectMetadata calldata _metadata) external;\\n\\n function setTokenUriResolver(IJBTokenUriResolver _newResolver) external;\\n}\\n\",\"keccak256\":\"0x7cfc021d0bd7e73b1ba8f4845d7d35e3419d6a14d3d25ca3a8010e7f91062fe4\",\"license\":\"MIT\"},\"contracts/interfaces/IJBRedemptionDelegate.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBDidRedeemData.sol';\\n\\n/**\\n @title\\n Redemption delegate\\n\\n @notice\\n Delegate called after JBTerminal.redeemTokensOf(..) logic completion (if passed by the funding cycle datasource)\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n*/\\ninterface IJBRedemptionDelegate is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.redeemTokensOf(..), after the execution of its logic\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control\\n \\n @param _data the data passed by the terminal, as a JBDidRedeemData struct:\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 projectTokenCount;\\n JBTokenAmount reclaimedAmount;\\n JBTokenAmount forwardedAmount;\\n address payable beneficiary;\\n string memo;\\n bytes metadata;\\n */\\n function didRedeem(JBDidRedeemData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0x172d2c0be65e72e54f71ae521907067f0fa30e8ca05c4f88826903208aa437e2\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSingleTokenPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBPaymentTerminal.sol';\\n\\ninterface IJBSingleTokenPaymentTerminal is IJBPaymentTerminal {\\n function token() external view returns (address);\\n\\n function currency() external view returns (uint256);\\n\\n function decimals() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xf6e78323caa9af7bbf024f44b2032a83fed0394e0b3a242a6346e73c85b2e46f\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSingleTokenPaymentTerminalStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBPayDelegateAllocation.sol';\\nimport './../structs/JBRedemptionDelegateAllocation.sol';\\nimport './../structs/JBTokenAmount.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBPrices.sol';\\nimport './IJBSingleTokenPaymentTerminal.sol';\\n\\ninterface IJBSingleTokenPaymentTerminalStore {\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function prices() external view returns (IJBPrices);\\n\\n function balanceOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\\n external\\n view\\n returns (uint256);\\n\\n function usedDistributionLimitOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _fundingCycleNumber\\n ) external view returns (uint256);\\n\\n function usedOverflowAllowanceOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _fundingCycleConfiguration\\n ) external view returns (uint256);\\n\\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\\n external\\n view\\n returns (uint256);\\n\\n function currentTotalOverflowOf(\\n uint256 _projectId,\\n uint256 _decimals,\\n uint256 _currency\\n ) external view returns (uint256);\\n\\n function currentReclaimableOverflowOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n bool _useTotalOverflow\\n ) external view returns (uint256);\\n\\n function currentReclaimableOverflowOf(\\n uint256 _projectId,\\n uint256 _tokenCount,\\n uint256 _totalSupply,\\n uint256 _overflow\\n ) external view returns (uint256);\\n\\n function recordPaymentFrom(\\n address _payer,\\n JBTokenAmount memory _amount,\\n uint256 _projectId,\\n uint256 _baseWeightCurrency,\\n address _beneficiary,\\n string calldata _memo,\\n bytes calldata _metadata\\n )\\n external\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 tokenCount,\\n JBPayDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n );\\n\\n function recordRedemptionFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n string calldata _memo,\\n bytes calldata _metadata\\n )\\n external\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 reclaimAmount,\\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n );\\n\\n function recordDistributionFor(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n ) external returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount);\\n\\n function recordUsedAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n ) external returns (JBFundingCycle memory fundingCycle, uint256 withdrawnAmount);\\n\\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external;\\n\\n function recordMigration(uint256 _projectId) external returns (uint256 balance);\\n}\\n\",\"keccak256\":\"0xd78929c9371fd7895b829ef5e4ad4b3786523c3580ac3f6f5f25d2b5941c0dd3\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSplitAllocator.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport '../structs/JBSplitAllocationData.sol';\\n\\n/**\\n @title\\n Split allocator\\n\\n @notice\\n Provide a way to process a single split with extra logic\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n\\n @dev\\n The contract address should be set as an allocator in the adequate split\\n*/\\ninterface IJBSplitAllocator is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.distributePayoutOf(..), during the processing of the split including it\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control. The token and/or eth are optimistically transfered\\n to the allocator for its logic.\\n \\n @param _data the data passed by the terminal, as a JBSplitAllocationData struct:\\n address token;\\n uint256 amount;\\n uint256 decimals;\\n uint256 projectId;\\n uint256 group;\\n JBSplit split;\\n */\\n function allocate(JBSplitAllocationData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0x5efb6f51fc161f42ff58989386ad99028e4039a0ba897d66f358c3dfcf686105\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSplitsStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBGroupedSplits.sol';\\nimport './../structs/JBSplit.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBProjects.sol';\\n\\ninterface IJBSplitsStore {\\n event SetSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n address caller\\n );\\n\\n function projects() external view returns (IJBProjects);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function splitsOf(\\n uint256 _projectId,\\n uint256 _domain,\\n uint256 _group\\n ) external view returns (JBSplit[] memory);\\n\\n function set(\\n uint256 _projectId,\\n uint256 _domain,\\n JBGroupedSplits[] memory _groupedSplits\\n ) external;\\n}\\n\",\"keccak256\":\"0x66dab3dd394e318b850401ca92c2963b906cc0ad5562fa5d4f6f850175d1c77a\",\"license\":\"MIT\"},\"contracts/interfaces/IJBToken.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBToken {\\n function projectId() external view returns (uint256);\\n\\n function decimals() external view returns (uint8);\\n\\n function totalSupply(uint256 _projectId) external view returns (uint256);\\n\\n function balanceOf(address _account, uint256 _projectId) external view returns (uint256);\\n\\n function mint(\\n uint256 _projectId,\\n address _account,\\n uint256 _amount\\n ) external;\\n\\n function burn(\\n uint256 _projectId,\\n address _account,\\n uint256 _amount\\n ) external;\\n\\n function approve(\\n uint256,\\n address _spender,\\n uint256 _amount\\n ) external;\\n\\n function transfer(\\n uint256 _projectId,\\n address _to,\\n uint256 _amount\\n ) external;\\n\\n function transferFrom(\\n uint256 _projectId,\\n address _from,\\n address _to,\\n uint256 _amount\\n ) external;\\n}\\n\",\"keccak256\":\"0xe8969210417736c85d71101bf1c0bd8ebbf9d1e62a93e758148bd5709a6c7097\",\"license\":\"MIT\"},\"contracts/interfaces/IJBTokenStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBProjects.sol';\\nimport './IJBToken.sol';\\n\\ninterface IJBTokenStore {\\n event Issue(\\n uint256 indexed projectId,\\n IJBToken indexed token,\\n string name,\\n string symbol,\\n address caller\\n );\\n\\n event Mint(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 amount,\\n bool tokensWereClaimed,\\n bool preferClaimedTokens,\\n address caller\\n );\\n\\n event Burn(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 amount,\\n uint256 initialUnclaimedBalance,\\n uint256 initialClaimedBalance,\\n bool preferClaimedTokens,\\n address caller\\n );\\n\\n event Claim(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 initialUnclaimedBalance,\\n uint256 amount,\\n address caller\\n );\\n\\n event Set(uint256 indexed projectId, IJBToken indexed newToken, address caller);\\n\\n event Transfer(\\n address indexed holder,\\n uint256 indexed projectId,\\n address indexed recipient,\\n uint256 amount,\\n address caller\\n );\\n\\n function tokenOf(uint256 _projectId) external view returns (IJBToken);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function unclaimedBalanceOf(address _holder, uint256 _projectId) external view returns (uint256);\\n\\n function unclaimedTotalSupplyOf(uint256 _projectId) external view returns (uint256);\\n\\n function totalSupplyOf(uint256 _projectId) external view returns (uint256);\\n\\n function balanceOf(address _holder, uint256 _projectId) external view returns (uint256 _result);\\n\\n function issueFor(\\n uint256 _projectId,\\n string calldata _name,\\n string calldata _symbol\\n ) external returns (IJBToken token);\\n\\n function setFor(uint256 _projectId, IJBToken _token) external;\\n\\n function burnFrom(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function mintFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function claimFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount\\n ) external;\\n\\n function transferFrom(\\n address _holder,\\n uint256 _projectId,\\n address _recipient,\\n uint256 _amount\\n ) external;\\n}\\n\",\"keccak256\":\"0x98459e3af050d41dfeffdc97f1c93330207ba450f8ff3613224b49a89eeca9c6\",\"license\":\"MIT\"},\"contracts/interfaces/IJBTokenUriResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBTokenUriResolver {\\n function getUri(uint256 _projectId) external view returns (string memory tokenUri);\\n}\\n\",\"keccak256\":\"0xd267fd8ca7c21c2c71794acdb9a98314c33a35fc559e0bf0897a6686d196d174\",\"license\":\"MIT\"},\"contracts/libraries/JBConstants.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/**\\n @notice\\n Global constants used across Juicebox contracts.\\n*/\\nlibrary JBConstants {\\n uint256 public constant MAX_RESERVED_RATE = 10_000;\\n uint256 public constant MAX_REDEMPTION_RATE = 10_000;\\n uint256 public constant MAX_DISCOUNT_RATE = 1_000_000_000;\\n uint256 public constant SPLITS_TOTAL_PERCENT = 1_000_000_000;\\n uint256 public constant MAX_FEE = 1_000_000_000;\\n uint256 public constant MAX_FEE_DISCOUNT = 1_000_000_000;\\n}\\n\",\"keccak256\":\"0x34362846a1cd428a8bdedf4ab6857e11402f345cb87b994b2e7fb6d2474b808d\",\"license\":\"MIT\"},\"contracts/libraries/JBCurrencies.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBCurrencies {\\n uint256 public constant ETH = 1;\\n uint256 public constant USD = 2;\\n}\\n\",\"keccak256\":\"0x7e417ff25c173608ee4fe6d9fc3dcd5e1458c78c889af12bac47b1189a436076\",\"license\":\"MIT\"},\"contracts/libraries/JBFixedPointNumber.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nlibrary JBFixedPointNumber {\\n function adjustDecimals(\\n uint256 _value,\\n uint256 _decimals,\\n uint256 _targetDecimals\\n ) internal pure returns (uint256) {\\n // If decimals need adjusting, multiply or divide the price by the decimal adjuster to get the normalized result.\\n if (_targetDecimals == _decimals) return _value;\\n else if (_targetDecimals > _decimals) return _value * 10**(_targetDecimals - _decimals);\\n else return _value / 10**(_decimals - _targetDecimals);\\n }\\n}\\n\",\"keccak256\":\"0x18efac48269f3a3bd7e9a1c770776f950e0afa86769e6f8b128002c3b8c6742c\",\"license\":\"MIT\"},\"contracts/libraries/JBFundingCycleMetadataResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBFundingCycleMetadata.sol';\\nimport './../structs/JBGlobalFundingCycleMetadata.sol';\\nimport './JBConstants.sol';\\nimport './JBGlobalFundingCycleMetadataResolver.sol';\\n\\nlibrary JBFundingCycleMetadataResolver {\\n function global(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (JBGlobalFundingCycleMetadata memory)\\n {\\n return JBGlobalFundingCycleMetadataResolver.expandMetadata(uint8(_fundingCycle.metadata >> 8));\\n }\\n\\n function reservedRate(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n return uint256(uint16(_fundingCycle.metadata >> 24));\\n }\\n\\n function redemptionRate(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n // Redemption rate is a number 0-10000. It's inverse was stored so the most common case of 100% results in no storage needs.\\n return JBConstants.MAX_REDEMPTION_RATE - uint256(uint16(_fundingCycle.metadata >> 40));\\n }\\n\\n function ballotRedemptionRate(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (uint256)\\n {\\n // Redemption rate is a number 0-10000. It's inverse was stored so the most common case of 100% results in no storage needs.\\n return JBConstants.MAX_REDEMPTION_RATE - uint256(uint16(_fundingCycle.metadata >> 56));\\n }\\n\\n function payPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 72) & 1) == 1;\\n }\\n\\n function distributionsPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 73) & 1) == 1;\\n }\\n\\n function redeemPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 74) & 1) == 1;\\n }\\n\\n function burnPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 75) & 1) == 1;\\n }\\n\\n function mintingAllowed(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 76) & 1) == 1;\\n }\\n\\n function terminalMigrationAllowed(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 77) & 1) == 1;\\n }\\n\\n function controllerMigrationAllowed(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 78) & 1) == 1;\\n }\\n\\n function shouldHoldFees(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 79) & 1) == 1;\\n }\\n\\n function preferClaimedTokenOverride(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 80) & 1) == 1;\\n }\\n\\n function useTotalOverflowForRedemptions(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 81) & 1) == 1;\\n }\\n\\n function useDataSourceForPay(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return (_fundingCycle.metadata >> 82) & 1 == 1;\\n }\\n\\n function useDataSourceForRedeem(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return (_fundingCycle.metadata >> 83) & 1 == 1;\\n }\\n\\n function dataSource(JBFundingCycle memory _fundingCycle) internal pure returns (address) {\\n return address(uint160(_fundingCycle.metadata >> 84));\\n }\\n\\n function metadata(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n return uint256(uint8(_fundingCycle.metadata >> 244));\\n }\\n\\n /**\\n @notice\\n Pack the funding cycle metadata.\\n\\n @param _metadata The metadata to validate and pack.\\n\\n @return packed The packed uint256 of all metadata params. The first 8 bits specify the version.\\n */\\n function packFundingCycleMetadata(JBFundingCycleMetadata memory _metadata)\\n internal\\n pure\\n returns (uint256 packed)\\n {\\n // version 1 in the bits 0-7 (8 bits).\\n packed = 1;\\n // global metadta in bits 8-23 (16 bits).\\n packed |=\\n JBGlobalFundingCycleMetadataResolver.packFundingCycleGlobalMetadata(_metadata.global) <<\\n 8;\\n // reserved rate in bits 24-39 (16 bits).\\n packed |= _metadata.reservedRate << 24;\\n // redemption rate in bits 40-55 (16 bits).\\n // redemption rate is a number 0-10000. Store the reverse so the most common case of 100% results in no storage needs.\\n packed |= (JBConstants.MAX_REDEMPTION_RATE - _metadata.redemptionRate) << 40;\\n // ballot redemption rate rate in bits 56-71 (16 bits).\\n // ballot redemption rate is a number 0-10000. Store the reverse so the most common case of 100% results in no storage needs.\\n packed |= (JBConstants.MAX_REDEMPTION_RATE - _metadata.ballotRedemptionRate) << 56;\\n // pause pay in bit 72.\\n if (_metadata.pausePay) packed |= 1 << 72;\\n // pause tap in bit 73.\\n if (_metadata.pauseDistributions) packed |= 1 << 73;\\n // pause redeem in bit 74.\\n if (_metadata.pauseRedeem) packed |= 1 << 74;\\n // pause burn in bit 75.\\n if (_metadata.pauseBurn) packed |= 1 << 75;\\n // allow minting in bit 76.\\n if (_metadata.allowMinting) packed |= 1 << 76;\\n // allow terminal migration in bit 77.\\n if (_metadata.allowTerminalMigration) packed |= 1 << 77;\\n // allow controller migration in bit 78.\\n if (_metadata.allowControllerMigration) packed |= 1 << 78;\\n // hold fees in bit 79.\\n if (_metadata.holdFees) packed |= 1 << 79;\\n // prefer claimed token override in bit 80.\\n if (_metadata.preferClaimedTokenOverride) packed |= 1 << 80;\\n // useTotalOverflowForRedemptions in bit 81.\\n if (_metadata.useTotalOverflowForRedemptions) packed |= 1 << 81;\\n // use pay data source in bit 82.\\n if (_metadata.useDataSourceForPay) packed |= 1 << 82;\\n // use redeem data source in bit 83.\\n if (_metadata.useDataSourceForRedeem) packed |= 1 << 83;\\n // data source address in bits 84-243.\\n packed |= uint256(uint160(address(_metadata.dataSource))) << 84;\\n // metadata in bits 244-252 (8 bits).\\n packed |= _metadata.metadata << 244;\\n }\\n\\n /**\\n @notice\\n Expand the funding cycle metadata.\\n\\n @param _fundingCycle The funding cycle having its metadata expanded.\\n\\n @return metadata The metadata object.\\n */\\n function expandMetadata(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (JBFundingCycleMetadata memory)\\n {\\n return\\n JBFundingCycleMetadata(\\n global(_fundingCycle),\\n reservedRate(_fundingCycle),\\n redemptionRate(_fundingCycle),\\n ballotRedemptionRate(_fundingCycle),\\n payPaused(_fundingCycle),\\n distributionsPaused(_fundingCycle),\\n redeemPaused(_fundingCycle),\\n burnPaused(_fundingCycle),\\n mintingAllowed(_fundingCycle),\\n terminalMigrationAllowed(_fundingCycle),\\n controllerMigrationAllowed(_fundingCycle),\\n shouldHoldFees(_fundingCycle),\\n preferClaimedTokenOverride(_fundingCycle),\\n useTotalOverflowForRedemptions(_fundingCycle),\\n useDataSourceForPay(_fundingCycle),\\n useDataSourceForRedeem(_fundingCycle),\\n dataSource(_fundingCycle),\\n metadata(_fundingCycle)\\n );\\n }\\n}\\n\",\"keccak256\":\"0x3d045c38593102cfb6ac67f3ddf2232e1ff5518d6d021423ae2681387599fbd3\",\"license\":\"MIT\"},\"contracts/libraries/JBGlobalFundingCycleMetadataResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport './../structs/JBFundingCycleMetadata.sol';\\n\\nlibrary JBGlobalFundingCycleMetadataResolver {\\n function setTerminalsAllowed(uint8 _data) internal pure returns (bool) {\\n return (_data & 1) == 1;\\n }\\n\\n function setControllerAllowed(uint8 _data) internal pure returns (bool) {\\n return ((_data >> 1) & 1) == 1;\\n }\\n\\n function transfersPaused(uint8 _data) internal pure returns (bool) {\\n return ((_data >> 2) & 1) == 1;\\n }\\n\\n /**\\n @notice\\n Pack the global funding cycle metadata.\\n\\n @param _metadata The metadata to validate and pack.\\n\\n @return packed The packed uint256 of all global metadata params. The first 8 bits specify the version.\\n */\\n function packFundingCycleGlobalMetadata(JBGlobalFundingCycleMetadata memory _metadata)\\n internal\\n pure\\n returns (uint256 packed)\\n {\\n // allow set terminals in bit 0.\\n if (_metadata.allowSetTerminals) packed |= 1;\\n // allow set controller in bit 1.\\n if (_metadata.allowSetController) packed |= 1 << 1;\\n // pause transfers in bit 2.\\n if (_metadata.pauseTransfers) packed |= 1 << 2;\\n }\\n\\n /**\\n @notice\\n Expand the global funding cycle metadata.\\n\\n @param _packedMetadata The packed metadata to expand.\\n\\n @return metadata The global metadata object.\\n */\\n function expandMetadata(uint8 _packedMetadata)\\n internal\\n pure\\n returns (JBGlobalFundingCycleMetadata memory metadata)\\n {\\n return\\n JBGlobalFundingCycleMetadata(\\n setTerminalsAllowed(_packedMetadata),\\n setControllerAllowed(_packedMetadata),\\n transfersPaused(_packedMetadata)\\n );\\n }\\n}\\n\",\"keccak256\":\"0x0d998f938026edeb755987a79421267cf860801161b5f171206a200b60f1061f\",\"license\":\"MIT\"},\"contracts/structs/JBDidPayData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member payer The address from which the payment originated.\\n @member projectId The ID of the project for which the payment was made.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the payment is being made.\\n @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.\\n @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.\\n @member projectTokenCount The number of project tokens minted for the beneficiary.\\n @member beneficiary The address to which the tokens were minted.\\n @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.\\n @member memo The memo that is being emitted alongside the payment.\\n @member metadata Extra data to send to the delegate.\\n*/\\nstruct JBDidPayData {\\n address payer;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n JBTokenAmount amount;\\n JBTokenAmount forwardedAmount;\\n uint256 projectTokenCount;\\n address beneficiary;\\n bool preferClaimedTokens;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0xf3c664309b37790f16047ae97b0459889ae0242dfcde7fc8902c8d10c7f8e6b6\",\"license\":\"MIT\"},\"contracts/structs/JBDidRedeemData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member holder The holder of the tokens being redeemed.\\n @member projectId The ID of the project with which the redeemed tokens are associated.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the redemption is being made.\\n @member projectTokenCount The number of project tokens being redeemed.\\n @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.\\n @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.\\n @member beneficiary The address to which the reclaimed amount will be sent.\\n @member memo The memo that is being emitted alongside the redemption.\\n @member metadata Extra data to send to the delegate.\\n*/\\nstruct JBDidRedeemData {\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 projectTokenCount;\\n JBTokenAmount reclaimedAmount;\\n JBTokenAmount forwardedAmount;\\n address payable beneficiary;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0xe2c401f39723a7ce915b8bef328744c66daaf57460843964b941456c2258a412\",\"license\":\"MIT\"},\"contracts/structs/JBFundAccessConstraints.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBPaymentTerminal.sol';\\n\\n/** \\n @member terminal The terminal within which the distribution limit and the overflow allowance applies.\\n @member token The token for which the fund access constraints apply.\\n @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.\\n @member distributionLimitCurrency The currency of the distribution limit.\\n @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.\\n @member overflowAllowanceCurrency The currency of the overflow allowance.\\n*/\\nstruct JBFundAccessConstraints {\\n IJBPaymentTerminal terminal;\\n address token;\\n uint256 distributionLimit;\\n uint256 distributionLimitCurrency;\\n uint256 overflowAllowance;\\n uint256 overflowAllowanceCurrency;\\n}\\n\",\"keccak256\":\"0x85ebaa57b788cbdedc7a3d0eec4892eda5d79db7c1a6103797f10d0d989775b2\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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.\\n @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.\\n @member basedOn The `configuration` of the funding cycle that was active when this cycle was created.\\n @member start The timestamp marking the moment from which the funding cycle is considered active. It is a unix timestamp measured in seconds.\\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n @member metadata Extra data that can be associated with a funding cycle.\\n*/\\nstruct JBFundingCycle {\\n uint256 number;\\n uint256 configuration;\\n uint256 basedOn;\\n uint256 start;\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n uint256 metadata;\\n}\\n\",\"keccak256\":\"0xcdd3ac9b6fa67e62ada88d09b73bc35ade1cd77d43db712289266a788928b4c2\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycleData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n*/\\nstruct JBFundingCycleData {\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n}\\n\",\"keccak256\":\"0x2aa6368bf4dfc5797e8b02a978293de0c777fae2658de2c825a103587240f3b0\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycleMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBGlobalFundingCycleMetadata.sol';\\n\\n/** \\n @member global Data used globally in non-migratable ecosystem contracts.\\n @member reservedRate The reserved rate of the funding cycle. This number is a percentage calculated out of `JBConstants.MAX_RESERVED_RATE`.\\n @member redemptionRate The redemption rate of the funding cycle. This number is a percentage calculated out of `JBConstants.MAX_REDEMPTION_RATE`.\\n @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`.\\n @member pausePay A flag indicating if the pay functionality should be paused during the funding cycle.\\n @member pauseDistributions A flag indicating if the distribute functionality should be paused during the funding cycle.\\n @member pauseRedeem A flag indicating if the redeem functionality should be paused during the funding cycle.\\n @member pauseBurn A flag indicating if the burn functionality should be paused during the funding cycle.\\n @member allowMinting A flag indicating if minting tokens should be allowed during this funding cycle.\\n @member allowTerminalMigration A flag indicating if migrating terminals should be allowed during this funding cycle.\\n @member allowControllerMigration A flag indicating if migrating controllers should be allowed during this funding cycle.\\n @member holdFees A flag indicating if fees should be held during this funding cycle.\\n @member preferClaimedTokenOverride A flag indicating if claimed tokens should always be prefered to unclaimed tokens when minting.\\n @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.\\n @member useDataSourceForPay A flag indicating if the data source should be used for pay transactions during this funding cycle.\\n @member useDataSourceForRedeem A flag indicating if the data source should be used for redeem transactions during this funding cycle.\\n @member dataSource The data source to use during this funding cycle.\\n @member metadata Metadata of the metadata, up to uint8 in size.\\n*/\\nstruct JBFundingCycleMetadata {\\n JBGlobalFundingCycleMetadata global;\\n uint256 reservedRate;\\n uint256 redemptionRate;\\n uint256 ballotRedemptionRate;\\n bool pausePay;\\n bool pauseDistributions;\\n bool pauseRedeem;\\n bool pauseBurn;\\n bool allowMinting;\\n bool allowTerminalMigration;\\n bool allowControllerMigration;\\n bool holdFees;\\n bool preferClaimedTokenOverride;\\n bool useTotalOverflowForRedemptions;\\n bool useDataSourceForPay;\\n bool useDataSourceForRedeem;\\n address dataSource;\\n uint256 metadata;\\n}\\n\",\"keccak256\":\"0x783604440cac8d176332eab28166f188ee5c230378c08cfc95fea4f7187dc77d\",\"license\":\"MIT\"},\"contracts/structs/JBGlobalFundingCycleMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member allowSetTerminals A flag indicating if setting terminals should be allowed during this funding cycle.\\n @member allowSetController A flag indicating if setting a new controller should be allowed during this funding cycle.\\n @member pauseTransfers A flag indicating if the project token transfer functionality should be paused during the funding cycle.\\n*/\\nstruct JBGlobalFundingCycleMetadata {\\n bool allowSetTerminals;\\n bool allowSetController;\\n bool pauseTransfers;\\n}\\n\",\"keccak256\":\"0x05d85530305fec6d6eca54cdbc2cd9110cbda0146598032b0203aa4b622944ff\",\"license\":\"MIT\"},\"contracts/structs/JBGroupedSplits.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBSplit.sol';\\n\\n/** \\n @member group The group indentifier.\\n @member splits The splits to associate with the group.\\n*/\\nstruct JBGroupedSplits {\\n uint256 group;\\n JBSplit[] splits;\\n}\\n\",\"keccak256\":\"0x80be1b220da4ac04851ea540ebb94c1ec2b0442ec5bd1e88fdf78a56becd8b5a\",\"license\":\"MIT\"},\"contracts/structs/JBPayDelegateAllocation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '../interfaces/IJBPayDelegate.sol';\\n\\n/** \\n @member delegate A delegate contract to use for subsequent calls.\\n @member amount The amount to send to the delegate.\\n*/\\nstruct JBPayDelegateAllocation {\\n IJBPayDelegate delegate;\\n uint256 amount;\\n}\\n\",\"keccak256\":\"0xb4e558dc62231d89e9b48998012577d22c3e52b58e23401f22d9096827f6ea0c\",\"license\":\"MIT\"},\"contracts/structs/JBPayParamsData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBPaymentTerminal.sol';\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member terminal The terminal that is facilitating the payment.\\n @member payer The address from which the payment originated.\\n @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.\\n @member projectId The ID of the project being paid.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the payment is being made.\\n @member beneficiary The specified address that should be the beneficiary of anything that results from the payment.\\n @member weight The weight of the funding cycle during which the payment is being made.\\n @member reservedRate The reserved rate of the funding cycle during which the payment is being made.\\n @member memo The memo that was sent alongside the payment.\\n @member metadata Extra data provided by the payer.\\n*/\\nstruct JBPayParamsData {\\n IJBPaymentTerminal terminal;\\n address payer;\\n JBTokenAmount amount;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n address beneficiary;\\n uint256 weight;\\n uint256 reservedRate;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0x05007b26feb5d9a026b883c6d734a341b5a49ef7b8215fb40507882e2c14e24d\",\"license\":\"MIT\"},\"contracts/structs/JBProjectMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member content The metadata content.\\n @member domain The domain within which the metadata applies.\\n*/\\nstruct JBProjectMetadata {\\n string content;\\n uint256 domain;\\n}\\n\",\"keccak256\":\"0x90ad7b1014c0a9f945fe7a2efde9d5de41e40574fa27969070b1d2ff52033ea0\",\"license\":\"MIT\"},\"contracts/structs/JBRedeemParamsData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBPaymentTerminal.sol';\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member terminal The terminal that is facilitating the redemption.\\n @member holder The holder of the tokens being redeemed.\\n @member projectId The ID of the project whos tokens are being redeemed.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the redemption is being made.\\n @member tokenCount The proposed number of tokens being redeemed, as a fixed point number with 18 decimals.\\n @member totalSupply The total supply of tokens used in the calculation, as a fixed point number with 18 decimals.\\n @member overflow The amount of overflow used in the reclaim amount calculation.\\n @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.\\n @member useTotalOverflow If overflow across all of a project's terminals is being used when making redemptions.\\n @member redemptionRate The redemption rate of the funding cycle during which the redemption is being made.\\n @member memo The proposed memo that is being emitted alongside the redemption.\\n @member metadata Extra data provided by the redeemer.\\n*/\\nstruct JBRedeemParamsData {\\n IJBPaymentTerminal terminal;\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 tokenCount;\\n uint256 totalSupply;\\n uint256 overflow;\\n JBTokenAmount reclaimAmount;\\n bool useTotalOverflow;\\n uint256 redemptionRate;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0x5065a824ebb34952f016c6dfa47e8a7ac28427b719470e74a41022c11ace7788\",\"license\":\"MIT\"},\"contracts/structs/JBRedemptionDelegateAllocation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '../interfaces/IJBRedemptionDelegate.sol';\\n\\n/** \\n @member delegate A delegate contract to use for subsequent calls.\\n @member amount The amount to send to the delegate.\\n*/\\nstruct JBRedemptionDelegateAllocation {\\n IJBRedemptionDelegate delegate;\\n uint256 amount;\\n}\\n\",\"keccak256\":\"0x10c29d33dd0d875a0d4692a2b9a9355c2ebf433cc06a9a60253d4366b60d4d31\",\"license\":\"MIT\"},\"contracts/structs/JBSplit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBSplitAllocator.sol';\\n\\n/** \\n @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.\\n @member preferAddToBalance A flag indicating if a distribution to a project should prefer triggering it's addToBalance function instead of its pay function.\\n @member percent The percent of the whole group that this split occupies. This number is out of `JBConstants.SPLITS_TOTAL_PERCENT`.\\n @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.\\n @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.\\n @member lockedUntil Specifies if the split should be unchangeable until the specified time, with the exception of extending the locked period.\\n @member allocator If an allocator is specified, funds will be sent to the allocator contract along with all properties of this split.\\n*/\\nstruct JBSplit {\\n bool preferClaimed;\\n bool preferAddToBalance;\\n uint256 percent;\\n uint256 projectId;\\n address payable beneficiary;\\n uint256 lockedUntil;\\n IJBSplitAllocator allocator;\\n}\\n\",\"keccak256\":\"0xc80a16606da8abf76d0f73abc38aee041e24f29342c1939018f70c286e89f105\",\"license\":\"MIT\"},\"contracts/structs/JBSplitAllocationData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBSplit.sol';\\n\\n/** \\n @member token The token being sent to the split allocator.\\n @member amount The amount being sent to the split allocator, as a fixed point number.\\n @member decimals The number of decimals in the amount.\\n @member projectId The project to which the split belongs.\\n @member group The group to which the split belongs.\\n @member split The split that caused the allocation.\\n*/\\nstruct JBSplitAllocationData {\\n address token;\\n uint256 amount;\\n uint256 decimals;\\n uint256 projectId;\\n uint256 group;\\n JBSplit split;\\n}\\n\",\"keccak256\":\"0x39f5c41bd31d36774744698ac94484b6cab62d7038df2f29d947668959782e63\",\"license\":\"MIT\"},\"contracts/structs/JBTokenAmount.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/* \\n @member token The token the payment was made in.\\n @member value The amount of tokens that was paid, as a fixed point number.\\n @member decimals The number of decimals included in the value fixed point number.\\n @member currency The expected currency of the value.\\n**/\\nstruct JBTokenAmount {\\n address token;\\n uint256 value;\\n uint256 decimals;\\n uint256 currency;\\n}\\n\",\"keccak256\":\"0x4a778e779ba257ba5638c5469e07a4d21b55a3128d56db5a0fdfacb1f3301c51\",\"license\":\"MIT\"},\"prb-math/contracts/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivFixedPointOverflow(uint256 prod1);\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivOverflow(uint256 prod1, uint256 denominator);\\n\\n/// @notice Emitted when one of the inputs is type(int256).min.\\nerror PRBMath__MulDivSignedInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows int256.\\nerror PRBMath__MulDivSignedOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is MIN_SD59x18.\\nerror PRBMathSD59x18__AbsInputTooSmall();\\n\\n/// @notice Emitted when ceiling a number overflows SD59x18.\\nerror PRBMathSD59x18__CeilOverflow(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__DivInputTooSmall();\\n\\n/// @notice Emitted when one of the intermediary unsigned results overflows SD59x18.\\nerror PRBMathSD59x18__DivOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathSD59x18__ExpInputTooBig(int256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathSD59x18__Exp2InputTooBig(int256 x);\\n\\n/// @notice Emitted when flooring a number underflows SD59x18.\\nerror PRBMathSD59x18__FloorUnderflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format overflows SD59x18.\\nerror PRBMathSD59x18__FromIntOverflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format underflows SD59x18.\\nerror PRBMathSD59x18__FromIntUnderflow(int256 x);\\n\\n/// @notice Emitted when the product of the inputs is negative.\\nerror PRBMathSD59x18__GmNegativeProduct(int256 x, int256 y);\\n\\n/// @notice Emitted when multiplying the inputs overflows SD59x18.\\nerror PRBMathSD59x18__GmOverflow(int256 x, int256 y);\\n\\n/// @notice Emitted when the input is less than or equal to zero.\\nerror PRBMathSD59x18__LogInputTooSmall(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__MulInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__MulOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__PowuOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is negative.\\nerror PRBMathSD59x18__SqrtNegativeInput(int256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows SD59x18.\\nerror PRBMathSD59x18__SqrtOverflow(int256 x);\\n\\n/// @notice Emitted when addition overflows UD60x18.\\nerror PRBMathUD60x18__AddOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when ceiling a number overflows UD60x18.\\nerror PRBMathUD60x18__CeilOverflow(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathUD60x18__ExpInputTooBig(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathUD60x18__Exp2InputTooBig(uint256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format format overflows UD60x18.\\nerror PRBMathUD60x18__FromUintOverflow(uint256 x);\\n\\n/// @notice Emitted when multiplying the inputs overflows UD60x18.\\nerror PRBMathUD60x18__GmOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when the input is less than 1.\\nerror PRBMathUD60x18__LogInputTooSmall(uint256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows UD60x18.\\nerror PRBMathUD60x18__SqrtOverflow(uint256 x);\\n\\n/// @notice Emitted when subtraction underflows UD60x18.\\nerror PRBMathUD60x18__SubUnderflow(uint256 x, uint256 y);\\n\\n/// @dev Common mathematical functions used in both PRBMathSD59x18 and PRBMathUD60x18. Note that this shared library\\n/// does not always assume the signed 59.18-decimal fixed-point or the unsigned 60.18-decimal fixed-point\\n/// representation. When it does not, it is explicitly mentioned in the NatSpec documentation.\\nlibrary PRBMath {\\n /// STRUCTS ///\\n\\n struct SD59x18 {\\n int256 value;\\n }\\n\\n struct UD60x18 {\\n uint256 value;\\n }\\n\\n /// STORAGE ///\\n\\n /// @dev How many trailing decimals can be represented.\\n uint256 internal constant SCALE = 1e18;\\n\\n /// @dev Largest power of two divisor of SCALE.\\n uint256 internal constant SCALE_LPOTD = 262144;\\n\\n /// @dev SCALE inverted mod 2^256.\\n uint256 internal constant SCALE_INVERSE =\\n 78156646155174841979727994598816262306175212592076161876661_508869554232690281;\\n\\n /// FUNCTIONS ///\\n\\n /// @notice Calculates the binary exponent of x using the binary fraction method.\\n /// @dev Has to use 192.64-bit fixed-point numbers.\\n /// See https://ethereum.stackexchange.com/a/96594/24693.\\n /// @param x The exponent as an unsigned 192.64-bit fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp2(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n // Start from 0.5 in the 192.64-bit fixed-point format.\\n result = 0x800000000000000000000000000000000000000000000000;\\n\\n // Multiply the result by root(2, 2^-i) when the bit at position i is 1. None of the intermediary results overflows\\n // because the initial result is 2^191 and all magic factors are less than 2^65.\\n if (x & 0x8000000000000000 > 0) {\\n result = (result * 0x16A09E667F3BCC909) >> 64;\\n }\\n if (x & 0x4000000000000000 > 0) {\\n result = (result * 0x1306FE0A31B7152DF) >> 64;\\n }\\n if (x & 0x2000000000000000 > 0) {\\n result = (result * 0x1172B83C7D517ADCE) >> 64;\\n }\\n if (x & 0x1000000000000000 > 0) {\\n result = (result * 0x10B5586CF9890F62A) >> 64;\\n }\\n if (x & 0x800000000000000 > 0) {\\n result = (result * 0x1059B0D31585743AE) >> 64;\\n }\\n if (x & 0x400000000000000 > 0) {\\n result = (result * 0x102C9A3E778060EE7) >> 64;\\n }\\n if (x & 0x200000000000000 > 0) {\\n result = (result * 0x10163DA9FB33356D8) >> 64;\\n }\\n if (x & 0x100000000000000 > 0) {\\n result = (result * 0x100B1AFA5ABCBED61) >> 64;\\n }\\n if (x & 0x80000000000000 > 0) {\\n result = (result * 0x10058C86DA1C09EA2) >> 64;\\n }\\n if (x & 0x40000000000000 > 0) {\\n result = (result * 0x1002C605E2E8CEC50) >> 64;\\n }\\n if (x & 0x20000000000000 > 0) {\\n result = (result * 0x100162F3904051FA1) >> 64;\\n }\\n if (x & 0x10000000000000 > 0) {\\n result = (result * 0x1000B175EFFDC76BA) >> 64;\\n }\\n if (x & 0x8000000000000 > 0) {\\n result = (result * 0x100058BA01FB9F96D) >> 64;\\n }\\n if (x & 0x4000000000000 > 0) {\\n result = (result * 0x10002C5CC37DA9492) >> 64;\\n }\\n if (x & 0x2000000000000 > 0) {\\n result = (result * 0x1000162E525EE0547) >> 64;\\n }\\n if (x & 0x1000000000000 > 0) {\\n result = (result * 0x10000B17255775C04) >> 64;\\n }\\n if (x & 0x800000000000 > 0) {\\n result = (result * 0x1000058B91B5BC9AE) >> 64;\\n }\\n if (x & 0x400000000000 > 0) {\\n result = (result * 0x100002C5C89D5EC6D) >> 64;\\n }\\n if (x & 0x200000000000 > 0) {\\n result = (result * 0x10000162E43F4F831) >> 64;\\n }\\n if (x & 0x100000000000 > 0) {\\n result = (result * 0x100000B1721BCFC9A) >> 64;\\n }\\n if (x & 0x80000000000 > 0) {\\n result = (result * 0x10000058B90CF1E6E) >> 64;\\n }\\n if (x & 0x40000000000 > 0) {\\n result = (result * 0x1000002C5C863B73F) >> 64;\\n }\\n if (x & 0x20000000000 > 0) {\\n result = (result * 0x100000162E430E5A2) >> 64;\\n }\\n if (x & 0x10000000000 > 0) {\\n result = (result * 0x1000000B172183551) >> 64;\\n }\\n if (x & 0x8000000000 > 0) {\\n result = (result * 0x100000058B90C0B49) >> 64;\\n }\\n if (x & 0x4000000000 > 0) {\\n result = (result * 0x10000002C5C8601CC) >> 64;\\n }\\n if (x & 0x2000000000 > 0) {\\n result = (result * 0x1000000162E42FFF0) >> 64;\\n }\\n if (x & 0x1000000000 > 0) {\\n result = (result * 0x10000000B17217FBB) >> 64;\\n }\\n if (x & 0x800000000 > 0) {\\n result = (result * 0x1000000058B90BFCE) >> 64;\\n }\\n if (x & 0x400000000 > 0) {\\n result = (result * 0x100000002C5C85FE3) >> 64;\\n }\\n if (x & 0x200000000 > 0) {\\n result = (result * 0x10000000162E42FF1) >> 64;\\n }\\n if (x & 0x100000000 > 0) {\\n result = (result * 0x100000000B17217F8) >> 64;\\n }\\n if (x & 0x80000000 > 0) {\\n result = (result * 0x10000000058B90BFC) >> 64;\\n }\\n if (x & 0x40000000 > 0) {\\n result = (result * 0x1000000002C5C85FE) >> 64;\\n }\\n if (x & 0x20000000 > 0) {\\n result = (result * 0x100000000162E42FF) >> 64;\\n }\\n if (x & 0x10000000 > 0) {\\n result = (result * 0x1000000000B17217F) >> 64;\\n }\\n if (x & 0x8000000 > 0) {\\n result = (result * 0x100000000058B90C0) >> 64;\\n }\\n if (x & 0x4000000 > 0) {\\n result = (result * 0x10000000002C5C860) >> 64;\\n }\\n if (x & 0x2000000 > 0) {\\n result = (result * 0x1000000000162E430) >> 64;\\n }\\n if (x & 0x1000000 > 0) {\\n result = (result * 0x10000000000B17218) >> 64;\\n }\\n if (x & 0x800000 > 0) {\\n result = (result * 0x1000000000058B90C) >> 64;\\n }\\n if (x & 0x400000 > 0) {\\n result = (result * 0x100000000002C5C86) >> 64;\\n }\\n if (x & 0x200000 > 0) {\\n result = (result * 0x10000000000162E43) >> 64;\\n }\\n if (x & 0x100000 > 0) {\\n result = (result * 0x100000000000B1721) >> 64;\\n }\\n if (x & 0x80000 > 0) {\\n result = (result * 0x10000000000058B91) >> 64;\\n }\\n if (x & 0x40000 > 0) {\\n result = (result * 0x1000000000002C5C8) >> 64;\\n }\\n if (x & 0x20000 > 0) {\\n result = (result * 0x100000000000162E4) >> 64;\\n }\\n if (x & 0x10000 > 0) {\\n result = (result * 0x1000000000000B172) >> 64;\\n }\\n if (x & 0x8000 > 0) {\\n result = (result * 0x100000000000058B9) >> 64;\\n }\\n if (x & 0x4000 > 0) {\\n result = (result * 0x10000000000002C5D) >> 64;\\n }\\n if (x & 0x2000 > 0) {\\n result = (result * 0x1000000000000162E) >> 64;\\n }\\n if (x & 0x1000 > 0) {\\n result = (result * 0x10000000000000B17) >> 64;\\n }\\n if (x & 0x800 > 0) {\\n result = (result * 0x1000000000000058C) >> 64;\\n }\\n if (x & 0x400 > 0) {\\n result = (result * 0x100000000000002C6) >> 64;\\n }\\n if (x & 0x200 > 0) {\\n result = (result * 0x10000000000000163) >> 64;\\n }\\n if (x & 0x100 > 0) {\\n result = (result * 0x100000000000000B1) >> 64;\\n }\\n if (x & 0x80 > 0) {\\n result = (result * 0x10000000000000059) >> 64;\\n }\\n if (x & 0x40 > 0) {\\n result = (result * 0x1000000000000002C) >> 64;\\n }\\n if (x & 0x20 > 0) {\\n result = (result * 0x10000000000000016) >> 64;\\n }\\n if (x & 0x10 > 0) {\\n result = (result * 0x1000000000000000B) >> 64;\\n }\\n if (x & 0x8 > 0) {\\n result = (result * 0x10000000000000006) >> 64;\\n }\\n if (x & 0x4 > 0) {\\n result = (result * 0x10000000000000003) >> 64;\\n }\\n if (x & 0x2 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n if (x & 0x1 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n\\n // We're doing two things at the same time:\\n //\\n // 1. Multiply the result by 2^n + 1, where \\\"2^n\\\" is the integer part and the one is added to account for\\n // the fact that we initially set the result to 0.5. This is accomplished by subtracting from 191\\n // rather than 192.\\n // 2. Convert the result to the unsigned 60.18-decimal fixed-point format.\\n //\\n // This works because 2^(191-ip) = 2^ip / 2^191, where \\\"ip\\\" is the integer part \\\"2^n\\\".\\n result *= SCALE;\\n result >>= (191 - (x >> 64));\\n }\\n }\\n\\n /// @notice Finds the zero-based index of the first one in the binary representation of x.\\n /// @dev See the note on msb in the \\\"Find First Set\\\" Wikipedia article https://en.wikipedia.org/wiki/Find_first_set\\n /// @param x The uint256 number for which to find the index of the most significant bit.\\n /// @return msb The index of the most significant bit as an uint256.\\n function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\\n if (x >= 2**128) {\\n x >>= 128;\\n msb += 128;\\n }\\n if (x >= 2**64) {\\n x >>= 64;\\n msb += 64;\\n }\\n if (x >= 2**32) {\\n x >>= 32;\\n msb += 32;\\n }\\n if (x >= 2**16) {\\n x >>= 16;\\n msb += 16;\\n }\\n if (x >= 2**8) {\\n x >>= 8;\\n msb += 8;\\n }\\n if (x >= 2**4) {\\n x >>= 4;\\n msb += 4;\\n }\\n if (x >= 2**2) {\\n x >>= 2;\\n msb += 2;\\n }\\n if (x >= 2**1) {\\n // No need to shift x any more.\\n msb += 1;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.\\n ///\\n /// Requirements:\\n /// - The denominator cannot be zero.\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The multiplicand as an uint256.\\n /// @param y The multiplier as an uint256.\\n /// @param denominator The divisor as an uint256.\\n /// @return result The result as an uint256.\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n unchecked {\\n result = prod0 / denominator;\\n }\\n return result;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n if (prod1 >= denominator) {\\n revert PRBMath__MulDivOverflow(prod1, denominator);\\n }\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n unchecked {\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 lpotdod = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by lpotdod.\\n denominator := div(denominator, lpotdod)\\n\\n // Divide [prod1 prod0] by lpotdod.\\n prod0 := div(prod0, lpotdod)\\n\\n // Flip lpotdod such that it is 2^256 / lpotdod. If lpotdod is zero, then it becomes one.\\n lpotdod := add(div(sub(0, lpotdod), lpotdod), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * lpotdod;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f71e18) with full precision.\\n ///\\n /// @dev Variant of \\\"mulDiv\\\" with constant folding, i.e. in which the denominator is always 1e18. Before returning the\\n /// final result, we add 1 if (x * y) % SCALE >= HALF_SCALE. Without this, 6.6e-19 would be truncated to 0 instead of\\n /// being rounded to 1e-18. See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717.\\n ///\\n /// Requirements:\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - The body is purposely left uncommented; see the NatSpec comments in \\\"PRBMath.mulDiv\\\" to understand how this works.\\n /// - It is assumed that the result can never be type(uint256).max when x and y solve the following two equations:\\n /// 1. x * y = type(uint256).max * SCALE\\n /// 2. (x * y) % SCALE >= SCALE / 2\\n ///\\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function mulDivFixedPoint(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n uint256 prod0;\\n uint256 prod1;\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n if (prod1 >= SCALE) {\\n revert PRBMath__MulDivFixedPointOverflow(prod1);\\n }\\n\\n uint256 remainder;\\n uint256 roundUpUnit;\\n assembly {\\n remainder := mulmod(x, y, SCALE)\\n roundUpUnit := gt(remainder, 499999999999999999)\\n }\\n\\n if (prod1 == 0) {\\n unchecked {\\n result = (prod0 / SCALE) + roundUpUnit;\\n return result;\\n }\\n }\\n\\n assembly {\\n result := add(\\n mul(\\n or(\\n div(sub(prod0, remainder), SCALE_LPOTD),\\n mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, SCALE_LPOTD), SCALE_LPOTD), 1))\\n ),\\n SCALE_INVERSE\\n ),\\n roundUpUnit\\n )\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev An extension of \\\"mulDiv\\\" for signed numbers. Works by computing the signs and the absolute values separately.\\n ///\\n /// Requirements:\\n /// - None of the inputs can be type(int256).min.\\n /// - The result must fit within int256.\\n ///\\n /// @param x The multiplicand as an int256.\\n /// @param y The multiplier as an int256.\\n /// @param denominator The divisor as an int256.\\n /// @return result The result as an int256.\\n function mulDivSigned(\\n int256 x,\\n int256 y,\\n int256 denominator\\n ) internal pure returns (int256 result) {\\n if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {\\n revert PRBMath__MulDivSignedInputTooSmall();\\n }\\n\\n // Get hold of the absolute values of x, y and the denominator.\\n uint256 ax;\\n uint256 ay;\\n uint256 ad;\\n unchecked {\\n ax = x < 0 ? uint256(-x) : uint256(x);\\n ay = y < 0 ? uint256(-y) : uint256(y);\\n ad = denominator < 0 ? uint256(-denominator) : uint256(denominator);\\n }\\n\\n // Compute the absolute value of (x*y)\\u00f7denominator. The result must fit within int256.\\n uint256 rAbs = mulDiv(ax, ay, ad);\\n if (rAbs > uint256(type(int256).max)) {\\n revert PRBMath__MulDivSignedOverflow(rAbs);\\n }\\n\\n // Get the signs of x, y and the denominator.\\n uint256 sx;\\n uint256 sy;\\n uint256 sd;\\n assembly {\\n sx := sgt(x, sub(0, 1))\\n sy := sgt(y, sub(0, 1))\\n sd := sgt(denominator, sub(0, 1))\\n }\\n\\n // XOR over sx, sy and sd. This is checking whether there are one or three negative signs in the inputs.\\n // If yes, the result should be negative.\\n result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs);\\n }\\n\\n /// @notice Calculates the square root of x, rounding down.\\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The uint256 number for which to calculate the square root.\\n /// @return result The result as an uint256.\\n function sqrt(uint256 x) internal pure returns (uint256 result) {\\n if (x == 0) {\\n return 0;\\n }\\n\\n // Set the initial guess to the closest power of two that is higher than x.\\n uint256 xAux = uint256(x);\\n result = 1;\\n if (xAux >= 0x100000000000000000000000000000000) {\\n xAux >>= 128;\\n result <<= 64;\\n }\\n if (xAux >= 0x10000000000000000) {\\n xAux >>= 64;\\n result <<= 32;\\n }\\n if (xAux >= 0x100000000) {\\n xAux >>= 32;\\n result <<= 16;\\n }\\n if (xAux >= 0x10000) {\\n xAux >>= 16;\\n result <<= 8;\\n }\\n if (xAux >= 0x100) {\\n xAux >>= 8;\\n result <<= 4;\\n }\\n if (xAux >= 0x10) {\\n xAux >>= 4;\\n result <<= 2;\\n }\\n if (xAux >= 0x8) {\\n result <<= 1;\\n }\\n\\n // The operations can never overflow because the result is max 2^127 when it enters this block.\\n unchecked {\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1; // Seven iterations should be enough\\n uint256 roundedDownResult = x / result;\\n return result >= roundedDownResult ? roundedDownResult : result;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x62cbabae4910e168e99b9c2c3e3b5c9c7ad5e7abd961dcc63b7ea3d83d8ea87e\",\"license\":\"Unlicense\"}},\"version\":1}", + "metadata": "{\"compiler\":{\"version\":\"0.8.16+commit.07a7930e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IJBDirectory\",\"name\":\"_directory\",\"type\":\"address\"},{\"internalType\":\"contract IJBFundingCycleStore\",\"name\":\"_fundingCycleStore\",\"type\":\"address\"},{\"internalType\":\"contract IJBPrices\",\"name\":\"_prices\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CURRENCY_MISMATCH\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DISTRIBUTION_AMOUNT_LIMIT_REACHED\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FUNDING_CYCLE_DISTRIBUTION_PAUSED\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FUNDING_CYCLE_PAYMENT_PAUSED\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FUNDING_CYCLE_REDEEM_PAUSED\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INADEQUATE_CONTROLLER_ALLOWANCE\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INSUFFICIENT_TOKENS\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INVALID_AMOUNT_TO_SEND_DELEGATE\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INVALID_FUNDING_CYCLE\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"prod1\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"denominator\",\"type\":\"uint256\"}],\"name\":\"PRBMath__MulDivOverflow\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminal\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminal\",\"name\":\"_terminal\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"}],\"name\":\"currentOverflowOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_tokenCount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_overflow\",\"type\":\"uint256\"}],\"name\":\"currentReclaimableOverflowOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminal\",\"name\":\"_terminal\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_tokenCount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"_useTotalOverflow\",\"type\":\"bool\"}],\"name\":\"currentReclaimableOverflowOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_decimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_currency\",\"type\":\"uint256\"}],\"name\":\"currentTotalOverflowOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"directory\",\"outputs\":[{\"internalType\":\"contract IJBDirectory\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fundingCycleStore\",\"outputs\":[{\"internalType\":\"contract IJBFundingCycleStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"prices\",\"outputs\":[{\"internalType\":\"contract IJBPrices\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"recordAddedBalanceFor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_currency\",\"type\":\"uint256\"}],\"name\":\"recordDistributionFor\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"configuration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"basedOn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"discountRate\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBFundingCycleBallot\",\"name\":\"ballot\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"metadata\",\"type\":\"uint256\"}],\"internalType\":\"struct JBFundingCycle\",\"name\":\"fundingCycle\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"distributedAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"}],\"name\":\"recordMigration\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_payer\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"decimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"currency\",\"type\":\"uint256\"}],\"internalType\":\"struct JBTokenAmount\",\"name\":\"_amount\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_baseWeightCurrency\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"recordPaymentFrom\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"configuration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"basedOn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"discountRate\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBFundingCycleBallot\",\"name\":\"ballot\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"metadata\",\"type\":\"uint256\"}],\"internalType\":\"struct JBFundingCycle\",\"name\":\"fundingCycle\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"tokenCount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"contract IJBPayDelegate\",\"name\":\"delegate\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"struct JBPayDelegateAllocation[]\",\"name\":\"delegateAllocations\",\"type\":\"tuple[]\"},{\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_holder\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_tokenCount\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"recordRedemptionFor\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"configuration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"basedOn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"discountRate\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBFundingCycleBallot\",\"name\":\"ballot\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"metadata\",\"type\":\"uint256\"}],\"internalType\":\"struct JBFundingCycle\",\"name\":\"fundingCycle\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"reclaimAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"contract IJBRedemptionDelegate\",\"name\":\"delegate\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"struct JBRedemptionDelegateAllocation[]\",\"name\":\"delegateAllocations\",\"type\":\"tuple[]\"},{\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_currency\",\"type\":\"uint256\"}],\"name\":\"recordUsedAllowanceOf\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"configuration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"basedOn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"discountRate\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBFundingCycleBallot\",\"name\":\"ballot\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"metadata\",\"type\":\"uint256\"}],\"internalType\":\"struct JBFundingCycle\",\"name\":\"fundingCycle\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"usedAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminal\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"usedDistributionLimitOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminal\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"usedOverflowAllowanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Adheres to: IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.Inherits from - ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_directory\":\"A contract storing directories of terminals and controllers for each project.\",\"_fundingCycleStore\":\"A contract storing all funding cycle configurations.\",\"_prices\":\"A contract that exposes price feeds.\"}},\"currentOverflowOf(address,uint256)\":{\"details\":\"The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\",\"params\":{\"_projectId\":\"The ID of the project to get overflow for.\",\"_terminal\":\"The terminal for which the overflow is being calculated.\"},\"returns\":{\"_0\":\"The current amount of overflow that project has in the specified terminal.\"}},\"currentReclaimableOverflowOf(address,uint256,uint256,bool)\":{\"details\":\" If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.The current reclaimable overflow is returned in terms of the specified terminal's currency.The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\",\"params\":{\"_projectId\":\"The ID of the project to get the reclaimable overflow amount for.\",\"_terminal\":\"The terminal from which the reclaimable amount would come.\",\"_tokenCount\":\"The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\",\"_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`.\"},\"returns\":{\"_0\":\"The amount of overflowed tokens that can be reclaimed, as a fixed point number with the same number of decimals as the provided `_terminal`.\"}},\"currentReclaimableOverflowOf(uint256,uint256,uint256,uint256)\":{\"details\":\" If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\",\"params\":{\"_overflow\":\"The amount of overflow to make the calculation with, as a fixed point number.\",\"_projectId\":\"The ID of the project to get the reclaimable overflow amount for.\",\"_tokenCount\":\"The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\",\"_totalSupply\":\"The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\"},\"returns\":{\"_0\":\"The amount of overflowed tokens that can be reclaimed, as a fixed point number with the same number of decimals as the provided `_overflow`.\"}},\"currentTotalOverflowOf(uint256,uint256,uint256)\":{\"params\":{\"_currency\":\"The currency that the total overflow should be in terms of.\",\"_decimals\":\"The number of decimals that the fixed point overflow should include.\",\"_projectId\":\"The ID of the project to get total overflow for.\"},\"returns\":{\"_0\":\"The current total amount of overflow that project has across all terminals.\"}},\"recordAddedBalanceFor(uint256,uint256)\":{\"details\":\"The msg.sender must be an IJBSingleTokenPaymentTerminal. \",\"params\":{\"_amount\":\"The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\",\"_projectId\":\"The ID of the project to which the funds being added belong.\"}},\"recordDistributionFor(uint256,uint256,uint256)\":{\"details\":\"The msg.sender must be an IJBSingleTokenPaymentTerminal. \",\"params\":{\"_amount\":\"The amount to use from the distribution limit, as a fixed point number.\",\"_currency\":\"The currency of the `_amount`. This must match the project's current funding cycle's currency.\",\"_projectId\":\"The ID of the project that is having funds distributed.\"},\"returns\":{\"distributedAmount\":\"The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\",\"fundingCycle\":\"The funding cycle during which the distribution was made.\"}},\"recordMigration(uint256)\":{\"details\":\"The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\",\"params\":{\"_projectId\":\"The ID of the project being migrated.\"},\"returns\":{\"balance\":\"The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\"}},\"recordPaymentFrom(address,(address,uint256,uint256,uint256),uint256,uint256,address,string,bytes)\":{\"details\":\"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.The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\",\"params\":{\"_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.\",\"_baseWeightCurrency\":\"The currency to base token issuance on.\",\"_beneficiary\":\"The specified address that should be the beneficiary of anything that results from the payment.\",\"_memo\":\"A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\",\"_metadata\":\"Bytes to send along to the data source, if one is provided.\",\"_payer\":\"The original address that sent the payment to the terminal.\",\"_projectId\":\"The ID of the project being paid.\"},\"returns\":{\"delegateAllocations\":\"The amount to send to delegates instead of adding to the local balance.\",\"fundingCycle\":\"The project's funding cycle during which payment was made.\",\"memo\":\"A memo that should be passed along to the emitted event.\",\"tokenCount\":\"The number of project tokens that were minted, as a fixed point number with 18 decimals.\"}},\"recordRedemptionFor(address,uint256,uint256,string,bytes)\":{\"details\":\"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.The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\",\"params\":{\"_holder\":\"The account that is having its tokens redeemed.\",\"_memo\":\"A memo to pass along to the emitted event.\",\"_metadata\":\"Bytes to send along to the data source, if one is provided.\",\"_projectId\":\"The ID of the project to which the tokens being redeemed belong.\",\"_tokenCount\":\"The number of project tokens to redeem, as a fixed point number with 18 decimals.\"},\"returns\":{\"delegateAllocations\":\"The amount to send to delegates instead of sending to the beneficiary.\",\"fundingCycle\":\"The funding cycle during which the redemption was made.\",\"memo\":\"A memo that should be passed along to the emitted event.\",\"reclaimAmount\":\"The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\"}},\"recordUsedAllowanceOf(uint256,uint256,uint256)\":{\"details\":\"The msg.sender must be an IJBSingleTokenPaymentTerminal. \",\"params\":{\"_amount\":\"The amount to use from the allowance, as a fixed point number. \",\"_currency\":\"The currency of the `_amount`. Must match the currency of the overflow allowance.\",\"_projectId\":\"The ID of the project to use the allowance of.\"},\"returns\":{\"fundingCycle\":\"The funding cycle during which the overflow allowance is being used.\",\"usedAmount\":\"The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\"}}},\"stateVariables\":{\"balanceOf\":{\"details\":\"The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal. _terminal The terminal to which the balance applies. _projectId The ID of the project to get the balance of.\"},\"usedDistributionLimitOf\":{\"details\":\"Increases as projects use their preconfigured distribution limits.The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal. _terminal The terminal to which the used distribution limit applies. _projectId The ID of the project to get the used distribution limit of. _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\"},\"usedOverflowAllowanceOf\":{\"details\":\"Increases as projects use their allowance.The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal. _terminal The terminal to which the overflow allowance applies. _projectId The ID of the project to get the used overflow allowance of. _configuration The configuration of the during which the allowance was used.\"}},\"version\":1},\"userdoc\":{\"errors\":{\"PRBMath__MulDivOverflow(uint256,uint256)\":[{\"notice\":\"Emitted when the result overflows uint256.\"}]},\"kind\":\"user\",\"methods\":{\"balanceOf(address,uint256)\":{\"notice\":\"The amount of tokens that each project has for each terminal, in terms of the terminal's token.\"},\"currentOverflowOf(address,uint256)\":{\"notice\":\"Gets the current overflowed amount in a terminal for a specified project.\"},\"currentReclaimableOverflowOf(address,uint256,uint256,bool)\":{\"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.\"},\"currentReclaimableOverflowOf(uint256,uint256,uint256,uint256)\":{\"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.\"},\"currentTotalOverflowOf(uint256,uint256,uint256)\":{\"notice\":\"Gets the current overflowed amount for a specified project across all terminals.\"},\"directory()\":{\"notice\":\"The directory of terminals and controllers for projects.\"},\"fundingCycleStore()\":{\"notice\":\"The contract storing all funding cycle configurations.\"},\"prices()\":{\"notice\":\"The contract that exposes price feeds.\"},\"recordAddedBalanceFor(uint256,uint256)\":{\"notice\":\"Records newly added funds for the project.\"},\"recordDistributionFor(uint256,uint256,uint256)\":{\"notice\":\"Records newly distributed funds for a project.\"},\"recordMigration(uint256)\":{\"notice\":\"Records the migration of funds from this store.\"},\"recordPaymentFrom(address,(address,uint256,uint256,uint256),uint256,uint256,address,string,bytes)\":{\"notice\":\"Records newly contributed tokens to a project.\"},\"recordRedemptionFor(address,uint256,uint256,string,bytes)\":{\"notice\":\"Records newly redeemed tokens of a project.\"},\"recordUsedAllowanceOf(uint256,uint256,uint256)\":{\"notice\":\"Records newly used allowance funds of a project.\"},\"usedDistributionLimitOf(address,uint256,uint256)\":{\"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.\"},\"usedOverflowAllowanceOf(address,uint256,uint256)\":{\"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.\"}},\"notice\":\"Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/JBSingleTokenPaymentTerminalStore.sol\":\"JBSingleTokenPaymentTerminalStore\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/security/ReentrancyGuard.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuard {\\n // Booleans are more expensive than uint256 or any type that takes up a full\\n // word because each write operation emits an extra SLOAD to first read the\\n // slot's contents, replace the bits taken up by the boolean, and then write\\n // back. This is the compiler's defense against contract upgrades and\\n // pointer aliasing, and it cannot be disabled.\\n\\n // The values being non-zero value makes deployment a bit more expensive,\\n // but in exchange the refund on every call to nonReentrant will be lower in\\n // amount. Since refunds are capped to a percentage of the total\\n // transaction's gas, it is best to keep them low in cases like this one, to\\n // increase the likelihood of the full refund coming into effect.\\n uint256 private constant _NOT_ENTERED = 1;\\n uint256 private constant _ENTERED = 2;\\n\\n uint256 private _status;\\n\\n constructor() {\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and making it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n // On the first call to nonReentrant, _notEntered will be true\\n require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n _status = _ENTERED;\\n\\n _;\\n\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n _status = _NOT_ENTERED;\\n }\\n}\\n\",\"keccak256\":\"0x0e9621f60b2faabe65549f7ed0f24e8853a45c1b7990d47e8160e523683f3935\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool _approved) external;\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x516a22876c1fab47f49b1bc22b4614491cd05338af8bd2e7b382da090a079990\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"@paulrberg/contracts/math/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\nimport \\\"prb-math/contracts/PRBMath.sol\\\";\\n\",\"keccak256\":\"0x42821345981bc0434a90ba2268a2f5278dfe9e38166981d72fc7f3b776a29495\",\"license\":\"Unlicense\"},\"contracts/JBSingleTokenPaymentTerminalStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\\nimport '@paulrberg/contracts/math/PRBMath.sol';\\nimport './interfaces/IJBController.sol';\\nimport './interfaces/IJBFundingCycleDataSource.sol';\\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\\nimport './libraries/JBConstants.sol';\\nimport './libraries/JBCurrencies.sol';\\nimport './libraries/JBFixedPointNumber.sol';\\nimport './libraries/JBFundingCycleMetadataResolver.sol';\\nimport './structs/JBPayDelegateAllocation.sol';\\nimport './structs/JBPayParamsData.sol';\\n\\n/**\\n @notice\\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\\n\\n @dev\\n Adheres to:\\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n\\n @dev\\n Inherits from -\\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\\n*/\\ncontract JBSingleTokenPaymentTerminalStore is ReentrancyGuard, IJBSingleTokenPaymentTerminalStore {\\n // A library that parses the packed funding cycle metadata into a friendlier format.\\n using JBFundingCycleMetadataResolver for JBFundingCycle;\\n\\n //*********************************************************************//\\n // --------------------------- custom errors ------------------------- //\\n //*********************************************************************//\\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\\n error CURRENCY_MISMATCH();\\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\\n error FUNDING_CYCLE_PAYMENT_PAUSED();\\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\\n error FUNDING_CYCLE_REDEEM_PAUSED();\\n error INADEQUATE_CONTROLLER_ALLOWANCE();\\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\\n error INSUFFICIENT_TOKENS();\\n error INVALID_FUNDING_CYCLE();\\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\\n\\n //*********************************************************************//\\n // -------------------------- private constants ---------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \\n */\\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\\n\\n //*********************************************************************//\\n // ---------------- public immutable stored properties --------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The directory of terminals and controllers for projects.\\n */\\n IJBDirectory public immutable override directory;\\n\\n /**\\n @notice\\n The contract storing all funding cycle configurations.\\n */\\n IJBFundingCycleStore public immutable override fundingCycleStore;\\n\\n /**\\n @notice\\n The contract that exposes price feeds.\\n */\\n IJBPrices public immutable override prices;\\n\\n //*********************************************************************//\\n // --------------------- public stored properties -------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\\n\\n @dev\\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\\n\\n _terminal The terminal to which the balance applies.\\n _projectId The ID of the project to get the balance of.\\n */\\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\\n\\n /**\\n @notice\\n 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.\\n\\n @dev\\n Increases as projects use their preconfigured distribution limits.\\n\\n @dev\\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\\n\\n _terminal The terminal to which the used distribution limit applies.\\n _projectId The ID of the project to get the used distribution limit of.\\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\\n */\\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\\n public\\n override usedDistributionLimitOf;\\n\\n /**\\n @notice\\n 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.\\n\\n @dev\\n Increases as projects use their allowance.\\n\\n @dev\\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\\n\\n _terminal The terminal to which the overflow allowance applies.\\n _projectId The ID of the project to get the used overflow allowance of.\\n _configuration The configuration of the during which the allowance was used.\\n */\\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\\n public\\n override usedOverflowAllowanceOf;\\n\\n //*********************************************************************//\\n // ------------------------- external views -------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Gets the current overflowed amount in a terminal for a specified project.\\n\\n @dev\\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\\n\\n @param _terminal The terminal for which the overflow is being calculated.\\n @param _projectId The ID of the project to get overflow for.\\n\\n @return The current amount of overflow that project has in the specified terminal.\\n */\\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\\n external\\n view\\n override\\n returns (uint256)\\n {\\n // Return the overflow during the project's current funding cycle.\\n return\\n _overflowDuring(\\n _terminal,\\n _projectId,\\n fundingCycleStore.currentOf(_projectId),\\n _terminal.currency()\\n );\\n }\\n\\n /**\\n @notice\\n Gets the current overflowed amount for a specified project across all terminals.\\n\\n @param _projectId The ID of the project to get total overflow for.\\n @param _decimals The number of decimals that the fixed point overflow should include.\\n @param _currency The currency that the total overflow should be in terms of.\\n\\n @return The current total amount of overflow that project has across all terminals.\\n */\\n function currentTotalOverflowOf(\\n uint256 _projectId,\\n uint256 _decimals,\\n uint256 _currency\\n ) external view override returns (uint256) {\\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\\n }\\n\\n /**\\n @notice\\n 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.\\n\\n @dev \\n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\\n\\n @dev\\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\\n\\n @dev\\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\\n\\n @param _terminal The terminal from which the reclaimable amount would come.\\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\\n @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`.\\n\\n @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`.\\n */\\n function currentReclaimableOverflowOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n bool _useTotalOverflow\\n ) external view override returns (uint256) {\\n // Get a reference to the project's current funding cycle.\\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // Get the amount of current overflow.\\n // 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.\\n uint256 _currentOverflow = _useTotalOverflow\\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\\n\\n // If there's no overflow, there's no reclaimable overflow.\\n if (_currentOverflow == 0) return 0;\\n\\n // Get the number of outstanding tokens the project has.\\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\\n\\n // Can't redeem more tokens that is in the supply.\\n if (_tokenCount > _totalSupply) return 0;\\n\\n // Return the reclaimable overflow amount.\\n return\\n _reclaimableOverflowDuring(\\n _projectId,\\n _fundingCycle,\\n _tokenCount,\\n _totalSupply,\\n _currentOverflow\\n );\\n }\\n\\n /**\\n @notice\\n 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.\\n\\n @dev \\n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\\n\\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\\n\\n @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`.\\n */\\n function currentReclaimableOverflowOf(\\n uint256 _projectId,\\n uint256 _tokenCount,\\n uint256 _totalSupply,\\n uint256 _overflow\\n ) external view override returns (uint256) {\\n // If there's no overflow, there's no reclaimable overflow.\\n if (_overflow == 0) return 0;\\n\\n // Can't redeem more tokens that is in the supply.\\n if (_tokenCount > _totalSupply) return 0;\\n\\n // Get a reference to the project's current funding cycle.\\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // Return the reclaimable overflow amount.\\n return\\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\\n }\\n\\n //*********************************************************************//\\n // -------------------------- constructor ---------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @param _directory A contract storing directories of terminals and controllers for each project.\\n @param _fundingCycleStore A contract storing all funding cycle configurations.\\n @param _prices A contract that exposes price feeds.\\n */\\n constructor(\\n IJBDirectory _directory,\\n IJBFundingCycleStore _fundingCycleStore,\\n IJBPrices _prices\\n ) {\\n directory = _directory;\\n fundingCycleStore = _fundingCycleStore;\\n prices = _prices;\\n }\\n\\n //*********************************************************************//\\n // ---------------------- external transactions ---------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Records newly contributed tokens to a project.\\n\\n @dev\\n 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.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\\n\\n @param _payer The original address that sent the payment to the terminal.\\n @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.\\n @param _projectId The ID of the project being paid.\\n @param _baseWeightCurrency The currency to base token issuance on.\\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\\n @param _metadata Bytes to send along to the data source, if one is provided.\\n\\n @return fundingCycle The project's funding cycle during which payment was made.\\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\\n @return memo A memo that should be passed along to the emitted event.\\n */\\n function recordPaymentFrom(\\n address _payer,\\n JBTokenAmount calldata _amount,\\n uint256 _projectId,\\n uint256 _baseWeightCurrency,\\n address _beneficiary,\\n string calldata _memo,\\n bytes memory _metadata\\n )\\n external\\n override\\n nonReentrant\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 tokenCount,\\n JBPayDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n )\\n {\\n // Get a reference to the current funding cycle for the project.\\n fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // The project must have a funding cycle configured.\\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\\n\\n // Must not be paused.\\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\\n\\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\\n uint256 _weight;\\n\\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\\n // Create the params that'll be sent to the data source.\\n JBPayParamsData memory _data = JBPayParamsData(\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n _payer,\\n _amount,\\n _projectId,\\n fundingCycle.configuration,\\n _beneficiary,\\n fundingCycle.weight,\\n fundingCycle.reservedRate(),\\n _memo,\\n _metadata\\n );\\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\\n .payParams(_data);\\n }\\n // Otherwise use the funding cycle's weight\\n else {\\n _weight = fundingCycle.weight;\\n memo = _memo;\\n }\\n\\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\\n {\\n // Keep a reference to the amount that should be added to the project's balance.\\n uint256 _balanceDiff = _amount.value;\\n\\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\\n if (delegateAllocations.length != 0) {\\n for (uint256 _i; _i < delegateAllocations.length; ) {\\n // Get a reference to the amount to be delegated.\\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\\n\\n // Validate if non-zero.\\n if (_delegatedAmount != 0) {\\n // Can't delegate more than was paid.\\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\\n\\n // Decrement the total amount being added to the balance.\\n _balanceDiff = _balanceDiff - _delegatedAmount;\\n }\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n\\n // If there's no amount being recorded, there's nothing left to do.\\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\\n\\n // Add the correct balance difference to the token balance of the project.\\n if (_balanceDiff != 0)\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\\n _balanceDiff;\\n }\\n\\n // If there's no weight, token count must be 0 so there's nothing left to do.\\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\\n\\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\\n uint256 _decimals = _amount.decimals;\\n\\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\\n // 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`.\\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\\n ? 10**_decimals\\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\\n\\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\\n }\\n\\n /**\\n @notice\\n Records newly redeemed tokens of a project.\\n\\n @dev\\n 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.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\\n\\n @param _holder The account that is having its tokens redeemed.\\n @param _projectId The ID of the project to which the tokens being redeemed belong.\\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Bytes to send along to the data source, if one is provided.\\n\\n @return fundingCycle The funding cycle during which the redemption was made.\\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\\n @return memo A memo that should be passed along to the emitted event.\\n */\\n function recordRedemptionFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n string memory _memo,\\n bytes memory _metadata\\n )\\n external\\n override\\n nonReentrant\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 reclaimAmount,\\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n )\\n {\\n // Get a reference to the project's current funding cycle.\\n fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // The current funding cycle must not be paused.\\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\\n\\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\\n {\\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\\n JBTokenAmount memory _reclaimedTokenAmount;\\n uint256 _currentOverflow;\\n uint256 _totalSupply;\\n\\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\\n {\\n // Get a reference to the terminal's tokens.\\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\\n\\n // Get a reference to the terminal's decimals.\\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\\n\\n // Get areference to the terminal's currency.\\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\\n\\n // Get the amount of current overflow.\\n // 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.\\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\\n : _overflowDuring(\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n _projectId,\\n fundingCycle,\\n _currency\\n );\\n\\n // Get the number of outstanding tokens the project has.\\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\\n _projectId,\\n fundingCycle.reservedRate()\\n );\\n\\n // Can't redeem more tokens that is in the supply.\\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\\n\\n if (_currentOverflow != 0)\\n // Calculate reclaim amount using the current overflow amount.\\n reclaimAmount = _reclaimableOverflowDuring(\\n _projectId,\\n fundingCycle,\\n _tokenCount,\\n _totalSupply,\\n _currentOverflow\\n );\\n\\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\\n }\\n\\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\\n {\\n // Get a reference to the ballot state.\\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\\n\\n // Create the params that'll be sent to the data source.\\n JBRedeemParamsData memory _data = JBRedeemParamsData(\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n _holder,\\n _projectId,\\n fundingCycle.configuration,\\n _tokenCount,\\n _totalSupply,\\n _currentOverflow,\\n _reclaimedTokenAmount,\\n fundingCycle.useTotalOverflowForRedemptions(),\\n _state == JBBallotState.Active\\n ? fundingCycle.ballotRedemptionRate()\\n : fundingCycle.redemptionRate(),\\n _memo,\\n _metadata\\n );\\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\\n fundingCycle.dataSource()\\n ).redeemParams(_data);\\n }\\n } else {\\n memo = _memo;\\n }\\n }\\n\\n // Keep a reference to the amount that should be subtracted from the project's balance.\\n uint256 _balanceDiff = reclaimAmount;\\n\\n if (delegateAllocations.length != 0) {\\n // Validate all delegated amounts.\\n for (uint256 _i; _i < delegateAllocations.length; ) {\\n // Get a reference to the amount to be delegated.\\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\\n\\n // Validate if non-zero.\\n if (_delegatedAmount != 0)\\n // Increment the total amount being subtracted from the balance.\\n _balanceDiff = _balanceDiff + _delegatedAmount;\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n\\n // The amount being reclaimed must be within the project's balance.\\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\\n\\n // Remove the reclaimed funds from the project's balance.\\n if (_balanceDiff != 0) {\\n unchecked {\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\\n _balanceDiff;\\n }\\n }\\n }\\n\\n /**\\n @notice\\n Records newly distributed funds for a project.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \\n\\n @param _projectId The ID of the project that is having funds distributed.\\n @param _amount The amount to use from the distribution limit, as a fixed point number.\\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\\n\\n @return fundingCycle The funding cycle during which the distribution was made.\\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\\n */\\n function recordDistributionFor(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n )\\n external\\n override\\n nonReentrant\\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\\n {\\n // Get a reference to the project's current funding cycle.\\n fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // The funding cycle must not be configured to have distributions paused.\\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\\n\\n // The new total amount that has been distributed during this funding cycle.\\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\\n IJBSingleTokenPaymentTerminal(msg.sender)\\n ][_projectId][fundingCycle.number] + _amount;\\n\\n // Amount must be within what is still distributable.\\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\\n directory.controllerOf(_projectId)\\n ).distributionLimitOf(\\n _projectId,\\n fundingCycle.configuration,\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n IJBSingleTokenPaymentTerminal(msg.sender).token()\\n );\\n\\n // Make sure the new used amount is within the distribution limit.\\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\\n\\n // Make sure the currencies match.\\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\\n\\n // Get a reference to the terminal's currency.\\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\\n\\n // Convert the amount to the balance's currency.\\n distributedAmount = (_currency == _balanceCurrency)\\n ? _amount\\n : PRBMath.mulDiv(\\n _amount,\\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\\n );\\n\\n // The amount being distributed must be available.\\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\\n\\n // Store the new amount.\\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\\n fundingCycle.number\\n ] = _newUsedDistributionLimitOf;\\n\\n // Removed the distributed funds from the project's token balance.\\n unchecked {\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\\n distributedAmount;\\n }\\n }\\n\\n /**\\n @notice\\n Records newly used allowance funds of a project.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \\n\\n @param _projectId The ID of the project to use the allowance of.\\n @param _amount The amount to use from the allowance, as a fixed point number. \\n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\\n\\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\\n */\\n function recordUsedAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n )\\n external\\n override\\n nonReentrant\\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\\n {\\n // Get a reference to the project's current funding cycle.\\n fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\\n IJBSingleTokenPaymentTerminal(msg.sender)\\n ][_projectId][fundingCycle.configuration] + _amount;\\n\\n // There must be sufficient allowance available.\\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\\n directory.controllerOf(_projectId)\\n ).overflowAllowanceOf(\\n _projectId,\\n fundingCycle.configuration,\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n IJBSingleTokenPaymentTerminal(msg.sender).token()\\n );\\n\\n // Make sure the new used amount is within the allowance.\\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\\n\\n // Make sure the currencies match.\\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\\n\\n // Get a reference to the terminal's currency.\\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\\n\\n // Convert the amount to this store's terminal's token.\\n usedAmount = (_currency == _balanceCurrency)\\n ? _amount\\n : PRBMath.mulDiv(\\n _amount,\\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\\n );\\n\\n // The amount being distributed must be available in the overflow.\\n if (\\n usedAmount >\\n _overflowDuring(\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n _projectId,\\n fundingCycle,\\n _balanceCurrency\\n )\\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\\n\\n // Store the incremented value.\\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\\n fundingCycle.configuration\\n ] = _newUsedOverflowAllowanceOf;\\n\\n // Update the project's balance.\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\\n usedAmount;\\n }\\n\\n /**\\n @notice\\n Records newly added funds for the project.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \\n\\n @param _projectId The ID of the project to which the funds being added belong.\\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\\n */\\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\\n // Increment the balance.\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\\n _amount;\\n }\\n\\n /**\\n @notice\\n Records the migration of funds from this store.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\\n\\n @param _projectId The ID of the project being migrated.\\n\\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\\n */\\n function recordMigration(uint256 _projectId)\\n external\\n override\\n nonReentrant\\n returns (uint256 balance)\\n {\\n // Get a reference to the project's current funding cycle.\\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // Migration must be allowed.\\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\\n\\n // Return the current balance.\\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\\n\\n // Set the balance to 0.\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\\n }\\n\\n //*********************************************************************//\\n // --------------------- private helper functions -------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\\n\\n @dev \\n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\\n\\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\\n @param _overflow The amount of overflow to make the calculation with.\\n\\n @return The amount of overflowed tokens that can be reclaimed.\\n */\\n function _reclaimableOverflowDuring(\\n uint256 _projectId,\\n JBFundingCycle memory _fundingCycle,\\n uint256 _tokenCount,\\n uint256 _totalSupply,\\n uint256 _overflow\\n ) private view returns (uint256) {\\n // If the amount being redeemed is the total supply, return the rest of the overflow.\\n if (_tokenCount == _totalSupply) return _overflow;\\n\\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\\n JBBallotState.Active\\n ? _fundingCycle.ballotRedemptionRate()\\n : _fundingCycle.redemptionRate();\\n\\n // If the redemption rate is 0, nothing is claimable.\\n if (_redemptionRate == 0) return 0;\\n\\n // Get a reference to the linear proportion.\\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\\n\\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\\n\\n return\\n PRBMath.mulDiv(\\n _base,\\n _redemptionRate +\\n PRBMath.mulDiv(\\n _tokenCount,\\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\\n _totalSupply\\n ),\\n JBConstants.MAX_REDEMPTION_RATE\\n );\\n }\\n\\n /**\\n @notice\\n Gets the amount that is overflowing when measured from the specified funding cycle.\\n\\n @dev\\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\\n\\n @param _terminal The terminal for which the overflow is being calculated.\\n @param _projectId The ID of the project to get overflow for.\\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\\n\\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\\n */\\n function _overflowDuring(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n JBFundingCycle memory _fundingCycle,\\n uint256 _balanceCurrency\\n ) private view returns (uint256) {\\n // Get the current balance of the project.\\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\\n\\n // If there's no balance, there's no overflow.\\n if (_balanceOf == 0) return 0;\\n\\n // Get a reference to the distribution limit during the funding cycle.\\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\\n directory.controllerOf(_projectId)\\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\\n\\n // Get a reference to the amount still distributable during the funding cycle.\\n uint256 _distributionLimitRemaining = _distributionLimit -\\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\\n\\n // Convert the _distributionRemaining to be in terms of the provided currency.\\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\\n _distributionLimitRemaining = PRBMath.mulDiv(\\n _distributionLimitRemaining,\\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\\n );\\n\\n // Overflow is the balance of this project minus the amount that can still be distributed.\\n unchecked {\\n return\\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\\n }\\n }\\n\\n /**\\n @notice\\n Gets the amount that is currently overflowing across all of a project's terminals. \\n\\n @dev\\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\\n\\n @param _projectId The ID of the project to get the total overflow for.\\n @param _decimals The number of decimals that the fixed point overflow should include.\\n @param _currency The currency that the overflow should be in terms of.\\n\\n @return overflow The total overflow of a project's funds.\\n */\\n function _currentTotalOverflowOf(\\n uint256 _projectId,\\n uint256 _decimals,\\n uint256 _currency\\n ) private view returns (uint256) {\\n // Get a reference to the project's terminals.\\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\\n\\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\\n uint256 _ethOverflow;\\n\\n // Add the current ETH overflow for each terminal.\\n for (uint256 _i; _i < _terminals.length; ) {\\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\\n unchecked {\\n ++_i;\\n }\\n }\\n\\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.GAS_CURRENCY\\n ? _ethOverflow\\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.GAS_CURRENCY, _currency, 18));\\n\\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\\n return\\n (_decimals == 18)\\n ? _totalOverflow18Decimal\\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\\n }\\n}\\n\",\"keccak256\":\"0x17c0330168982f5da39eb12537ff22871b2d73220ca1012c1ad59d6999db7dd6\",\"license\":\"MIT\"},\"contracts/enums/JBBallotState.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nenum JBBallotState {\\n Active,\\n Approved,\\n Failed\\n}\\n\",\"keccak256\":\"0x891fcac63470398b3a11239da7feba6b07d640809fcefd2404303b823d7378f8\",\"license\":\"MIT\"},\"contracts/interfaces/IJBController.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBFundAccessConstraints.sol';\\nimport './../structs/JBFundingCycleData.sol';\\nimport './../structs/JBFundingCycleMetadata.sol';\\nimport './../structs/JBGroupedSplits.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBMigratable.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBSplitsStore.sol';\\nimport './IJBTokenStore.sol';\\n\\ninterface IJBController is IERC165 {\\n event LaunchProject(uint256 configuration, uint256 projectId, string memo, address caller);\\n\\n event LaunchFundingCycles(uint256 configuration, uint256 projectId, string memo, address caller);\\n\\n event ReconfigureFundingCycles(\\n uint256 configuration,\\n uint256 projectId,\\n string memo,\\n address caller\\n );\\n\\n event SetFundAccessConstraints(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n JBFundAccessConstraints constraints,\\n address caller\\n );\\n\\n event DistributeReservedTokens(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address beneficiary,\\n uint256 tokenCount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n address caller\\n );\\n\\n event DistributeToReservedTokenSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n uint256 tokenCount,\\n address caller\\n );\\n\\n event MintTokens(\\n address indexed beneficiary,\\n uint256 indexed projectId,\\n uint256 tokenCount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n uint256 reservedRate,\\n address caller\\n );\\n\\n event BurnTokens(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 tokenCount,\\n string memo,\\n address caller\\n );\\n\\n event Migrate(uint256 indexed projectId, IJBMigratable to, address caller);\\n\\n event PrepMigration(uint256 indexed projectId, address from, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function tokenStore() external view returns (IJBTokenStore);\\n\\n function splitsStore() external view returns (IJBSplitsStore);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function reservedTokenBalanceOf(uint256 _projectId, uint256 _reservedRate)\\n external\\n view\\n returns (uint256);\\n\\n function distributionLimitOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n IJBPaymentTerminal _terminal,\\n address _token\\n ) external view returns (uint256 distributionLimit, uint256 distributionLimitCurrency);\\n\\n function overflowAllowanceOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n IJBPaymentTerminal _terminal,\\n address _token\\n ) external view returns (uint256 overflowAllowance, uint256 overflowAllowanceCurrency);\\n\\n function totalOutstandingTokensOf(uint256 _projectId, uint256 _reservedRate)\\n external\\n view\\n returns (uint256);\\n\\n function getFundingCycleOf(uint256 _projectId, uint256 _configuration)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function latestConfiguredFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (\\n JBFundingCycle memory,\\n JBFundingCycleMetadata memory metadata,\\n JBBallotState\\n );\\n\\n function currentFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function queuedFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function launchProjectFor(\\n address _owner,\\n JBProjectMetadata calldata _projectMetadata,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n IJBPaymentTerminal[] memory _terminals,\\n string calldata _memo\\n ) external returns (uint256 projectId);\\n\\n function launchFundingCyclesFor(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n IJBPaymentTerminal[] memory _terminals,\\n string calldata _memo\\n ) external returns (uint256 configuration);\\n\\n function reconfigureFundingCyclesOf(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n string calldata _memo\\n ) external returns (uint256);\\n\\n function mintTokensOf(\\n uint256 _projectId,\\n uint256 _tokenCount,\\n address _beneficiary,\\n string calldata _memo,\\n bool _preferClaimedTokens,\\n bool _useReservedRate\\n ) external returns (uint256 beneficiaryTokenCount);\\n\\n function burnTokensOf(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n string calldata _memo,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function distributeReservedTokensOf(uint256 _projectId, string memory _memo)\\n external\\n returns (uint256);\\n\\n function migrate(uint256 _projectId, IJBMigratable _to) external;\\n}\\n\",\"keccak256\":\"0xb1ee4b41f2a06f28f69c74cb729b8964f2e75f3c545a68f85bd9082b5575bc85\",\"license\":\"MIT\"},\"contracts/interfaces/IJBDirectory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBProjects.sol';\\n\\ninterface IJBDirectory {\\n event SetController(uint256 indexed projectId, address indexed controller, address caller);\\n\\n event AddTerminal(uint256 indexed projectId, IJBPaymentTerminal indexed terminal, address caller);\\n\\n event SetTerminals(uint256 indexed projectId, IJBPaymentTerminal[] terminals, address caller);\\n\\n event SetPrimaryTerminal(\\n uint256 indexed projectId,\\n address indexed token,\\n IJBPaymentTerminal indexed terminal,\\n address caller\\n );\\n\\n event SetIsAllowedToSetFirstController(address indexed addr, bool indexed flag, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function controllerOf(uint256 _projectId) external view returns (address);\\n\\n function isAllowedToSetFirstController(address _address) external view returns (bool);\\n\\n function terminalsOf(uint256 _projectId) external view returns (IJBPaymentTerminal[] memory);\\n\\n function isTerminalOf(uint256 _projectId, IJBPaymentTerminal _terminal)\\n external\\n view\\n returns (bool);\\n\\n function primaryTerminalOf(uint256 _projectId, address _token)\\n external\\n view\\n returns (IJBPaymentTerminal);\\n\\n function setControllerOf(uint256 _projectId, address _controller) external;\\n\\n function setTerminalsOf(uint256 _projectId, IJBPaymentTerminal[] calldata _terminals) external;\\n\\n function setPrimaryTerminalOf(\\n uint256 _projectId,\\n address _token,\\n IJBPaymentTerminal _terminal\\n ) external;\\n\\n function setIsAllowedToSetFirstController(address _address, bool _flag) external;\\n}\\n\",\"keccak256\":\"0x715321646db00514d1355ed43c40cd3f01e94959552fd07797b315d9c49cdb1d\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleBallot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../enums/JBBallotState.sol';\\n\\ninterface IJBFundingCycleBallot is IERC165 {\\n function duration() external view returns (uint256);\\n\\n function stateOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n uint256 _start\\n ) external view returns (JBBallotState);\\n}\\n\",\"keccak256\":\"0x49553a56209237846bc400cf27f260824a6bd06fd8094a7eb5abb9de75779598\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleDataSource.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBPayDelegateAllocation.sol';\\nimport './../structs/JBPayParamsData.sol';\\nimport './../structs/JBRedeemParamsData.sol';\\nimport './../structs/JBRedemptionDelegateAllocation.sol';\\n\\n/**\\n @title\\n Datasource\\n\\n @notice\\n The datasource is called by JBPaymentTerminal on pay and redemption, and provide an extra layer of logic to use \\n a custom weight, a custom memo and/or a pay/redeem delegate\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n*/\\ninterface IJBFundingCycleDataSource is IERC165 {\\n /**\\n @notice\\n The datasource implementation for JBPaymentTerminal.pay(..)\\n\\n @param _data the data passed to the data source in terminal.pay(..), as a JBPayParamsData struct:\\n IJBPaymentTerminal terminal;\\n address payer;\\n JBTokenAmount amount;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n address beneficiary;\\n uint256 weight;\\n uint256 reservedRate;\\n string memo;\\n bytes metadata;\\n\\n @return weight the weight to use to override the funding cycle weight\\n @return memo the memo to override the pay(..) memo\\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\\n */\\n function payParams(JBPayParamsData calldata _data)\\n external\\n returns (\\n uint256 weight,\\n string memory memo,\\n JBPayDelegateAllocation[] memory delegateAllocations\\n );\\n\\n /**\\n @notice\\n The datasource implementation for JBPaymentTerminal.redeemTokensOf(..)\\n\\n @param _data the data passed to the data source in terminal.redeemTokensOf(..), as a JBRedeemParamsData struct:\\n IJBPaymentTerminal terminal;\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 tokenCount;\\n uint256 totalSupply;\\n uint256 overflow;\\n JBTokenAmount reclaimAmount;\\n bool useTotalOverflow;\\n uint256 redemptionRate;\\n uint256 ballotRedemptionRate;\\n string memo;\\n bytes metadata;\\n\\n @return reclaimAmount The amount to claim, overriding the terminal logic.\\n @return memo The memo to override the redeemTokensOf(..) memo.\\n @return delegateAllocations The amount to send to delegates instead of adding to the beneficiary.\\n */\\n function redeemParams(JBRedeemParamsData calldata _data)\\n external\\n returns (\\n uint256 reclaimAmount,\\n string memory memo,\\n JBRedemptionDelegateAllocation[] memory delegateAllocations\\n );\\n}\\n\",\"keccak256\":\"0xa424abc146a61b69db83e511c064492da6fab6d8226e13d1580bc9fbc50d6738\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../enums/JBBallotState.sol';\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBFundingCycleData.sol';\\n\\ninterface IJBFundingCycleStore {\\n event Configure(\\n uint256 indexed configuration,\\n uint256 indexed projectId,\\n JBFundingCycleData data,\\n uint256 metadata,\\n uint256 mustStartAtOrAfter,\\n address caller\\n );\\n\\n event Init(uint256 indexed configuration, uint256 indexed projectId, uint256 indexed basedOn);\\n\\n function latestConfigurationOf(uint256 _projectId) external view returns (uint256);\\n\\n function get(uint256 _projectId, uint256 _configuration)\\n external\\n view\\n returns (JBFundingCycle memory);\\n\\n function latestConfiguredOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBBallotState ballotState);\\n\\n function queuedOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentBallotStateOf(uint256 _projectId) external view returns (JBBallotState);\\n\\n function configureFor(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n uint256 _metadata,\\n uint256 _mustStartAtOrAfter\\n ) external returns (JBFundingCycle memory fundingCycle);\\n}\\n\",\"keccak256\":\"0xaead823851433be0c2ddc8f8086813e6cd647de3a1bc0f7570a5d6b38c378b5a\",\"license\":\"MIT\"},\"contracts/interfaces/IJBMigratable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBMigratable {\\n function prepForMigrationOf(uint256 _projectId, address _from) external;\\n}\\n\",\"keccak256\":\"0xc81053e4b4754fc510aa04fecd3ab1460f01e3e27761e7a8c94f631a978ae127\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPayDelegate.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBDidPayData.sol';\\n\\n/**\\n @title\\n Pay delegate\\n\\n @notice\\n Delegate called after JBTerminal.pay(..) logic completion (if passed by the funding cycle datasource)\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n*/\\ninterface IJBPayDelegate is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.pay(..), after the execution of its logic\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control\\n \\n @param _data the data passed by the terminal, as a JBDidPayData struct:\\n address payer;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n JBTokenAmount amount;\\n JBTokenAmount forwardedAmount;\\n uint256 projectTokenCount;\\n address beneficiary;\\n bool preferClaimedTokens;\\n string memo;\\n bytes metadata;\\n */\\n function didPay(JBDidPayData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0xa797de18b69eceba117e1f0b3810cf3cc2d2791417d580a5bdc510d1b868ab26\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\n\\ninterface IJBPaymentTerminal is IERC165 {\\n function acceptsToken(address _token, uint256 _projectId) external view returns (bool);\\n\\n function currencyForToken(address _token) external view returns (uint256);\\n\\n function decimalsForToken(address _token) external view returns (uint256);\\n\\n // Return value must be a fixed point number with 18 decimals.\\n function currentEthOverflowOf(uint256 _projectId) external view returns (uint256);\\n\\n function pay(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable returns (uint256 beneficiaryTokenCount);\\n\\n function addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable;\\n}\\n\",\"keccak256\":\"0xb7826f5ed609359ce322c09e83236c47ba385df1c3cad3607e56fd0a2e00eee2\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPriceFeed.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBPriceFeed {\\n function currentPrice(uint256 _targetDecimals) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x57c71282fec1b34b00cf991ffed2e36031c393e35bfa7ca5d723eb6572fb7122\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPrices.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBPriceFeed.sol';\\n\\ninterface IJBPrices {\\n event AddFeed(uint256 indexed currency, uint256 indexed base, IJBPriceFeed feed);\\n\\n function feedFor(uint256 _currency, uint256 _base) external view returns (IJBPriceFeed);\\n\\n function priceFor(\\n uint256 _currency,\\n uint256 _base,\\n uint256 _decimals\\n ) external view returns (uint256);\\n\\n function addFeedFor(\\n uint256 _currency,\\n uint256 _base,\\n IJBPriceFeed _priceFeed\\n ) external;\\n}\\n\",\"keccak256\":\"0x82a175b1f4b95b506c98406576cd59cbe04615e3df24f9cf3587b61b8ee323b1\",\"license\":\"MIT\"},\"contracts/interfaces/IJBProjects.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBTokenUriResolver.sol';\\n\\ninterface IJBProjects is IERC721 {\\n event Create(\\n uint256 indexed projectId,\\n address indexed owner,\\n JBProjectMetadata metadata,\\n address caller\\n );\\n\\n event SetMetadata(uint256 indexed projectId, JBProjectMetadata metadata, address caller);\\n\\n event SetTokenUriResolver(IJBTokenUriResolver indexed resolver, address caller);\\n\\n function count() external view returns (uint256);\\n\\n function metadataContentOf(uint256 _projectId, uint256 _domain)\\n external\\n view\\n returns (string memory);\\n\\n function tokenUriResolver() external view returns (IJBTokenUriResolver);\\n\\n function createFor(address _owner, JBProjectMetadata calldata _metadata)\\n external\\n returns (uint256 projectId);\\n\\n function setMetadataOf(uint256 _projectId, JBProjectMetadata calldata _metadata) external;\\n\\n function setTokenUriResolver(IJBTokenUriResolver _newResolver) external;\\n}\\n\",\"keccak256\":\"0x7cfc021d0bd7e73b1ba8f4845d7d35e3419d6a14d3d25ca3a8010e7f91062fe4\",\"license\":\"MIT\"},\"contracts/interfaces/IJBRedemptionDelegate.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBDidRedeemData.sol';\\n\\n/**\\n @title\\n Redemption delegate\\n\\n @notice\\n Delegate called after JBTerminal.redeemTokensOf(..) logic completion (if passed by the funding cycle datasource)\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n*/\\ninterface IJBRedemptionDelegate is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.redeemTokensOf(..), after the execution of its logic\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control\\n \\n @param _data the data passed by the terminal, as a JBDidRedeemData struct:\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 projectTokenCount;\\n JBTokenAmount reclaimedAmount;\\n JBTokenAmount forwardedAmount;\\n address payable beneficiary;\\n string memo;\\n bytes metadata;\\n */\\n function didRedeem(JBDidRedeemData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0x172d2c0be65e72e54f71ae521907067f0fa30e8ca05c4f88826903208aa437e2\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSingleTokenPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBPaymentTerminal.sol';\\n\\ninterface IJBSingleTokenPaymentTerminal is IJBPaymentTerminal {\\n function token() external view returns (address);\\n\\n function currency() external view returns (uint256);\\n\\n function decimals() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xf6e78323caa9af7bbf024f44b2032a83fed0394e0b3a242a6346e73c85b2e46f\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSingleTokenPaymentTerminalStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBPayDelegateAllocation.sol';\\nimport './../structs/JBRedemptionDelegateAllocation.sol';\\nimport './../structs/JBTokenAmount.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBPrices.sol';\\nimport './IJBSingleTokenPaymentTerminal.sol';\\n\\ninterface IJBSingleTokenPaymentTerminalStore {\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function prices() external view returns (IJBPrices);\\n\\n function balanceOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\\n external\\n view\\n returns (uint256);\\n\\n function usedDistributionLimitOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _fundingCycleNumber\\n ) external view returns (uint256);\\n\\n function usedOverflowAllowanceOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _fundingCycleConfiguration\\n ) external view returns (uint256);\\n\\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\\n external\\n view\\n returns (uint256);\\n\\n function currentTotalOverflowOf(\\n uint256 _projectId,\\n uint256 _decimals,\\n uint256 _currency\\n ) external view returns (uint256);\\n\\n function currentReclaimableOverflowOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n bool _useTotalOverflow\\n ) external view returns (uint256);\\n\\n function currentReclaimableOverflowOf(\\n uint256 _projectId,\\n uint256 _tokenCount,\\n uint256 _totalSupply,\\n uint256 _overflow\\n ) external view returns (uint256);\\n\\n function recordPaymentFrom(\\n address _payer,\\n JBTokenAmount memory _amount,\\n uint256 _projectId,\\n uint256 _baseWeightCurrency,\\n address _beneficiary,\\n string calldata _memo,\\n bytes calldata _metadata\\n )\\n external\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 tokenCount,\\n JBPayDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n );\\n\\n function recordRedemptionFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n string calldata _memo,\\n bytes calldata _metadata\\n )\\n external\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 reclaimAmount,\\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n );\\n\\n function recordDistributionFor(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n ) external returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount);\\n\\n function recordUsedAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n ) external returns (JBFundingCycle memory fundingCycle, uint256 withdrawnAmount);\\n\\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external;\\n\\n function recordMigration(uint256 _projectId) external returns (uint256 balance);\\n}\\n\",\"keccak256\":\"0xd78929c9371fd7895b829ef5e4ad4b3786523c3580ac3f6f5f25d2b5941c0dd3\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSplitAllocator.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport '../structs/JBSplitAllocationData.sol';\\n\\n/**\\n @title\\n Split allocator\\n\\n @notice\\n Provide a way to process a single split with extra logic\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n\\n @dev\\n The contract address should be set as an allocator in the adequate split\\n*/\\ninterface IJBSplitAllocator is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.distributePayoutOf(..), during the processing of the split including it\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control. The token and/or eth are optimistically transfered\\n to the allocator for its logic.\\n \\n @param _data the data passed by the terminal, as a JBSplitAllocationData struct:\\n address token;\\n uint256 amount;\\n uint256 decimals;\\n uint256 projectId;\\n uint256 group;\\n JBSplit split;\\n */\\n function allocate(JBSplitAllocationData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0x5efb6f51fc161f42ff58989386ad99028e4039a0ba897d66f358c3dfcf686105\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSplitsStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBGroupedSplits.sol';\\nimport './../structs/JBSplit.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBProjects.sol';\\n\\ninterface IJBSplitsStore {\\n event SetSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n address caller\\n );\\n\\n function projects() external view returns (IJBProjects);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function splitsOf(\\n uint256 _projectId,\\n uint256 _domain,\\n uint256 _group\\n ) external view returns (JBSplit[] memory);\\n\\n function set(\\n uint256 _projectId,\\n uint256 _domain,\\n JBGroupedSplits[] memory _groupedSplits\\n ) external;\\n}\\n\",\"keccak256\":\"0x66dab3dd394e318b850401ca92c2963b906cc0ad5562fa5d4f6f850175d1c77a\",\"license\":\"MIT\"},\"contracts/interfaces/IJBToken.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBToken {\\n function projectId() external view returns (uint256);\\n\\n function decimals() external view returns (uint8);\\n\\n function totalSupply(uint256 _projectId) external view returns (uint256);\\n\\n function balanceOf(address _account, uint256 _projectId) external view returns (uint256);\\n\\n function mint(\\n uint256 _projectId,\\n address _account,\\n uint256 _amount\\n ) external;\\n\\n function burn(\\n uint256 _projectId,\\n address _account,\\n uint256 _amount\\n ) external;\\n\\n function approve(\\n uint256,\\n address _spender,\\n uint256 _amount\\n ) external;\\n\\n function transfer(\\n uint256 _projectId,\\n address _to,\\n uint256 _amount\\n ) external;\\n\\n function transferFrom(\\n uint256 _projectId,\\n address _from,\\n address _to,\\n uint256 _amount\\n ) external;\\n}\\n\",\"keccak256\":\"0xe8969210417736c85d71101bf1c0bd8ebbf9d1e62a93e758148bd5709a6c7097\",\"license\":\"MIT\"},\"contracts/interfaces/IJBTokenStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBProjects.sol';\\nimport './IJBToken.sol';\\n\\ninterface IJBTokenStore {\\n event Issue(\\n uint256 indexed projectId,\\n IJBToken indexed token,\\n string name,\\n string symbol,\\n address caller\\n );\\n\\n event Mint(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 amount,\\n bool tokensWereClaimed,\\n bool preferClaimedTokens,\\n address caller\\n );\\n\\n event Burn(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 amount,\\n uint256 initialUnclaimedBalance,\\n uint256 initialClaimedBalance,\\n bool preferClaimedTokens,\\n address caller\\n );\\n\\n event Claim(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 initialUnclaimedBalance,\\n uint256 amount,\\n address caller\\n );\\n\\n event Set(uint256 indexed projectId, IJBToken indexed newToken, address caller);\\n\\n event Transfer(\\n address indexed holder,\\n uint256 indexed projectId,\\n address indexed recipient,\\n uint256 amount,\\n address caller\\n );\\n\\n function tokenOf(uint256 _projectId) external view returns (IJBToken);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function unclaimedBalanceOf(address _holder, uint256 _projectId) external view returns (uint256);\\n\\n function unclaimedTotalSupplyOf(uint256 _projectId) external view returns (uint256);\\n\\n function totalSupplyOf(uint256 _projectId) external view returns (uint256);\\n\\n function balanceOf(address _holder, uint256 _projectId) external view returns (uint256 _result);\\n\\n function issueFor(\\n uint256 _projectId,\\n string calldata _name,\\n string calldata _symbol\\n ) external returns (IJBToken token);\\n\\n function setFor(uint256 _projectId, IJBToken _token) external;\\n\\n function burnFrom(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function mintFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function claimFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount\\n ) external;\\n\\n function transferFrom(\\n address _holder,\\n uint256 _projectId,\\n address _recipient,\\n uint256 _amount\\n ) external;\\n}\\n\",\"keccak256\":\"0x98459e3af050d41dfeffdc97f1c93330207ba450f8ff3613224b49a89eeca9c6\",\"license\":\"MIT\"},\"contracts/interfaces/IJBTokenUriResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBTokenUriResolver {\\n function getUri(uint256 _projectId) external view returns (string memory tokenUri);\\n}\\n\",\"keccak256\":\"0xd267fd8ca7c21c2c71794acdb9a98314c33a35fc559e0bf0897a6686d196d174\",\"license\":\"MIT\"},\"contracts/libraries/JBConstants.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/**\\n @notice\\n Global constants used across Juicebox contracts.\\n*/\\nlibrary JBConstants {\\n uint256 public constant MAX_RESERVED_RATE = 10_000;\\n uint256 public constant MAX_REDEMPTION_RATE = 10_000;\\n uint256 public constant MAX_DISCOUNT_RATE = 1_000_000_000;\\n uint256 public constant SPLITS_TOTAL_PERCENT = 1_000_000_000;\\n uint256 public constant MAX_FEE = 1_000_000_000;\\n uint256 public constant MAX_FEE_DISCOUNT = 1_000_000_000;\\n}\\n\",\"keccak256\":\"0x34362846a1cd428a8bdedf4ab6857e11402f345cb87b994b2e7fb6d2474b808d\",\"license\":\"MIT\"},\"contracts/libraries/JBCurrencies.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBCurrencies {\\n uint256 public constant ETH = 1;\\n uint256 public constant USD = 2;\\n}\\n\",\"keccak256\":\"0x7e417ff25c173608ee4fe6d9fc3dcd5e1458c78c889af12bac47b1189a436076\",\"license\":\"MIT\"},\"contracts/libraries/JBFixedPointNumber.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nlibrary JBFixedPointNumber {\\n function adjustDecimals(\\n uint256 _value,\\n uint256 _decimals,\\n uint256 _targetDecimals\\n ) internal pure returns (uint256) {\\n // If decimals need adjusting, multiply or divide the price by the decimal adjuster to get the normalized result.\\n if (_targetDecimals == _decimals) return _value;\\n else if (_targetDecimals > _decimals) return _value * 10**(_targetDecimals - _decimals);\\n else return _value / 10**(_decimals - _targetDecimals);\\n }\\n}\\n\",\"keccak256\":\"0x18efac48269f3a3bd7e9a1c770776f950e0afa86769e6f8b128002c3b8c6742c\",\"license\":\"MIT\"},\"contracts/libraries/JBFundingCycleMetadataResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBFundingCycleMetadata.sol';\\nimport './../structs/JBGlobalFundingCycleMetadata.sol';\\nimport './JBConstants.sol';\\nimport './JBGlobalFundingCycleMetadataResolver.sol';\\n\\nlibrary JBFundingCycleMetadataResolver {\\n function global(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (JBGlobalFundingCycleMetadata memory)\\n {\\n return JBGlobalFundingCycleMetadataResolver.expandMetadata(uint8(_fundingCycle.metadata >> 8));\\n }\\n\\n function reservedRate(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n return uint256(uint16(_fundingCycle.metadata >> 24));\\n }\\n\\n function redemptionRate(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n // Redemption rate is a number 0-10000. It's inverse was stored so the most common case of 100% results in no storage needs.\\n return JBConstants.MAX_REDEMPTION_RATE - uint256(uint16(_fundingCycle.metadata >> 40));\\n }\\n\\n function ballotRedemptionRate(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (uint256)\\n {\\n // Redemption rate is a number 0-10000. It's inverse was stored so the most common case of 100% results in no storage needs.\\n return JBConstants.MAX_REDEMPTION_RATE - uint256(uint16(_fundingCycle.metadata >> 56));\\n }\\n\\n function payPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 72) & 1) == 1;\\n }\\n\\n function distributionsPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 73) & 1) == 1;\\n }\\n\\n function redeemPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 74) & 1) == 1;\\n }\\n\\n function burnPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 75) & 1) == 1;\\n }\\n\\n function mintingAllowed(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 76) & 1) == 1;\\n }\\n\\n function terminalMigrationAllowed(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 77) & 1) == 1;\\n }\\n\\n function controllerMigrationAllowed(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 78) & 1) == 1;\\n }\\n\\n function shouldHoldFees(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 79) & 1) == 1;\\n }\\n\\n function preferClaimedTokenOverride(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 80) & 1) == 1;\\n }\\n\\n function useTotalOverflowForRedemptions(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 81) & 1) == 1;\\n }\\n\\n function useDataSourceForPay(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return (_fundingCycle.metadata >> 82) & 1 == 1;\\n }\\n\\n function useDataSourceForRedeem(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return (_fundingCycle.metadata >> 83) & 1 == 1;\\n }\\n\\n function dataSource(JBFundingCycle memory _fundingCycle) internal pure returns (address) {\\n return address(uint160(_fundingCycle.metadata >> 84));\\n }\\n\\n function metadata(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n return uint256(uint8(_fundingCycle.metadata >> 244));\\n }\\n\\n /**\\n @notice\\n Pack the funding cycle metadata.\\n\\n @param _metadata The metadata to validate and pack.\\n\\n @return packed The packed uint256 of all metadata params. The first 8 bits specify the version.\\n */\\n function packFundingCycleMetadata(JBFundingCycleMetadata memory _metadata)\\n internal\\n pure\\n returns (uint256 packed)\\n {\\n // version 1 in the bits 0-7 (8 bits).\\n packed = 1;\\n // global metadta in bits 8-23 (16 bits).\\n packed |=\\n JBGlobalFundingCycleMetadataResolver.packFundingCycleGlobalMetadata(_metadata.global) <<\\n 8;\\n // reserved rate in bits 24-39 (16 bits).\\n packed |= _metadata.reservedRate << 24;\\n // redemption rate in bits 40-55 (16 bits).\\n // redemption rate is a number 0-10000. Store the reverse so the most common case of 100% results in no storage needs.\\n packed |= (JBConstants.MAX_REDEMPTION_RATE - _metadata.redemptionRate) << 40;\\n // ballot redemption rate rate in bits 56-71 (16 bits).\\n // ballot redemption rate is a number 0-10000. Store the reverse so the most common case of 100% results in no storage needs.\\n packed |= (JBConstants.MAX_REDEMPTION_RATE - _metadata.ballotRedemptionRate) << 56;\\n // pause pay in bit 72.\\n if (_metadata.pausePay) packed |= 1 << 72;\\n // pause tap in bit 73.\\n if (_metadata.pauseDistributions) packed |= 1 << 73;\\n // pause redeem in bit 74.\\n if (_metadata.pauseRedeem) packed |= 1 << 74;\\n // pause burn in bit 75.\\n if (_metadata.pauseBurn) packed |= 1 << 75;\\n // allow minting in bit 76.\\n if (_metadata.allowMinting) packed |= 1 << 76;\\n // allow terminal migration in bit 77.\\n if (_metadata.allowTerminalMigration) packed |= 1 << 77;\\n // allow controller migration in bit 78.\\n if (_metadata.allowControllerMigration) packed |= 1 << 78;\\n // hold fees in bit 79.\\n if (_metadata.holdFees) packed |= 1 << 79;\\n // prefer claimed token override in bit 80.\\n if (_metadata.preferClaimedTokenOverride) packed |= 1 << 80;\\n // useTotalOverflowForRedemptions in bit 81.\\n if (_metadata.useTotalOverflowForRedemptions) packed |= 1 << 81;\\n // use pay data source in bit 82.\\n if (_metadata.useDataSourceForPay) packed |= 1 << 82;\\n // use redeem data source in bit 83.\\n if (_metadata.useDataSourceForRedeem) packed |= 1 << 83;\\n // data source address in bits 84-243.\\n packed |= uint256(uint160(address(_metadata.dataSource))) << 84;\\n // metadata in bits 244-252 (8 bits).\\n packed |= _metadata.metadata << 244;\\n }\\n\\n /**\\n @notice\\n Expand the funding cycle metadata.\\n\\n @param _fundingCycle The funding cycle having its metadata expanded.\\n\\n @return metadata The metadata object.\\n */\\n function expandMetadata(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (JBFundingCycleMetadata memory)\\n {\\n return\\n JBFundingCycleMetadata(\\n global(_fundingCycle),\\n reservedRate(_fundingCycle),\\n redemptionRate(_fundingCycle),\\n ballotRedemptionRate(_fundingCycle),\\n payPaused(_fundingCycle),\\n distributionsPaused(_fundingCycle),\\n redeemPaused(_fundingCycle),\\n burnPaused(_fundingCycle),\\n mintingAllowed(_fundingCycle),\\n terminalMigrationAllowed(_fundingCycle),\\n controllerMigrationAllowed(_fundingCycle),\\n shouldHoldFees(_fundingCycle),\\n preferClaimedTokenOverride(_fundingCycle),\\n useTotalOverflowForRedemptions(_fundingCycle),\\n useDataSourceForPay(_fundingCycle),\\n useDataSourceForRedeem(_fundingCycle),\\n dataSource(_fundingCycle),\\n metadata(_fundingCycle)\\n );\\n }\\n}\\n\",\"keccak256\":\"0x3d045c38593102cfb6ac67f3ddf2232e1ff5518d6d021423ae2681387599fbd3\",\"license\":\"MIT\"},\"contracts/libraries/JBGlobalFundingCycleMetadataResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport './../structs/JBFundingCycleMetadata.sol';\\n\\nlibrary JBGlobalFundingCycleMetadataResolver {\\n function setTerminalsAllowed(uint8 _data) internal pure returns (bool) {\\n return (_data & 1) == 1;\\n }\\n\\n function setControllerAllowed(uint8 _data) internal pure returns (bool) {\\n return ((_data >> 1) & 1) == 1;\\n }\\n\\n function transfersPaused(uint8 _data) internal pure returns (bool) {\\n return ((_data >> 2) & 1) == 1;\\n }\\n\\n /**\\n @notice\\n Pack the global funding cycle metadata.\\n\\n @param _metadata The metadata to validate and pack.\\n\\n @return packed The packed uint256 of all global metadata params. The first 8 bits specify the version.\\n */\\n function packFundingCycleGlobalMetadata(JBGlobalFundingCycleMetadata memory _metadata)\\n internal\\n pure\\n returns (uint256 packed)\\n {\\n // allow set terminals in bit 0.\\n if (_metadata.allowSetTerminals) packed |= 1;\\n // allow set controller in bit 1.\\n if (_metadata.allowSetController) packed |= 1 << 1;\\n // pause transfers in bit 2.\\n if (_metadata.pauseTransfers) packed |= 1 << 2;\\n }\\n\\n /**\\n @notice\\n Expand the global funding cycle metadata.\\n\\n @param _packedMetadata The packed metadata to expand.\\n\\n @return metadata The global metadata object.\\n */\\n function expandMetadata(uint8 _packedMetadata)\\n internal\\n pure\\n returns (JBGlobalFundingCycleMetadata memory metadata)\\n {\\n return\\n JBGlobalFundingCycleMetadata(\\n setTerminalsAllowed(_packedMetadata),\\n setControllerAllowed(_packedMetadata),\\n transfersPaused(_packedMetadata)\\n );\\n }\\n}\\n\",\"keccak256\":\"0x0d998f938026edeb755987a79421267cf860801161b5f171206a200b60f1061f\",\"license\":\"MIT\"},\"contracts/structs/JBDidPayData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member payer The address from which the payment originated.\\n @member projectId The ID of the project for which the payment was made.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the payment is being made.\\n @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.\\n @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.\\n @member projectTokenCount The number of project tokens minted for the beneficiary.\\n @member beneficiary The address to which the tokens were minted.\\n @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.\\n @member memo The memo that is being emitted alongside the payment.\\n @member metadata Extra data to send to the delegate.\\n*/\\nstruct JBDidPayData {\\n address payer;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n JBTokenAmount amount;\\n JBTokenAmount forwardedAmount;\\n uint256 projectTokenCount;\\n address beneficiary;\\n bool preferClaimedTokens;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0xf3c664309b37790f16047ae97b0459889ae0242dfcde7fc8902c8d10c7f8e6b6\",\"license\":\"MIT\"},\"contracts/structs/JBDidRedeemData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member holder The holder of the tokens being redeemed.\\n @member projectId The ID of the project with which the redeemed tokens are associated.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the redemption is being made.\\n @member projectTokenCount The number of project tokens being redeemed.\\n @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.\\n @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.\\n @member beneficiary The address to which the reclaimed amount will be sent.\\n @member memo The memo that is being emitted alongside the redemption.\\n @member metadata Extra data to send to the delegate.\\n*/\\nstruct JBDidRedeemData {\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 projectTokenCount;\\n JBTokenAmount reclaimedAmount;\\n JBTokenAmount forwardedAmount;\\n address payable beneficiary;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0xe2c401f39723a7ce915b8bef328744c66daaf57460843964b941456c2258a412\",\"license\":\"MIT\"},\"contracts/structs/JBFundAccessConstraints.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBPaymentTerminal.sol';\\n\\n/** \\n @member terminal The terminal within which the distribution limit and the overflow allowance applies.\\n @member token The token for which the fund access constraints apply.\\n @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.\\n @member distributionLimitCurrency The currency of the distribution limit.\\n @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.\\n @member overflowAllowanceCurrency The currency of the overflow allowance.\\n*/\\nstruct JBFundAccessConstraints {\\n IJBPaymentTerminal terminal;\\n address token;\\n uint256 distributionLimit;\\n uint256 distributionLimitCurrency;\\n uint256 overflowAllowance;\\n uint256 overflowAllowanceCurrency;\\n}\\n\",\"keccak256\":\"0x85ebaa57b788cbdedc7a3d0eec4892eda5d79db7c1a6103797f10d0d989775b2\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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.\\n @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.\\n @member basedOn The `configuration` of the funding cycle that was active when this cycle was created.\\n @member start The timestamp marking the moment from which the funding cycle is considered active. It is a unix timestamp measured in seconds.\\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n @member metadata Extra data that can be associated with a funding cycle.\\n*/\\nstruct JBFundingCycle {\\n uint256 number;\\n uint256 configuration;\\n uint256 basedOn;\\n uint256 start;\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n uint256 metadata;\\n}\\n\",\"keccak256\":\"0xcdd3ac9b6fa67e62ada88d09b73bc35ade1cd77d43db712289266a788928b4c2\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycleData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n*/\\nstruct JBFundingCycleData {\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n}\\n\",\"keccak256\":\"0x2aa6368bf4dfc5797e8b02a978293de0c777fae2658de2c825a103587240f3b0\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycleMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBGlobalFundingCycleMetadata.sol';\\n\\n/** \\n @member global Data used globally in non-migratable ecosystem contracts.\\n @member reservedRate The reserved rate of the funding cycle. This number is a percentage calculated out of `JBConstants.MAX_RESERVED_RATE`.\\n @member redemptionRate The redemption rate of the funding cycle. This number is a percentage calculated out of `JBConstants.MAX_REDEMPTION_RATE`.\\n @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`.\\n @member pausePay A flag indicating if the pay functionality should be paused during the funding cycle.\\n @member pauseDistributions A flag indicating if the distribute functionality should be paused during the funding cycle.\\n @member pauseRedeem A flag indicating if the redeem functionality should be paused during the funding cycle.\\n @member pauseBurn A flag indicating if the burn functionality should be paused during the funding cycle.\\n @member allowMinting A flag indicating if minting tokens should be allowed during this funding cycle.\\n @member allowTerminalMigration A flag indicating if migrating terminals should be allowed during this funding cycle.\\n @member allowControllerMigration A flag indicating if migrating controllers should be allowed during this funding cycle.\\n @member holdFees A flag indicating if fees should be held during this funding cycle.\\n @member preferClaimedTokenOverride A flag indicating if claimed tokens should always be prefered to unclaimed tokens when minting.\\n @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.\\n @member useDataSourceForPay A flag indicating if the data source should be used for pay transactions during this funding cycle.\\n @member useDataSourceForRedeem A flag indicating if the data source should be used for redeem transactions during this funding cycle.\\n @member dataSource The data source to use during this funding cycle.\\n @member metadata Metadata of the metadata, up to uint8 in size.\\n*/\\nstruct JBFundingCycleMetadata {\\n JBGlobalFundingCycleMetadata global;\\n uint256 reservedRate;\\n uint256 redemptionRate;\\n uint256 ballotRedemptionRate;\\n bool pausePay;\\n bool pauseDistributions;\\n bool pauseRedeem;\\n bool pauseBurn;\\n bool allowMinting;\\n bool allowTerminalMigration;\\n bool allowControllerMigration;\\n bool holdFees;\\n bool preferClaimedTokenOverride;\\n bool useTotalOverflowForRedemptions;\\n bool useDataSourceForPay;\\n bool useDataSourceForRedeem;\\n address dataSource;\\n uint256 metadata;\\n}\\n\",\"keccak256\":\"0x783604440cac8d176332eab28166f188ee5c230378c08cfc95fea4f7187dc77d\",\"license\":\"MIT\"},\"contracts/structs/JBGlobalFundingCycleMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member allowSetTerminals A flag indicating if setting terminals should be allowed during this funding cycle.\\n @member allowSetController A flag indicating if setting a new controller should be allowed during this funding cycle.\\n @member pauseTransfers A flag indicating if the project token transfer functionality should be paused during the funding cycle.\\n*/\\nstruct JBGlobalFundingCycleMetadata {\\n bool allowSetTerminals;\\n bool allowSetController;\\n bool pauseTransfers;\\n}\\n\",\"keccak256\":\"0x05d85530305fec6d6eca54cdbc2cd9110cbda0146598032b0203aa4b622944ff\",\"license\":\"MIT\"},\"contracts/structs/JBGroupedSplits.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBSplit.sol';\\n\\n/** \\n @member group The group indentifier.\\n @member splits The splits to associate with the group.\\n*/\\nstruct JBGroupedSplits {\\n uint256 group;\\n JBSplit[] splits;\\n}\\n\",\"keccak256\":\"0x80be1b220da4ac04851ea540ebb94c1ec2b0442ec5bd1e88fdf78a56becd8b5a\",\"license\":\"MIT\"},\"contracts/structs/JBPayDelegateAllocation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '../interfaces/IJBPayDelegate.sol';\\n\\n/** \\n @member delegate A delegate contract to use for subsequent calls.\\n @member amount The amount to send to the delegate.\\n*/\\nstruct JBPayDelegateAllocation {\\n IJBPayDelegate delegate;\\n uint256 amount;\\n}\\n\",\"keccak256\":\"0xb4e558dc62231d89e9b48998012577d22c3e52b58e23401f22d9096827f6ea0c\",\"license\":\"MIT\"},\"contracts/structs/JBPayParamsData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBPaymentTerminal.sol';\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member terminal The terminal that is facilitating the payment.\\n @member payer The address from which the payment originated.\\n @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.\\n @member projectId The ID of the project being paid.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the payment is being made.\\n @member beneficiary The specified address that should be the beneficiary of anything that results from the payment.\\n @member weight The weight of the funding cycle during which the payment is being made.\\n @member reservedRate The reserved rate of the funding cycle during which the payment is being made.\\n @member memo The memo that was sent alongside the payment.\\n @member metadata Extra data provided by the payer.\\n*/\\nstruct JBPayParamsData {\\n IJBPaymentTerminal terminal;\\n address payer;\\n JBTokenAmount amount;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n address beneficiary;\\n uint256 weight;\\n uint256 reservedRate;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0x05007b26feb5d9a026b883c6d734a341b5a49ef7b8215fb40507882e2c14e24d\",\"license\":\"MIT\"},\"contracts/structs/JBProjectMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member content The metadata content.\\n @member domain The domain within which the metadata applies.\\n*/\\nstruct JBProjectMetadata {\\n string content;\\n uint256 domain;\\n}\\n\",\"keccak256\":\"0x90ad7b1014c0a9f945fe7a2efde9d5de41e40574fa27969070b1d2ff52033ea0\",\"license\":\"MIT\"},\"contracts/structs/JBRedeemParamsData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBPaymentTerminal.sol';\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member terminal The terminal that is facilitating the redemption.\\n @member holder The holder of the tokens being redeemed.\\n @member projectId The ID of the project whos tokens are being redeemed.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the redemption is being made.\\n @member tokenCount The proposed number of tokens being redeemed, as a fixed point number with 18 decimals.\\n @member totalSupply The total supply of tokens used in the calculation, as a fixed point number with 18 decimals.\\n @member overflow The amount of overflow used in the reclaim amount calculation.\\n @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.\\n @member useTotalOverflow If overflow across all of a project's terminals is being used when making redemptions.\\n @member redemptionRate The redemption rate of the funding cycle during which the redemption is being made.\\n @member memo The proposed memo that is being emitted alongside the redemption.\\n @member metadata Extra data provided by the redeemer.\\n*/\\nstruct JBRedeemParamsData {\\n IJBPaymentTerminal terminal;\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 tokenCount;\\n uint256 totalSupply;\\n uint256 overflow;\\n JBTokenAmount reclaimAmount;\\n bool useTotalOverflow;\\n uint256 redemptionRate;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0x5065a824ebb34952f016c6dfa47e8a7ac28427b719470e74a41022c11ace7788\",\"license\":\"MIT\"},\"contracts/structs/JBRedemptionDelegateAllocation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '../interfaces/IJBRedemptionDelegate.sol';\\n\\n/** \\n @member delegate A delegate contract to use for subsequent calls.\\n @member amount The amount to send to the delegate.\\n*/\\nstruct JBRedemptionDelegateAllocation {\\n IJBRedemptionDelegate delegate;\\n uint256 amount;\\n}\\n\",\"keccak256\":\"0x10c29d33dd0d875a0d4692a2b9a9355c2ebf433cc06a9a60253d4366b60d4d31\",\"license\":\"MIT\"},\"contracts/structs/JBSplit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBSplitAllocator.sol';\\n\\n/** \\n @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.\\n @member preferAddToBalance A flag indicating if a distribution to a project should prefer triggering it's addToBalance function instead of its pay function.\\n @member percent The percent of the whole group that this split occupies. This number is out of `JBConstants.SPLITS_TOTAL_PERCENT`.\\n @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.\\n @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.\\n @member lockedUntil Specifies if the split should be unchangeable until the specified time, with the exception of extending the locked period.\\n @member allocator If an allocator is specified, funds will be sent to the allocator contract along with all properties of this split.\\n*/\\nstruct JBSplit {\\n bool preferClaimed;\\n bool preferAddToBalance;\\n uint256 percent;\\n uint256 projectId;\\n address payable beneficiary;\\n uint256 lockedUntil;\\n IJBSplitAllocator allocator;\\n}\\n\",\"keccak256\":\"0xc80a16606da8abf76d0f73abc38aee041e24f29342c1939018f70c286e89f105\",\"license\":\"MIT\"},\"contracts/structs/JBSplitAllocationData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBSplit.sol';\\n\\n/** \\n @member token The token being sent to the split allocator.\\n @member amount The amount being sent to the split allocator, as a fixed point number.\\n @member decimals The number of decimals in the amount.\\n @member projectId The project to which the split belongs.\\n @member group The group to which the split belongs.\\n @member split The split that caused the allocation.\\n*/\\nstruct JBSplitAllocationData {\\n address token;\\n uint256 amount;\\n uint256 decimals;\\n uint256 projectId;\\n uint256 group;\\n JBSplit split;\\n}\\n\",\"keccak256\":\"0x39f5c41bd31d36774744698ac94484b6cab62d7038df2f29d947668959782e63\",\"license\":\"MIT\"},\"contracts/structs/JBTokenAmount.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/* \\n @member token The token the payment was made in.\\n @member value The amount of tokens that was paid, as a fixed point number.\\n @member decimals The number of decimals included in the value fixed point number.\\n @member currency The expected currency of the value.\\n**/\\nstruct JBTokenAmount {\\n address token;\\n uint256 value;\\n uint256 decimals;\\n uint256 currency;\\n}\\n\",\"keccak256\":\"0x4a778e779ba257ba5638c5469e07a4d21b55a3128d56db5a0fdfacb1f3301c51\",\"license\":\"MIT\"},\"prb-math/contracts/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivFixedPointOverflow(uint256 prod1);\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivOverflow(uint256 prod1, uint256 denominator);\\n\\n/// @notice Emitted when one of the inputs is type(int256).min.\\nerror PRBMath__MulDivSignedInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows int256.\\nerror PRBMath__MulDivSignedOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is MIN_SD59x18.\\nerror PRBMathSD59x18__AbsInputTooSmall();\\n\\n/// @notice Emitted when ceiling a number overflows SD59x18.\\nerror PRBMathSD59x18__CeilOverflow(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__DivInputTooSmall();\\n\\n/// @notice Emitted when one of the intermediary unsigned results overflows SD59x18.\\nerror PRBMathSD59x18__DivOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathSD59x18__ExpInputTooBig(int256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathSD59x18__Exp2InputTooBig(int256 x);\\n\\n/// @notice Emitted when flooring a number underflows SD59x18.\\nerror PRBMathSD59x18__FloorUnderflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format overflows SD59x18.\\nerror PRBMathSD59x18__FromIntOverflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format underflows SD59x18.\\nerror PRBMathSD59x18__FromIntUnderflow(int256 x);\\n\\n/// @notice Emitted when the product of the inputs is negative.\\nerror PRBMathSD59x18__GmNegativeProduct(int256 x, int256 y);\\n\\n/// @notice Emitted when multiplying the inputs overflows SD59x18.\\nerror PRBMathSD59x18__GmOverflow(int256 x, int256 y);\\n\\n/// @notice Emitted when the input is less than or equal to zero.\\nerror PRBMathSD59x18__LogInputTooSmall(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__MulInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__MulOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__PowuOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is negative.\\nerror PRBMathSD59x18__SqrtNegativeInput(int256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows SD59x18.\\nerror PRBMathSD59x18__SqrtOverflow(int256 x);\\n\\n/// @notice Emitted when addition overflows UD60x18.\\nerror PRBMathUD60x18__AddOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when ceiling a number overflows UD60x18.\\nerror PRBMathUD60x18__CeilOverflow(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathUD60x18__ExpInputTooBig(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathUD60x18__Exp2InputTooBig(uint256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format format overflows UD60x18.\\nerror PRBMathUD60x18__FromUintOverflow(uint256 x);\\n\\n/// @notice Emitted when multiplying the inputs overflows UD60x18.\\nerror PRBMathUD60x18__GmOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when the input is less than 1.\\nerror PRBMathUD60x18__LogInputTooSmall(uint256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows UD60x18.\\nerror PRBMathUD60x18__SqrtOverflow(uint256 x);\\n\\n/// @notice Emitted when subtraction underflows UD60x18.\\nerror PRBMathUD60x18__SubUnderflow(uint256 x, uint256 y);\\n\\n/// @dev Common mathematical functions used in both PRBMathSD59x18 and PRBMathUD60x18. Note that this shared library\\n/// does not always assume the signed 59.18-decimal fixed-point or the unsigned 60.18-decimal fixed-point\\n/// representation. When it does not, it is explicitly mentioned in the NatSpec documentation.\\nlibrary PRBMath {\\n /// STRUCTS ///\\n\\n struct SD59x18 {\\n int256 value;\\n }\\n\\n struct UD60x18 {\\n uint256 value;\\n }\\n\\n /// STORAGE ///\\n\\n /// @dev How many trailing decimals can be represented.\\n uint256 internal constant SCALE = 1e18;\\n\\n /// @dev Largest power of two divisor of SCALE.\\n uint256 internal constant SCALE_LPOTD = 262144;\\n\\n /// @dev SCALE inverted mod 2^256.\\n uint256 internal constant SCALE_INVERSE =\\n 78156646155174841979727994598816262306175212592076161876661_508869554232690281;\\n\\n /// FUNCTIONS ///\\n\\n /// @notice Calculates the binary exponent of x using the binary fraction method.\\n /// @dev Has to use 192.64-bit fixed-point numbers.\\n /// See https://ethereum.stackexchange.com/a/96594/24693.\\n /// @param x The exponent as an unsigned 192.64-bit fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp2(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n // Start from 0.5 in the 192.64-bit fixed-point format.\\n result = 0x800000000000000000000000000000000000000000000000;\\n\\n // Multiply the result by root(2, 2^-i) when the bit at position i is 1. None of the intermediary results overflows\\n // because the initial result is 2^191 and all magic factors are less than 2^65.\\n if (x & 0x8000000000000000 > 0) {\\n result = (result * 0x16A09E667F3BCC909) >> 64;\\n }\\n if (x & 0x4000000000000000 > 0) {\\n result = (result * 0x1306FE0A31B7152DF) >> 64;\\n }\\n if (x & 0x2000000000000000 > 0) {\\n result = (result * 0x1172B83C7D517ADCE) >> 64;\\n }\\n if (x & 0x1000000000000000 > 0) {\\n result = (result * 0x10B5586CF9890F62A) >> 64;\\n }\\n if (x & 0x800000000000000 > 0) {\\n result = (result * 0x1059B0D31585743AE) >> 64;\\n }\\n if (x & 0x400000000000000 > 0) {\\n result = (result * 0x102C9A3E778060EE7) >> 64;\\n }\\n if (x & 0x200000000000000 > 0) {\\n result = (result * 0x10163DA9FB33356D8) >> 64;\\n }\\n if (x & 0x100000000000000 > 0) {\\n result = (result * 0x100B1AFA5ABCBED61) >> 64;\\n }\\n if (x & 0x80000000000000 > 0) {\\n result = (result * 0x10058C86DA1C09EA2) >> 64;\\n }\\n if (x & 0x40000000000000 > 0) {\\n result = (result * 0x1002C605E2E8CEC50) >> 64;\\n }\\n if (x & 0x20000000000000 > 0) {\\n result = (result * 0x100162F3904051FA1) >> 64;\\n }\\n if (x & 0x10000000000000 > 0) {\\n result = (result * 0x1000B175EFFDC76BA) >> 64;\\n }\\n if (x & 0x8000000000000 > 0) {\\n result = (result * 0x100058BA01FB9F96D) >> 64;\\n }\\n if (x & 0x4000000000000 > 0) {\\n result = (result * 0x10002C5CC37DA9492) >> 64;\\n }\\n if (x & 0x2000000000000 > 0) {\\n result = (result * 0x1000162E525EE0547) >> 64;\\n }\\n if (x & 0x1000000000000 > 0) {\\n result = (result * 0x10000B17255775C04) >> 64;\\n }\\n if (x & 0x800000000000 > 0) {\\n result = (result * 0x1000058B91B5BC9AE) >> 64;\\n }\\n if (x & 0x400000000000 > 0) {\\n result = (result * 0x100002C5C89D5EC6D) >> 64;\\n }\\n if (x & 0x200000000000 > 0) {\\n result = (result * 0x10000162E43F4F831) >> 64;\\n }\\n if (x & 0x100000000000 > 0) {\\n result = (result * 0x100000B1721BCFC9A) >> 64;\\n }\\n if (x & 0x80000000000 > 0) {\\n result = (result * 0x10000058B90CF1E6E) >> 64;\\n }\\n if (x & 0x40000000000 > 0) {\\n result = (result * 0x1000002C5C863B73F) >> 64;\\n }\\n if (x & 0x20000000000 > 0) {\\n result = (result * 0x100000162E430E5A2) >> 64;\\n }\\n if (x & 0x10000000000 > 0) {\\n result = (result * 0x1000000B172183551) >> 64;\\n }\\n if (x & 0x8000000000 > 0) {\\n result = (result * 0x100000058B90C0B49) >> 64;\\n }\\n if (x & 0x4000000000 > 0) {\\n result = (result * 0x10000002C5C8601CC) >> 64;\\n }\\n if (x & 0x2000000000 > 0) {\\n result = (result * 0x1000000162E42FFF0) >> 64;\\n }\\n if (x & 0x1000000000 > 0) {\\n result = (result * 0x10000000B17217FBB) >> 64;\\n }\\n if (x & 0x800000000 > 0) {\\n result = (result * 0x1000000058B90BFCE) >> 64;\\n }\\n if (x & 0x400000000 > 0) {\\n result = (result * 0x100000002C5C85FE3) >> 64;\\n }\\n if (x & 0x200000000 > 0) {\\n result = (result * 0x10000000162E42FF1) >> 64;\\n }\\n if (x & 0x100000000 > 0) {\\n result = (result * 0x100000000B17217F8) >> 64;\\n }\\n if (x & 0x80000000 > 0) {\\n result = (result * 0x10000000058B90BFC) >> 64;\\n }\\n if (x & 0x40000000 > 0) {\\n result = (result * 0x1000000002C5C85FE) >> 64;\\n }\\n if (x & 0x20000000 > 0) {\\n result = (result * 0x100000000162E42FF) >> 64;\\n }\\n if (x & 0x10000000 > 0) {\\n result = (result * 0x1000000000B17217F) >> 64;\\n }\\n if (x & 0x8000000 > 0) {\\n result = (result * 0x100000000058B90C0) >> 64;\\n }\\n if (x & 0x4000000 > 0) {\\n result = (result * 0x10000000002C5C860) >> 64;\\n }\\n if (x & 0x2000000 > 0) {\\n result = (result * 0x1000000000162E430) >> 64;\\n }\\n if (x & 0x1000000 > 0) {\\n result = (result * 0x10000000000B17218) >> 64;\\n }\\n if (x & 0x800000 > 0) {\\n result = (result * 0x1000000000058B90C) >> 64;\\n }\\n if (x & 0x400000 > 0) {\\n result = (result * 0x100000000002C5C86) >> 64;\\n }\\n if (x & 0x200000 > 0) {\\n result = (result * 0x10000000000162E43) >> 64;\\n }\\n if (x & 0x100000 > 0) {\\n result = (result * 0x100000000000B1721) >> 64;\\n }\\n if (x & 0x80000 > 0) {\\n result = (result * 0x10000000000058B91) >> 64;\\n }\\n if (x & 0x40000 > 0) {\\n result = (result * 0x1000000000002C5C8) >> 64;\\n }\\n if (x & 0x20000 > 0) {\\n result = (result * 0x100000000000162E4) >> 64;\\n }\\n if (x & 0x10000 > 0) {\\n result = (result * 0x1000000000000B172) >> 64;\\n }\\n if (x & 0x8000 > 0) {\\n result = (result * 0x100000000000058B9) >> 64;\\n }\\n if (x & 0x4000 > 0) {\\n result = (result * 0x10000000000002C5D) >> 64;\\n }\\n if (x & 0x2000 > 0) {\\n result = (result * 0x1000000000000162E) >> 64;\\n }\\n if (x & 0x1000 > 0) {\\n result = (result * 0x10000000000000B17) >> 64;\\n }\\n if (x & 0x800 > 0) {\\n result = (result * 0x1000000000000058C) >> 64;\\n }\\n if (x & 0x400 > 0) {\\n result = (result * 0x100000000000002C6) >> 64;\\n }\\n if (x & 0x200 > 0) {\\n result = (result * 0x10000000000000163) >> 64;\\n }\\n if (x & 0x100 > 0) {\\n result = (result * 0x100000000000000B1) >> 64;\\n }\\n if (x & 0x80 > 0) {\\n result = (result * 0x10000000000000059) >> 64;\\n }\\n if (x & 0x40 > 0) {\\n result = (result * 0x1000000000000002C) >> 64;\\n }\\n if (x & 0x20 > 0) {\\n result = (result * 0x10000000000000016) >> 64;\\n }\\n if (x & 0x10 > 0) {\\n result = (result * 0x1000000000000000B) >> 64;\\n }\\n if (x & 0x8 > 0) {\\n result = (result * 0x10000000000000006) >> 64;\\n }\\n if (x & 0x4 > 0) {\\n result = (result * 0x10000000000000003) >> 64;\\n }\\n if (x & 0x2 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n if (x & 0x1 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n\\n // We're doing two things at the same time:\\n //\\n // 1. Multiply the result by 2^n + 1, where \\\"2^n\\\" is the integer part and the one is added to account for\\n // the fact that we initially set the result to 0.5. This is accomplished by subtracting from 191\\n // rather than 192.\\n // 2. Convert the result to the unsigned 60.18-decimal fixed-point format.\\n //\\n // This works because 2^(191-ip) = 2^ip / 2^191, where \\\"ip\\\" is the integer part \\\"2^n\\\".\\n result *= SCALE;\\n result >>= (191 - (x >> 64));\\n }\\n }\\n\\n /// @notice Finds the zero-based index of the first one in the binary representation of x.\\n /// @dev See the note on msb in the \\\"Find First Set\\\" Wikipedia article https://en.wikipedia.org/wiki/Find_first_set\\n /// @param x The uint256 number for which to find the index of the most significant bit.\\n /// @return msb The index of the most significant bit as an uint256.\\n function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\\n if (x >= 2**128) {\\n x >>= 128;\\n msb += 128;\\n }\\n if (x >= 2**64) {\\n x >>= 64;\\n msb += 64;\\n }\\n if (x >= 2**32) {\\n x >>= 32;\\n msb += 32;\\n }\\n if (x >= 2**16) {\\n x >>= 16;\\n msb += 16;\\n }\\n if (x >= 2**8) {\\n x >>= 8;\\n msb += 8;\\n }\\n if (x >= 2**4) {\\n x >>= 4;\\n msb += 4;\\n }\\n if (x >= 2**2) {\\n x >>= 2;\\n msb += 2;\\n }\\n if (x >= 2**1) {\\n // No need to shift x any more.\\n msb += 1;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.\\n ///\\n /// Requirements:\\n /// - The denominator cannot be zero.\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The multiplicand as an uint256.\\n /// @param y The multiplier as an uint256.\\n /// @param denominator The divisor as an uint256.\\n /// @return result The result as an uint256.\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n unchecked {\\n result = prod0 / denominator;\\n }\\n return result;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n if (prod1 >= denominator) {\\n revert PRBMath__MulDivOverflow(prod1, denominator);\\n }\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n unchecked {\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 lpotdod = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by lpotdod.\\n denominator := div(denominator, lpotdod)\\n\\n // Divide [prod1 prod0] by lpotdod.\\n prod0 := div(prod0, lpotdod)\\n\\n // Flip lpotdod such that it is 2^256 / lpotdod. If lpotdod is zero, then it becomes one.\\n lpotdod := add(div(sub(0, lpotdod), lpotdod), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * lpotdod;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f71e18) with full precision.\\n ///\\n /// @dev Variant of \\\"mulDiv\\\" with constant folding, i.e. in which the denominator is always 1e18. Before returning the\\n /// final result, we add 1 if (x * y) % SCALE >= HALF_SCALE. Without this, 6.6e-19 would be truncated to 0 instead of\\n /// being rounded to 1e-18. See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717.\\n ///\\n /// Requirements:\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - The body is purposely left uncommented; see the NatSpec comments in \\\"PRBMath.mulDiv\\\" to understand how this works.\\n /// - It is assumed that the result can never be type(uint256).max when x and y solve the following two equations:\\n /// 1. x * y = type(uint256).max * SCALE\\n /// 2. (x * y) % SCALE >= SCALE / 2\\n ///\\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function mulDivFixedPoint(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n uint256 prod0;\\n uint256 prod1;\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n if (prod1 >= SCALE) {\\n revert PRBMath__MulDivFixedPointOverflow(prod1);\\n }\\n\\n uint256 remainder;\\n uint256 roundUpUnit;\\n assembly {\\n remainder := mulmod(x, y, SCALE)\\n roundUpUnit := gt(remainder, 499999999999999999)\\n }\\n\\n if (prod1 == 0) {\\n unchecked {\\n result = (prod0 / SCALE) + roundUpUnit;\\n return result;\\n }\\n }\\n\\n assembly {\\n result := add(\\n mul(\\n or(\\n div(sub(prod0, remainder), SCALE_LPOTD),\\n mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, SCALE_LPOTD), SCALE_LPOTD), 1))\\n ),\\n SCALE_INVERSE\\n ),\\n roundUpUnit\\n )\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev An extension of \\\"mulDiv\\\" for signed numbers. Works by computing the signs and the absolute values separately.\\n ///\\n /// Requirements:\\n /// - None of the inputs can be type(int256).min.\\n /// - The result must fit within int256.\\n ///\\n /// @param x The multiplicand as an int256.\\n /// @param y The multiplier as an int256.\\n /// @param denominator The divisor as an int256.\\n /// @return result The result as an int256.\\n function mulDivSigned(\\n int256 x,\\n int256 y,\\n int256 denominator\\n ) internal pure returns (int256 result) {\\n if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {\\n revert PRBMath__MulDivSignedInputTooSmall();\\n }\\n\\n // Get hold of the absolute values of x, y and the denominator.\\n uint256 ax;\\n uint256 ay;\\n uint256 ad;\\n unchecked {\\n ax = x < 0 ? uint256(-x) : uint256(x);\\n ay = y < 0 ? uint256(-y) : uint256(y);\\n ad = denominator < 0 ? uint256(-denominator) : uint256(denominator);\\n }\\n\\n // Compute the absolute value of (x*y)\\u00f7denominator. The result must fit within int256.\\n uint256 rAbs = mulDiv(ax, ay, ad);\\n if (rAbs > uint256(type(int256).max)) {\\n revert PRBMath__MulDivSignedOverflow(rAbs);\\n }\\n\\n // Get the signs of x, y and the denominator.\\n uint256 sx;\\n uint256 sy;\\n uint256 sd;\\n assembly {\\n sx := sgt(x, sub(0, 1))\\n sy := sgt(y, sub(0, 1))\\n sd := sgt(denominator, sub(0, 1))\\n }\\n\\n // XOR over sx, sy and sd. This is checking whether there are one or three negative signs in the inputs.\\n // If yes, the result should be negative.\\n result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs);\\n }\\n\\n /// @notice Calculates the square root of x, rounding down.\\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The uint256 number for which to calculate the square root.\\n /// @return result The result as an uint256.\\n function sqrt(uint256 x) internal pure returns (uint256 result) {\\n if (x == 0) {\\n return 0;\\n }\\n\\n // Set the initial guess to the closest power of two that is higher than x.\\n uint256 xAux = uint256(x);\\n result = 1;\\n if (xAux >= 0x100000000000000000000000000000000) {\\n xAux >>= 128;\\n result <<= 64;\\n }\\n if (xAux >= 0x10000000000000000) {\\n xAux >>= 64;\\n result <<= 32;\\n }\\n if (xAux >= 0x100000000) {\\n xAux >>= 32;\\n result <<= 16;\\n }\\n if (xAux >= 0x10000) {\\n xAux >>= 16;\\n result <<= 8;\\n }\\n if (xAux >= 0x100) {\\n xAux >>= 8;\\n result <<= 4;\\n }\\n if (xAux >= 0x10) {\\n xAux >>= 4;\\n result <<= 2;\\n }\\n if (xAux >= 0x8) {\\n result <<= 1;\\n }\\n\\n // The operations can never overflow because the result is max 2^127 when it enters this block.\\n unchecked {\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1; // Seven iterations should be enough\\n uint256 roundedDownResult = x / result;\\n return result >= roundedDownResult ? roundedDownResult : result;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x62cbabae4910e168e99b9c2c3e3b5c9c7ad5e7abd961dcc63b7ea3d83d8ea87e\",\"license\":\"Unlicense\"}},\"version\":1}", "bytecode": "0x60e06040523480156200001157600080fd5b5060405162003b6838038062003b68833981016040819052620000349162000070565b60016000556001600160a01b0392831660805290821660a0521660c052620000c4565b6001600160a01b03811681146200006d57600080fd5b50565b6000806000606084860312156200008657600080fd5b8351620000938162000057565b6020850151909350620000a68162000057565b6040850151909250620000b98162000057565b809150509250925092565b60805160a05160c0516139e862000180600039600081816102630152818161079101528181610e0b015281816126ac01526128bb01526000818161018b0152818161040e015281816109ca01528181610f580152818161113a015281816115ab015281816118a70152818161198901528181611dc201528181612201015261295b015260008181610229015281816104be0152818161139301528181611b8401528181611eb401528181612494015261274101526139e86000f3fe608060405234801561001057600080fd5b50600436106100ff5760003560e01c8063c294b2f411610097578063d49031c011610066578063d49031c014610285578063d4c3a8d214610298578063e7c8e3e3146102c9578063e8ba563a146102de57600080fd5b8063c294b2f414610211578063c41c2f2414610224578063c66445971461024b578063d3419bf31461025e57600080fd5b80636bb6a5ad116100d35780636bb6a5ad146101c5578063a2df1f95146101d8578063a57c7f59146101eb578063b753d7e9146101fe57600080fd5b8062fdd58e1461010457806325386715146101425780632fa1b39114610163578063557e715514610186575b600080fd5b61012f610112366004612b19565b600160209081526000928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b610155610150366004612b45565b61030f565b604051610139929190612b71565b610176610171366004612d68565b6108cd565b6040516101399493929190612e79565b6101ad7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610139565b61012f6101d3366004612f56565b610eb4565b6101766101e6366004612f6f565b61103d565b61012f6101f9366004613010565b611853565b61012f61020c366004612b45565b611936565b61012f61021f366004613042565b61194d565b6101ad7f000000000000000000000000000000000000000000000000000000000000000081565b610155610259366004612b45565b611cc8565b6101ad7f000000000000000000000000000000000000000000000000000000000000000081565b61012f610293366004612b19565b6121f8565b61012f6102a6366004613091565b600360209081526000938452604080852082529284528284209052825290205481565b6102dc6102d73660046130c6565b6122d6565b005b61012f6102ec366004613091565b600260209081526000938452604080852082529284528284209052825290205481565b6103676040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b60006002600054036103da576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b60026000556040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018690527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa15801561045e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061048291906130f8565b3360009081526003602090815260408083208984528252808320828501518452909152812054919350906104b79086906131a7565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635dd8f6aa896040518263ffffffff1660e01b815260040161050a91815260200190565b602060405180830381865afa158015610527573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061054b91906131ba565b6001600160a01b0316637a81b56289876020015133336001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561059e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105c291906131ba565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e087901b168152600481019490945260248401929092526001600160a01b0390811660448401521660648201526084016040805180830381865afa158015610633573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065791906131d7565b9150915081831180610667575081155b1561069e576040517fb6ecab1200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8086146106d7576040517fe56ea4e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000336001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610717573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061073b91906131fb565b905080871461080f5761080a886107546012600a613334565b6040517fa4d0caf2000000000000000000000000000000000000000000000000000000008152600481018b905260248101859052601260448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a4d0caf2906064015b602060405180830381865afa1580156107e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061080591906131fb565b61231f565b610811565b875b945061081f338a8884612423565b851115610858576040517f2fca7ece00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360008181526003602090815260408083208d845282528083208a83015184528252808320889055928252600181528282208c83529052205461089c908690613340565b3360009081526001602081815260408084209d84529c90529a81209190915598909855509296919550909350505050565b6109256040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b6000606080600260005403610996576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103d1565b60026000556040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018b90527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa158015610a1a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3e91906130f8565b8051909450600003610a7c576040517f2e96671a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61010084015160481c600190811603610ac1576040517fa3bb913300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61010084015160009060521c6001908116148015610af757506000610aeb86610100015160541c90565b6001600160a01b031614155b15610c49576000604051806101400160405280336001600160a01b031681526020018f6001600160a01b031681526020018e803603810190610b399190613353565b815260208082018f905288015160408201526001600160a01b038c16606082015260a080890151608083015261010089015191019060181c61ffff1681526020018a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050908252506020018890529050610bca86610100015160541c90565b6001600160a01b031663d46cf171826040518263ffffffff1660e01b8152600401610bf591906133c2565b6000604051808303816000875af1158015610c14573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610c3c9190810190613530565b955093509150610c8a9050565b8460a00151905087878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294505050505b825160208d01359015610d1f5760005b8451811015610d1d576000858281518110610cb757610cb7613621565b602002602001015160200151905080600014610d145782811115610d07576040517f6d51b52600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d118184613340565b92505b50600101610c9a565b505b8c60200135600003610d37575060009350610e9d9050565b8015610d9e573360009081526001602090815260408083208f8452909152902054610d639082906131a7565b60016000336001600160a01b03166001600160a01b0316815260200190815260200160002060008e8152602001908152602001600020819055505b5080600003610db1575060009250610e9d565b60408c0135600060608e01358c14610e7b576040517fa4d0caf200000000000000000000000000000000000000000000000000000000815260608f01356004820152602481018d9052604481018390526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a4d0caf290606401602060405180830381865afa158015610e52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7691906131fb565b610e86565b610e8682600a613334565b9050610e978e60200135848361231f565b95505050505b600160008190555098509850985098945050505050565b6000600260005403610f22576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103d1565b600260009081556040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa158015610fa8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fcc91906130f8565b610100810151909150604d1c600190811614611014576040517fe7c9e0be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505033600090815260016020818152604080842094845293905291812080549082905591905590565b6110956040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b6000606080600260005403611106576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103d1565b60026000556040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa15801561118a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ae91906130f8565b610100810151909450604a1c6001908116036111f6576040517fa97cf58f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61122a604051806080016040528060006001600160a01b031681526020016000815260200160008152602001600081525090565b6000806000336001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561126d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061129191906131ba565b90506000336001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f791906131fb565b90506000336001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611339573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061135d91906131fb565b6101008b015190915060511c6001908116146113845761137f338f8c84612423565b61138f565b61138f8e8383612705565b94507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635dd8f6aa8f6040518263ffffffff1660e01b81526004016113df91815260200190565b602060405180830381865afa1580156113fc573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061142091906131ba565b6001600160a01b031663b5f1e34d8f6114458d610100015161ffff60189190911c1690565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815260048101929092526024820152604401602060405180830381865afa15801561149e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114c291906131fb565b9350838d11156114fe576040517fb8af220000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8415611514576115118e8b8f8789612919565b98505b604080516080810182526001600160a01b03949094168452602084018a9052830191909152606082015261010088015190935060531c60019081161480156115745750600061156888610100015160541c90565b6001600160a01b031614155b15611764576040517fc55f571c000000000000000000000000000000000000000000000000000000008152600481018c90526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c55f571c90602401602060405180830381865afa1580156115fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061161e9190613650565b90506000604051806101800160405280336001600160a01b031681526020018f6001600160a01b031681526020018e81526020018a6020015181526020018d815260200184815260200185815260200186815260200161168b8b6101000151600160519190911c81161490565b1515815260200160008460028111156116a6576116a6613671565b146116b9576116b48b612a6a565b6116c2565b6116c28b612a87565b81526020018c81526020018b81525090506116e289610100015160541c90565b6001600160a01b031663a51cfd18826040518263ffffffff1660e01b815260040161170d91906136a0565b6000604051808303816000875af115801561172c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611754919081019061379b565b9199509097509550611768915050565b8893505b50508251849150156117c25760005b83518110156117c057600084828151811061179457611794613621565b6020026020010151602001519050806000146117b7576117b481846131a7565b92505b50600101611777565b505b3360009081526001602090815260408083208c8452909152902054811115611816576040517f2fca7ece00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b801561183e573360009081526001602090815260408083208c84529091529020805482900390555b50600160008190555095509550955095915050565b6000816000036118655750600061192e565b828411156118755750600061192e565b6040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018690526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa1580156118f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061191b91906130f8565b905061192a8682878787612919565b9150505b949350505050565b6000611943848484612705565b90505b9392505050565b6040517f43a266c20000000000000000000000000000000000000000000000000000000081526004810184905260009081906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906343a266c29060240161012060405180830381865afa1580156119d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119f591906130f8565b9050600083611a7057611a6b8787848a6001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a6691906131fb565b612423565b611b3d565b611b3d86886001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ab2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ad691906131fb565b896001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b3891906131fb565b612705565b905080600003611b525760009250505061192e565b6040517f5dd8f6aa000000000000000000000000000000000000000000000000000000008152600481018790526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635dd8f6aa90602401602060405180830381865afa158015611bd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bf791906131ba565b6001600160a01b031663b5f1e34d88611c1c86610100015161ffff60189190911c1690565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815260048101929092526024820152604401602060405180830381865afa158015611c75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c9991906131fb565b905080861115611caf576000935050505061192e565b611cbc8784888486612919565b98975050505050505050565b611d206040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b6000600260005403611d8e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103d1565b60026000556040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018690527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa158015611e12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3691906130f8565b61010081015190925060491c600190811603611e7e576040517f861e9dcd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152600260209081526040808320888452825280832085518452909152812054611ead9086906131a7565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635dd8f6aa896040518263ffffffff1660e01b8152600401611f0091815260200190565b602060405180830381865afa158015611f1d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f4191906131ba565b6001600160a01b031663e8db213089876020015133336001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f94573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fb891906131ba565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e087901b168152600481019490945260248401929092526001600160a01b0390811660448401521660648201526084016040805180830381865afa158015612029573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204d91906131d7565b915091508183118061205d575081155b15612094576040517f08dae4ac00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8086146120cd576040517fe56ea4e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000336001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561210d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061213191906131fb565b905080871461214f5761214a886107546012600a613334565b612151565b875b3360009081526001602090815260408083208d84529091529020549095508511156121a8576040517f2fca7ece00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50503360008181526002602090815260408083208b845282528083208851845282528083209590955591815260018083528482209982529890915291822080548490039055509490945593915050565b60006122cd83837f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166343a266c2866040518263ffffffff1660e01b815260040161224d91815260200190565b61012060405180830381865afa15801561226b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061228f91906130f8565b866001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a42573d6000803e3d6000fd5b90505b92915050565b3360009081526001602090815260408083208584529091529020546122fc9082906131a7565b336000908152600160209081526040808320958352949052929092209190915550565b600080807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff858709858702925082811083820303915050806000036123775783828161236d5761236d61387c565b0492505050611946565b8381106123ba576040517f773cc18c00000000000000000000000000000000000000000000000000000000815260048101829052602481018590526044016103d1565b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b6001600160a01b038416600090815260016020908152604080832086845290915281205480820361245857600091505061192e565b6040517f5dd8f6aa0000000000000000000000000000000000000000000000000000000081526004810186905260009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690635dd8f6aa90602401602060405180830381865afa1580156124db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124ff91906131ba565b6001600160a01b031663e8db21308888602001518b8c6001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612552573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061257691906131ba565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e087901b168152600481019490945260248401929092526001600160a01b0390811660448401521660648201526084016040805180830381865afa1580156125e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061260b91906131d7565b6001600160a01b038a1660009081526002602090815260408083208c845282528083208b518452909152812054929450909250906126499084613340565b9050801580159061265a5750858214155b156126e6576126e38161266f6012600a613334565b6040517fa4d0caf200000000000000000000000000000000000000000000000000000000815260048101869052602481018a9052601260448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a4d0caf2906064016107c4565b90505b8084116126f45760006126f8565b8084035b9998505050505050505050565b6040517fd17541530000000000000000000000000000000000000000000000000000000081526004810184905260009081906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063d175415390602401600060405180830381865afa158015612788573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526127b091908101906138ab565b90506000805b825181101561285b578281815181106127d1576127d1613621565b60200260200101516001600160a01b031663a32e1e96886040518263ffffffff1660e01b815260040161280691815260200190565b602060405180830381865afa158015612823573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061284791906131fb565b61285190836131a7565b91506001016127b6565b506000600185146128ef576040517fa4d0caf20000000000000000000000000000000000000000000000000000000081526001600482015260248101869052601260448201526128ea908390670de0b6b3a7640000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a4d0caf2906064016107c4565b6128f1565b815b90508560121461290c5761290781601288612aa4565b61290e565b805b979650505050505050565b6000828403612929575080612a61565b6000806040517fc55f571c000000000000000000000000000000000000000000000000000000008152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c55f571c90602401602060405180830381865afa1580156129aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129ce9190613650565b60028111156129df576129df613671565b146129f2576129ed86612a6a565b6129fb565b6129fb86612a87565b905080600003612a0f576000915050612a61565b6000612a1c84878761231f565b90506127108203612a30579150612a619050565b612a5c81612a4a88612a4486612710613340565b8961231f565b612a5490856131a7565b61271061231f565b925050505b95945050505050565b60006028826101000151901c61ffff166127106122d09190613340565b60006038826101000151901c61ffff166127106122d09190613340565b6000828203612ab4575082611946565b82821115612ae257612ac68383613340565b612ad190600a613334565b612adb908561393a565b9050611946565b612aec8284613340565b612af790600a613334565b612adb9085613977565b6001600160a01b0381168114612b1657600080fd5b50565b60008060408385031215612b2c57600080fd5b8235612b3781612b01565b946020939093013593505050565b600080600060608486031215612b5a57600080fd5b505081359360208301359350604090920135919050565b6101408101612bde8285805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c08301526001600160a01b0360e08201511660e08301526101008082015181840152505050565b826101208301529392505050565b60008083601f840112612bfe57600080fd5b50813567ffffffffffffffff811115612c1657600080fd5b602083019150836020828501011115612c2e57600080fd5b9250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff81118282101715612c8857612c88612c35565b60405290565b6040805190810167ffffffffffffffff81118282101715612c8857612c88612c35565b604051601f8201601f1916810167ffffffffffffffff81118282101715612cda57612cda612c35565b604052919050565b600067ffffffffffffffff821115612cfc57612cfc612c35565b50601f01601f191660200190565b6000612d1d612d1884612ce2565b612cb1565b9050828152838383011115612d3157600080fd5b828260208301376000602084830101529392505050565b600082601f830112612d5957600080fd5b6122cd83833560208501612d0a565b600080600080600080600080888a03610140811215612d8657600080fd5b8935612d9181612b01565b98506080601f1982011215612da557600080fd5b5060208901965060a0890135955060c0890135945060e0890135612dc881612b01565b935061010089013567ffffffffffffffff80821115612de657600080fd5b612df28c838d01612bec565b90955093506101208b0135915080821115612e0c57600080fd5b50612e198b828c01612d48565b9150509295985092959890939650565b60005b83811015612e44578181015183820152602001612e2c565b50506000910152565b60008151808452612e65816020860160208601612e29565b601f01601f19169290920160200192915050565b6000610180808301612ee98489805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c08301526001600160a01b0360e08201511660e08301526101008082015181840152505050565b61012084018790526101408401919091528451908190526101a083019060209081870160005b82811015612f3f57815180516001600160a01b031686528401518486015260409094019390830190600101612f0f565b5050505082810361016084015261290e8185612e4d565b600060208284031215612f6857600080fd5b5035919050565b600080600080600060a08688031215612f8757600080fd5b8535612f9281612b01565b94506020860135935060408601359250606086013567ffffffffffffffff80821115612fbd57600080fd5b818801915088601f830112612fd157600080fd5b612fe089833560208501612d0a565b93506080880135915080821115612ff657600080fd5b5061300388828901612d48565b9150509295509295909350565b6000806000806080858703121561302657600080fd5b5050823594602084013594506040840135936060013592509050565b6000806000806080858703121561305857600080fd5b843561306381612b01565b935060208501359250604085013591506060850135801515811461308657600080fd5b939692955090935050565b6000806000606084860312156130a657600080fd5b83356130b181612b01565b95602085013595506040909401359392505050565b600080604083850312156130d957600080fd5b50508035926020909101359150565b80516130f381612b01565b919050565b6000610120828403121561310b57600080fd5b613113612c64565b825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015261315f60e084016130e8565b60e0820152610100928301519281019290925250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156122d0576122d0613178565b6000602082840312156131cc57600080fd5b815161194681612b01565b600080604083850312156131ea57600080fd5b505080516020909101519092909150565b60006020828403121561320d57600080fd5b5051919050565b600181815b8085111561326d57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561325357613253613178565b8085161561326057918102915b93841c9390800290613219565b509250929050565b600082613284575060016122d0565b81613291575060006122d0565b81600181146132a757600281146132b1576132cd565b60019150506122d0565b60ff8411156132c2576132c2613178565b50506001821b6122d0565b5060208310610133831016604e8410600b84101617156132f0575081810a6122d0565b6132fa8383613214565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561332c5761332c613178565b029392505050565b60006122cd8383613275565b818103818111156122d0576122d0613178565b60006080828403121561336557600080fd5b6040516080810181811067ffffffffffffffff8211171561338857613388612c35565b604052823561339681612b01565b808252506020830135602082015260408301356040820152606083013560608201528091505092915050565b602081526133dc6020820183516001600160a01b03169052565b600060208301516133f860408401826001600160a01b03169052565b50604083015161343560608401826001600160a01b0381511682526020810151602083015260408101516040830152606081015160608301525050565b50606083015160e08301526080830151610100818185015260a0850151915061012061346b818601846001600160a01b03169052565b60c086015161014086015260e08601516101608601528186015192506101a09150816101808601526134a16101c0860184612e4d565b90860151858203601f1901838701529092506134bd8382612e4d565b9695505050505050565b600082601f8301126134d857600080fd5b81516134e6612d1882612ce2565b8181528460208386010111156134fb57600080fd5b61192e826020830160208701612e29565b600067ffffffffffffffff82111561352657613526612c35565b5060051b60200190565b60008060006060848603121561354557600080fd5b8351925060208085015167ffffffffffffffff8082111561356557600080fd5b613571888389016134c7565b945060409150818701518181111561358857600080fd5b87019050601f8101881361359b57600080fd5b80516135a9612d188261350c565b81815260069190911b8201840190848101908a8311156135c857600080fd5b928501925b828410156136115784848c0312156135e55760008081fd5b6135ed612c8e565b84516135f881612b01565b81528487015187820152825292840192908501906135cd565b8096505050505050509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561366257600080fd5b81516003811061194657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b602081526136ba6020820183516001600160a01b03169052565b600060208301516136d660408401826001600160a01b03169052565b506040830151606083015260608301516080830152608083015160a083015260a083015160c083015260c083015160e083015260e0830151610100613747818501836001600160a01b0381511682526020810151602083015260408101516040830152606081015160608301525050565b8401511515610180840152506101208301516101a08301526101408301516101e06101c0840181905261377e610200850183612e4d565b9150610160850151601f1985840301828601526134bd8382612e4d565b6000806000606084860312156137b057600080fd5b8351925060208085015167ffffffffffffffff808211156137d057600080fd5b6137dc888389016134c7565b94506040915081870151818111156137f357600080fd5b87019050601f8101881361380657600080fd5b8051613814612d188261350c565b81815260069190911b8201840190848101908a83111561383357600080fd5b928501925b828410156136115784848c0312156138505760008081fd5b613858612c8e565b845161386381612b01565b8152848701518782015282529284019290850190613838565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600060208083850312156138be57600080fd5b825167ffffffffffffffff8111156138d557600080fd5b8301601f810185136138e657600080fd5b80516138f4612d188261350c565b81815260059190911b8201830190838101908783111561391357600080fd5b928401925b8284101561290e57835161392b81612b01565b82529284019290840190613918565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561397257613972613178565b500290565b6000826139ad577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b50049056fea2646970667358221220496c9f50e79f6514ca61a35b21fe271a2d4fe217f051df7336af8ae92911191e64736f6c63430008100033", "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100ff5760003560e01c8063c294b2f411610097578063d49031c011610066578063d49031c014610285578063d4c3a8d214610298578063e7c8e3e3146102c9578063e8ba563a146102de57600080fd5b8063c294b2f414610211578063c41c2f2414610224578063c66445971461024b578063d3419bf31461025e57600080fd5b80636bb6a5ad116100d35780636bb6a5ad146101c5578063a2df1f95146101d8578063a57c7f59146101eb578063b753d7e9146101fe57600080fd5b8062fdd58e1461010457806325386715146101425780632fa1b39114610163578063557e715514610186575b600080fd5b61012f610112366004612b19565b600160209081526000928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b610155610150366004612b45565b61030f565b604051610139929190612b71565b610176610171366004612d68565b6108cd565b6040516101399493929190612e79565b6101ad7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610139565b61012f6101d3366004612f56565b610eb4565b6101766101e6366004612f6f565b61103d565b61012f6101f9366004613010565b611853565b61012f61020c366004612b45565b611936565b61012f61021f366004613042565b61194d565b6101ad7f000000000000000000000000000000000000000000000000000000000000000081565b610155610259366004612b45565b611cc8565b6101ad7f000000000000000000000000000000000000000000000000000000000000000081565b61012f610293366004612b19565b6121f8565b61012f6102a6366004613091565b600360209081526000938452604080852082529284528284209052825290205481565b6102dc6102d73660046130c6565b6122d6565b005b61012f6102ec366004613091565b600260209081526000938452604080852082529284528284209052825290205481565b6103676040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b60006002600054036103da576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b60026000556040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018690527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa15801561045e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061048291906130f8565b3360009081526003602090815260408083208984528252808320828501518452909152812054919350906104b79086906131a7565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635dd8f6aa896040518263ffffffff1660e01b815260040161050a91815260200190565b602060405180830381865afa158015610527573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061054b91906131ba565b6001600160a01b0316637a81b56289876020015133336001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561059e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105c291906131ba565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e087901b168152600481019490945260248401929092526001600160a01b0390811660448401521660648201526084016040805180830381865afa158015610633573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065791906131d7565b9150915081831180610667575081155b1561069e576040517fb6ecab1200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8086146106d7576040517fe56ea4e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000336001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610717573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061073b91906131fb565b905080871461080f5761080a886107546012600a613334565b6040517fa4d0caf2000000000000000000000000000000000000000000000000000000008152600481018b905260248101859052601260448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a4d0caf2906064015b602060405180830381865afa1580156107e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061080591906131fb565b61231f565b610811565b875b945061081f338a8884612423565b851115610858576040517f2fca7ece00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360008181526003602090815260408083208d845282528083208a83015184528252808320889055928252600181528282208c83529052205461089c908690613340565b3360009081526001602081815260408084209d84529c90529a81209190915598909855509296919550909350505050565b6109256040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b6000606080600260005403610996576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103d1565b60026000556040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018b90527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa158015610a1a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3e91906130f8565b8051909450600003610a7c576040517f2e96671a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61010084015160481c600190811603610ac1576040517fa3bb913300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61010084015160009060521c6001908116148015610af757506000610aeb86610100015160541c90565b6001600160a01b031614155b15610c49576000604051806101400160405280336001600160a01b031681526020018f6001600160a01b031681526020018e803603810190610b399190613353565b815260208082018f905288015160408201526001600160a01b038c16606082015260a080890151608083015261010089015191019060181c61ffff1681526020018a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050908252506020018890529050610bca86610100015160541c90565b6001600160a01b031663d46cf171826040518263ffffffff1660e01b8152600401610bf591906133c2565b6000604051808303816000875af1158015610c14573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610c3c9190810190613530565b955093509150610c8a9050565b8460a00151905087878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294505050505b825160208d01359015610d1f5760005b8451811015610d1d576000858281518110610cb757610cb7613621565b602002602001015160200151905080600014610d145782811115610d07576040517f6d51b52600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d118184613340565b92505b50600101610c9a565b505b8c60200135600003610d37575060009350610e9d9050565b8015610d9e573360009081526001602090815260408083208f8452909152902054610d639082906131a7565b60016000336001600160a01b03166001600160a01b0316815260200190815260200160002060008e8152602001908152602001600020819055505b5080600003610db1575060009250610e9d565b60408c0135600060608e01358c14610e7b576040517fa4d0caf200000000000000000000000000000000000000000000000000000000815260608f01356004820152602481018d9052604481018390526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a4d0caf290606401602060405180830381865afa158015610e52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7691906131fb565b610e86565b610e8682600a613334565b9050610e978e60200135848361231f565b95505050505b600160008190555098509850985098945050505050565b6000600260005403610f22576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103d1565b600260009081556040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa158015610fa8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fcc91906130f8565b610100810151909150604d1c600190811614611014576040517fe7c9e0be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505033600090815260016020818152604080842094845293905291812080549082905591905590565b6110956040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b6000606080600260005403611106576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103d1565b60026000556040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa15801561118a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ae91906130f8565b610100810151909450604a1c6001908116036111f6576040517fa97cf58f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61122a604051806080016040528060006001600160a01b031681526020016000815260200160008152602001600081525090565b6000806000336001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561126d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061129191906131ba565b90506000336001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f791906131fb565b90506000336001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611339573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061135d91906131fb565b6101008b015190915060511c6001908116146113845761137f338f8c84612423565b61138f565b61138f8e8383612705565b94507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635dd8f6aa8f6040518263ffffffff1660e01b81526004016113df91815260200190565b602060405180830381865afa1580156113fc573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061142091906131ba565b6001600160a01b031663b5f1e34d8f6114458d610100015161ffff60189190911c1690565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815260048101929092526024820152604401602060405180830381865afa15801561149e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114c291906131fb565b9350838d11156114fe576040517fb8af220000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8415611514576115118e8b8f8789612919565b98505b604080516080810182526001600160a01b03949094168452602084018a9052830191909152606082015261010088015190935060531c60019081161480156115745750600061156888610100015160541c90565b6001600160a01b031614155b15611764576040517fc55f571c000000000000000000000000000000000000000000000000000000008152600481018c90526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c55f571c90602401602060405180830381865afa1580156115fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061161e9190613650565b90506000604051806101800160405280336001600160a01b031681526020018f6001600160a01b031681526020018e81526020018a6020015181526020018d815260200184815260200185815260200186815260200161168b8b6101000151600160519190911c81161490565b1515815260200160008460028111156116a6576116a6613671565b146116b9576116b48b612a6a565b6116c2565b6116c28b612a87565b81526020018c81526020018b81525090506116e289610100015160541c90565b6001600160a01b031663a51cfd18826040518263ffffffff1660e01b815260040161170d91906136a0565b6000604051808303816000875af115801561172c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611754919081019061379b565b9199509097509550611768915050565b8893505b50508251849150156117c25760005b83518110156117c057600084828151811061179457611794613621565b6020026020010151602001519050806000146117b7576117b481846131a7565b92505b50600101611777565b505b3360009081526001602090815260408083208c8452909152902054811115611816576040517f2fca7ece00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b801561183e573360009081526001602090815260408083208c84529091529020805482900390555b50600160008190555095509550955095915050565b6000816000036118655750600061192e565b828411156118755750600061192e565b6040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018690526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa1580156118f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061191b91906130f8565b905061192a8682878787612919565b9150505b949350505050565b6000611943848484612705565b90505b9392505050565b6040517f43a266c20000000000000000000000000000000000000000000000000000000081526004810184905260009081906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906343a266c29060240161012060405180830381865afa1580156119d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119f591906130f8565b9050600083611a7057611a6b8787848a6001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a6691906131fb565b612423565b611b3d565b611b3d86886001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ab2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ad691906131fb565b896001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b3891906131fb565b612705565b905080600003611b525760009250505061192e565b6040517f5dd8f6aa000000000000000000000000000000000000000000000000000000008152600481018790526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635dd8f6aa90602401602060405180830381865afa158015611bd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bf791906131ba565b6001600160a01b031663b5f1e34d88611c1c86610100015161ffff60189190911c1690565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815260048101929092526024820152604401602060405180830381865afa158015611c75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c9991906131fb565b905080861115611caf576000935050505061192e565b611cbc8784888486612919565b98975050505050505050565b611d206040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b6000600260005403611d8e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103d1565b60026000556040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018690527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa158015611e12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3691906130f8565b61010081015190925060491c600190811603611e7e576040517f861e9dcd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152600260209081526040808320888452825280832085518452909152812054611ead9086906131a7565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635dd8f6aa896040518263ffffffff1660e01b8152600401611f0091815260200190565b602060405180830381865afa158015611f1d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f4191906131ba565b6001600160a01b031663e8db213089876020015133336001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f94573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fb891906131ba565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e087901b168152600481019490945260248401929092526001600160a01b0390811660448401521660648201526084016040805180830381865afa158015612029573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204d91906131d7565b915091508183118061205d575081155b15612094576040517f08dae4ac00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8086146120cd576040517fe56ea4e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000336001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561210d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061213191906131fb565b905080871461214f5761214a886107546012600a613334565b612151565b875b3360009081526001602090815260408083208d84529091529020549095508511156121a8576040517f2fca7ece00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50503360008181526002602090815260408083208b845282528083208851845282528083209590955591815260018083528482209982529890915291822080548490039055509490945593915050565b60006122cd83837f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166343a266c2866040518263ffffffff1660e01b815260040161224d91815260200190565b61012060405180830381865afa15801561226b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061228f91906130f8565b866001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a42573d6000803e3d6000fd5b90505b92915050565b3360009081526001602090815260408083208584529091529020546122fc9082906131a7565b336000908152600160209081526040808320958352949052929092209190915550565b600080807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff858709858702925082811083820303915050806000036123775783828161236d5761236d61387c565b0492505050611946565b8381106123ba576040517f773cc18c00000000000000000000000000000000000000000000000000000000815260048101829052602481018590526044016103d1565b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b6001600160a01b038416600090815260016020908152604080832086845290915281205480820361245857600091505061192e565b6040517f5dd8f6aa0000000000000000000000000000000000000000000000000000000081526004810186905260009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690635dd8f6aa90602401602060405180830381865afa1580156124db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124ff91906131ba565b6001600160a01b031663e8db21308888602001518b8c6001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612552573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061257691906131ba565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e087901b168152600481019490945260248401929092526001600160a01b0390811660448401521660648201526084016040805180830381865afa1580156125e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061260b91906131d7565b6001600160a01b038a1660009081526002602090815260408083208c845282528083208b518452909152812054929450909250906126499084613340565b9050801580159061265a5750858214155b156126e6576126e38161266f6012600a613334565b6040517fa4d0caf200000000000000000000000000000000000000000000000000000000815260048101869052602481018a9052601260448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a4d0caf2906064016107c4565b90505b8084116126f45760006126f8565b8084035b9998505050505050505050565b6040517fd17541530000000000000000000000000000000000000000000000000000000081526004810184905260009081906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063d175415390602401600060405180830381865afa158015612788573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526127b091908101906138ab565b90506000805b825181101561285b578281815181106127d1576127d1613621565b60200260200101516001600160a01b031663a32e1e96886040518263ffffffff1660e01b815260040161280691815260200190565b602060405180830381865afa158015612823573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061284791906131fb565b61285190836131a7565b91506001016127b6565b506000600185146128ef576040517fa4d0caf20000000000000000000000000000000000000000000000000000000081526001600482015260248101869052601260448201526128ea908390670de0b6b3a7640000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a4d0caf2906064016107c4565b6128f1565b815b90508560121461290c5761290781601288612aa4565b61290e565b805b979650505050505050565b6000828403612929575080612a61565b6000806040517fc55f571c000000000000000000000000000000000000000000000000000000008152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c55f571c90602401602060405180830381865afa1580156129aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129ce9190613650565b60028111156129df576129df613671565b146129f2576129ed86612a6a565b6129fb565b6129fb86612a87565b905080600003612a0f576000915050612a61565b6000612a1c84878761231f565b90506127108203612a30579150612a619050565b612a5c81612a4a88612a4486612710613340565b8961231f565b612a5490856131a7565b61271061231f565b925050505b95945050505050565b60006028826101000151901c61ffff166127106122d09190613340565b60006038826101000151901c61ffff166127106122d09190613340565b6000828203612ab4575082611946565b82821115612ae257612ac68383613340565b612ad190600a613334565b612adb908561393a565b9050611946565b612aec8284613340565b612af790600a613334565b612adb9085613977565b6001600160a01b0381168114612b1657600080fd5b50565b60008060408385031215612b2c57600080fd5b8235612b3781612b01565b946020939093013593505050565b600080600060608486031215612b5a57600080fd5b505081359360208301359350604090920135919050565b6101408101612bde8285805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c08301526001600160a01b0360e08201511660e08301526101008082015181840152505050565b826101208301529392505050565b60008083601f840112612bfe57600080fd5b50813567ffffffffffffffff811115612c1657600080fd5b602083019150836020828501011115612c2e57600080fd5b9250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff81118282101715612c8857612c88612c35565b60405290565b6040805190810167ffffffffffffffff81118282101715612c8857612c88612c35565b604051601f8201601f1916810167ffffffffffffffff81118282101715612cda57612cda612c35565b604052919050565b600067ffffffffffffffff821115612cfc57612cfc612c35565b50601f01601f191660200190565b6000612d1d612d1884612ce2565b612cb1565b9050828152838383011115612d3157600080fd5b828260208301376000602084830101529392505050565b600082601f830112612d5957600080fd5b6122cd83833560208501612d0a565b600080600080600080600080888a03610140811215612d8657600080fd5b8935612d9181612b01565b98506080601f1982011215612da557600080fd5b5060208901965060a0890135955060c0890135945060e0890135612dc881612b01565b935061010089013567ffffffffffffffff80821115612de657600080fd5b612df28c838d01612bec565b90955093506101208b0135915080821115612e0c57600080fd5b50612e198b828c01612d48565b9150509295985092959890939650565b60005b83811015612e44578181015183820152602001612e2c565b50506000910152565b60008151808452612e65816020860160208601612e29565b601f01601f19169290920160200192915050565b6000610180808301612ee98489805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c08301526001600160a01b0360e08201511660e08301526101008082015181840152505050565b61012084018790526101408401919091528451908190526101a083019060209081870160005b82811015612f3f57815180516001600160a01b031686528401518486015260409094019390830190600101612f0f565b5050505082810361016084015261290e8185612e4d565b600060208284031215612f6857600080fd5b5035919050565b600080600080600060a08688031215612f8757600080fd5b8535612f9281612b01565b94506020860135935060408601359250606086013567ffffffffffffffff80821115612fbd57600080fd5b818801915088601f830112612fd157600080fd5b612fe089833560208501612d0a565b93506080880135915080821115612ff657600080fd5b5061300388828901612d48565b9150509295509295909350565b6000806000806080858703121561302657600080fd5b5050823594602084013594506040840135936060013592509050565b6000806000806080858703121561305857600080fd5b843561306381612b01565b935060208501359250604085013591506060850135801515811461308657600080fd5b939692955090935050565b6000806000606084860312156130a657600080fd5b83356130b181612b01565b95602085013595506040909401359392505050565b600080604083850312156130d957600080fd5b50508035926020909101359150565b80516130f381612b01565b919050565b6000610120828403121561310b57600080fd5b613113612c64565b825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015261315f60e084016130e8565b60e0820152610100928301519281019290925250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156122d0576122d0613178565b6000602082840312156131cc57600080fd5b815161194681612b01565b600080604083850312156131ea57600080fd5b505080516020909101519092909150565b60006020828403121561320d57600080fd5b5051919050565b600181815b8085111561326d57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561325357613253613178565b8085161561326057918102915b93841c9390800290613219565b509250929050565b600082613284575060016122d0565b81613291575060006122d0565b81600181146132a757600281146132b1576132cd565b60019150506122d0565b60ff8411156132c2576132c2613178565b50506001821b6122d0565b5060208310610133831016604e8410600b84101617156132f0575081810a6122d0565b6132fa8383613214565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561332c5761332c613178565b029392505050565b60006122cd8383613275565b818103818111156122d0576122d0613178565b60006080828403121561336557600080fd5b6040516080810181811067ffffffffffffffff8211171561338857613388612c35565b604052823561339681612b01565b808252506020830135602082015260408301356040820152606083013560608201528091505092915050565b602081526133dc6020820183516001600160a01b03169052565b600060208301516133f860408401826001600160a01b03169052565b50604083015161343560608401826001600160a01b0381511682526020810151602083015260408101516040830152606081015160608301525050565b50606083015160e08301526080830151610100818185015260a0850151915061012061346b818601846001600160a01b03169052565b60c086015161014086015260e08601516101608601528186015192506101a09150816101808601526134a16101c0860184612e4d565b90860151858203601f1901838701529092506134bd8382612e4d565b9695505050505050565b600082601f8301126134d857600080fd5b81516134e6612d1882612ce2565b8181528460208386010111156134fb57600080fd5b61192e826020830160208701612e29565b600067ffffffffffffffff82111561352657613526612c35565b5060051b60200190565b60008060006060848603121561354557600080fd5b8351925060208085015167ffffffffffffffff8082111561356557600080fd5b613571888389016134c7565b945060409150818701518181111561358857600080fd5b87019050601f8101881361359b57600080fd5b80516135a9612d188261350c565b81815260069190911b8201840190848101908a8311156135c857600080fd5b928501925b828410156136115784848c0312156135e55760008081fd5b6135ed612c8e565b84516135f881612b01565b81528487015187820152825292840192908501906135cd565b8096505050505050509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561366257600080fd5b81516003811061194657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b602081526136ba6020820183516001600160a01b03169052565b600060208301516136d660408401826001600160a01b03169052565b506040830151606083015260608301516080830152608083015160a083015260a083015160c083015260c083015160e083015260e0830151610100613747818501836001600160a01b0381511682526020810151602083015260408101516040830152606081015160608301525050565b8401511515610180840152506101208301516101a08301526101408301516101e06101c0840181905261377e610200850183612e4d565b9150610160850151601f1985840301828601526134bd8382612e4d565b6000806000606084860312156137b057600080fd5b8351925060208085015167ffffffffffffffff808211156137d057600080fd5b6137dc888389016134c7565b94506040915081870151818111156137f357600080fd5b87019050601f8101881361380657600080fd5b8051613814612d188261350c565b81815260069190911b8201840190848101908a83111561383357600080fd5b928501925b828410156136115784848c0312156138505760008081fd5b613858612c8e565b845161386381612b01565b8152848701518782015282529284019290850190613838565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600060208083850312156138be57600080fd5b825167ffffffffffffffff8111156138d557600080fd5b8301601f810185136138e657600080fd5b80516138f4612d188261350c565b81815260059190911b8201830190838101908783111561391357600080fd5b928401925b8284101561290e57835161392b81612b01565b82529284019290840190613918565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561397257613972613178565b500290565b6000826139ad577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b50049056fea2646970667358221220496c9f50e79f6514ca61a35b21fe271a2d4fe217f051df7336af8ae92911191e64736f6c63430008100033", "devdoc": { diff --git a/deployments/goerli/JBSingleTokenPaymentTerminalStore3_1.json b/deployments/goerli/JBSingleTokenPaymentTerminalStore3_1.json index 185eb1492..754356f1f 100644 --- a/deployments/goerli/JBSingleTokenPaymentTerminalStore3_1.json +++ b/deployments/goerli/JBSingleTokenPaymentTerminalStore3_1.json @@ -816,7 +816,7 @@ ], "numDeployments": 1, "solcInputHash": "7271447540576b6e014cf146f777e938", - "metadata": "{\"compiler\":{\"version\":\"0.8.16+commit.07a7930e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IJBDirectory\",\"name\":\"_directory\",\"type\":\"address\"},{\"internalType\":\"contract IJBFundingCycleStore\",\"name\":\"_fundingCycleStore\",\"type\":\"address\"},{\"internalType\":\"contract IJBPrices\",\"name\":\"_prices\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CURRENCY_MISMATCH\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DISTRIBUTION_AMOUNT_LIMIT_REACHED\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FUNDING_CYCLE_DISTRIBUTION_PAUSED\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FUNDING_CYCLE_PAYMENT_PAUSED\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FUNDING_CYCLE_REDEEM_PAUSED\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INADEQUATE_CONTROLLER_ALLOWANCE\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INSUFFICIENT_TOKENS\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INVALID_AMOUNT_TO_SEND_DELEGATE\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INVALID_FUNDING_CYCLE\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"prod1\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"denominator\",\"type\":\"uint256\"}],\"name\":\"PRBMath__MulDivOverflow\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminal\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminal\",\"name\":\"_terminal\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"}],\"name\":\"currentOverflowOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_tokenCount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_overflow\",\"type\":\"uint256\"}],\"name\":\"currentReclaimableOverflowOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminal\",\"name\":\"_terminal\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_tokenCount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"_useTotalOverflow\",\"type\":\"bool\"}],\"name\":\"currentReclaimableOverflowOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_decimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_currency\",\"type\":\"uint256\"}],\"name\":\"currentTotalOverflowOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"directory\",\"outputs\":[{\"internalType\":\"contract IJBDirectory\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fundingCycleStore\",\"outputs\":[{\"internalType\":\"contract IJBFundingCycleStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"prices\",\"outputs\":[{\"internalType\":\"contract IJBPrices\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"recordAddedBalanceFor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_currency\",\"type\":\"uint256\"}],\"name\":\"recordDistributionFor\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"configuration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"basedOn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"discountRate\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBFundingCycleBallot\",\"name\":\"ballot\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"metadata\",\"type\":\"uint256\"}],\"internalType\":\"struct JBFundingCycle\",\"name\":\"fundingCycle\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"distributedAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"}],\"name\":\"recordMigration\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_payer\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"decimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"currency\",\"type\":\"uint256\"}],\"internalType\":\"struct JBTokenAmount\",\"name\":\"_amount\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_baseWeightCurrency\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"recordPaymentFrom\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"configuration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"basedOn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"discountRate\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBFundingCycleBallot\",\"name\":\"ballot\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"metadata\",\"type\":\"uint256\"}],\"internalType\":\"struct JBFundingCycle\",\"name\":\"fundingCycle\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"tokenCount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"contract IJBPayDelegate\",\"name\":\"delegate\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"struct JBPayDelegateAllocation[]\",\"name\":\"delegateAllocations\",\"type\":\"tuple[]\"},{\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_holder\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_tokenCount\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"recordRedemptionFor\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"configuration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"basedOn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"discountRate\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBFundingCycleBallot\",\"name\":\"ballot\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"metadata\",\"type\":\"uint256\"}],\"internalType\":\"struct JBFundingCycle\",\"name\":\"fundingCycle\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"reclaimAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"contract IJBRedemptionDelegate\",\"name\":\"delegate\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"struct JBRedemptionDelegateAllocation[]\",\"name\":\"delegateAllocations\",\"type\":\"tuple[]\"},{\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_currency\",\"type\":\"uint256\"}],\"name\":\"recordUsedAllowanceOf\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"configuration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"basedOn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"discountRate\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBFundingCycleBallot\",\"name\":\"ballot\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"metadata\",\"type\":\"uint256\"}],\"internalType\":\"struct JBFundingCycle\",\"name\":\"fundingCycle\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"usedAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminal\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"usedDistributionLimitOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminal\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"usedOverflowAllowanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Adheres to: IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.Inherits from - ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.This Store expects a project's controller to be an IJBController3_1. This is the only difference between this version and the original.\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_directory\":\"A contract storing directories of terminals and controllers for each project.\",\"_fundingCycleStore\":\"A contract storing all funding cycle configurations.\",\"_prices\":\"A contract that exposes price feeds.\"}},\"currentOverflowOf(address,uint256)\":{\"details\":\"The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\",\"params\":{\"_projectId\":\"The ID of the project to get overflow for.\",\"_terminal\":\"The terminal for which the overflow is being calculated.\"},\"returns\":{\"_0\":\"The current amount of overflow that project has in the specified terminal.\"}},\"currentReclaimableOverflowOf(address,uint256,uint256,bool)\":{\"details\":\" If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.The current reclaimable overflow is returned in terms of the specified terminal's currency.The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\",\"params\":{\"_projectId\":\"The ID of the project to get the reclaimable overflow amount for.\",\"_terminal\":\"The terminal from which the reclaimable amount would come.\",\"_tokenCount\":\"The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\",\"_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`.\"},\"returns\":{\"_0\":\"The amount of overflowed tokens that can be reclaimed, as a fixed point number with the same number of decimals as the provided `_terminal`.\"}},\"currentReclaimableOverflowOf(uint256,uint256,uint256,uint256)\":{\"details\":\" If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\",\"params\":{\"_overflow\":\"The amount of overflow to make the calculation with, as a fixed point number.\",\"_projectId\":\"The ID of the project to get the reclaimable overflow amount for.\",\"_tokenCount\":\"The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\",\"_totalSupply\":\"The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\"},\"returns\":{\"_0\":\"The amount of overflowed tokens that can be reclaimed, as a fixed point number with the same number of decimals as the provided `_overflow`.\"}},\"currentTotalOverflowOf(uint256,uint256,uint256)\":{\"params\":{\"_currency\":\"The currency that the total overflow should be in terms of.\",\"_decimals\":\"The number of decimals that the fixed point overflow should include.\",\"_projectId\":\"The ID of the project to get total overflow for.\"},\"returns\":{\"_0\":\"The current total amount of overflow that project has across all terminals.\"}},\"recordAddedBalanceFor(uint256,uint256)\":{\"details\":\"The msg.sender must be an IJBSingleTokenPaymentTerminal. \",\"params\":{\"_amount\":\"The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\",\"_projectId\":\"The ID of the project to which the funds being added belong.\"}},\"recordDistributionFor(uint256,uint256,uint256)\":{\"details\":\"The msg.sender must be an IJBSingleTokenPaymentTerminal. \",\"params\":{\"_amount\":\"The amount to use from the distribution limit, as a fixed point number.\",\"_currency\":\"The currency of the `_amount`. This must match the project's current funding cycle's currency.\",\"_projectId\":\"The ID of the project that is having funds distributed.\"},\"returns\":{\"distributedAmount\":\"The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\",\"fundingCycle\":\"The funding cycle during which the distribution was made.\"}},\"recordMigration(uint256)\":{\"details\":\"The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\",\"params\":{\"_projectId\":\"The ID of the project being migrated.\"},\"returns\":{\"balance\":\"The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\"}},\"recordPaymentFrom(address,(address,uint256,uint256,uint256),uint256,uint256,address,string,bytes)\":{\"details\":\"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.The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\",\"params\":{\"_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.\",\"_baseWeightCurrency\":\"The currency to base token issuance on.\",\"_beneficiary\":\"The specified address that should be the beneficiary of anything that results from the payment.\",\"_memo\":\"A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\",\"_metadata\":\"Bytes to send along to the data source, if one is provided.\",\"_payer\":\"The original address that sent the payment to the terminal.\",\"_projectId\":\"The ID of the project being paid.\"},\"returns\":{\"delegateAllocations\":\"The amount to send to delegates instead of adding to the local balance.\",\"fundingCycle\":\"The project's funding cycle during which payment was made.\",\"memo\":\"A memo that should be passed along to the emitted event.\",\"tokenCount\":\"The number of project tokens that were minted, as a fixed point number with 18 decimals.\"}},\"recordRedemptionFor(address,uint256,uint256,string,bytes)\":{\"details\":\"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.The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\",\"params\":{\"_holder\":\"The account that is having its tokens redeemed.\",\"_memo\":\"A memo to pass along to the emitted event.\",\"_metadata\":\"Bytes to send along to the data source, if one is provided.\",\"_projectId\":\"The ID of the project to which the tokens being redeemed belong.\",\"_tokenCount\":\"The number of project tokens to redeem, as a fixed point number with 18 decimals.\"},\"returns\":{\"delegateAllocations\":\"The amount to send to delegates instead of sending to the beneficiary.\",\"fundingCycle\":\"The funding cycle during which the redemption was made.\",\"memo\":\"A memo that should be passed along to the emitted event.\",\"reclaimAmount\":\"The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\"}},\"recordUsedAllowanceOf(uint256,uint256,uint256)\":{\"details\":\"The msg.sender must be an IJBSingleTokenPaymentTerminal. \",\"params\":{\"_amount\":\"The amount to use from the allowance, as a fixed point number. \",\"_currency\":\"The currency of the `_amount`. Must match the currency of the overflow allowance.\",\"_projectId\":\"The ID of the project to use the allowance of.\"},\"returns\":{\"fundingCycle\":\"The funding cycle during which the overflow allowance is being used.\",\"usedAmount\":\"The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\"}}},\"stateVariables\":{\"balanceOf\":{\"details\":\"The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal. _terminal The terminal to which the balance applies. _projectId The ID of the project to get the balance of.\"},\"usedDistributionLimitOf\":{\"details\":\"Increases as projects use their preconfigured distribution limits.The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal. _terminal The terminal to which the used distribution limit applies. _projectId The ID of the project to get the used distribution limit of. _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\"},\"usedOverflowAllowanceOf\":{\"details\":\"Increases as projects use their allowance.The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal. _terminal The terminal to which the overflow allowance applies. _projectId The ID of the project to get the used overflow allowance of. _configuration The configuration of the during which the allowance was used.\"}},\"version\":1},\"userdoc\":{\"errors\":{\"PRBMath__MulDivOverflow(uint256,uint256)\":[{\"notice\":\"Emitted when the result overflows uint256.\"}]},\"kind\":\"user\",\"methods\":{\"balanceOf(address,uint256)\":{\"notice\":\"The amount of tokens that each project has for each terminal, in terms of the terminal's token.\"},\"currentOverflowOf(address,uint256)\":{\"notice\":\"Gets the current overflowed amount in a terminal for a specified project.\"},\"currentReclaimableOverflowOf(address,uint256,uint256,bool)\":{\"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.\"},\"currentReclaimableOverflowOf(uint256,uint256,uint256,uint256)\":{\"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.\"},\"currentTotalOverflowOf(uint256,uint256,uint256)\":{\"notice\":\"Gets the current overflowed amount for a specified project across all terminals.\"},\"directory()\":{\"notice\":\"The directory of terminals and controllers for projects.\"},\"fundingCycleStore()\":{\"notice\":\"The contract storing all funding cycle configurations.\"},\"prices()\":{\"notice\":\"The contract that exposes price feeds.\"},\"recordAddedBalanceFor(uint256,uint256)\":{\"notice\":\"Records newly added funds for the project.\"},\"recordDistributionFor(uint256,uint256,uint256)\":{\"notice\":\"Records newly distributed funds for a project.\"},\"recordMigration(uint256)\":{\"notice\":\"Records the migration of funds from this store.\"},\"recordPaymentFrom(address,(address,uint256,uint256,uint256),uint256,uint256,address,string,bytes)\":{\"notice\":\"Records newly contributed tokens to a project.\"},\"recordRedemptionFor(address,uint256,uint256,string,bytes)\":{\"notice\":\"Records newly redeemed tokens of a project.\"},\"recordUsedAllowanceOf(uint256,uint256,uint256)\":{\"notice\":\"Records newly used allowance funds of a project.\"},\"usedDistributionLimitOf(address,uint256,uint256)\":{\"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.\"},\"usedOverflowAllowanceOf(address,uint256,uint256)\":{\"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.\"}},\"notice\":\"Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/JBSingleTokenPaymentTerminalStore3_1.sol\":\"JBSingleTokenPaymentTerminalStore3_1\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/security/ReentrancyGuard.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuard {\\n // Booleans are more expensive than uint256 or any type that takes up a full\\n // word because each write operation emits an extra SLOAD to first read the\\n // slot's contents, replace the bits taken up by the boolean, and then write\\n // back. This is the compiler's defense against contract upgrades and\\n // pointer aliasing, and it cannot be disabled.\\n\\n // The values being non-zero value makes deployment a bit more expensive,\\n // but in exchange the refund on every call to nonReentrant will be lower in\\n // amount. Since refunds are capped to a percentage of the total\\n // transaction's gas, it is best to keep them low in cases like this one, to\\n // increase the likelihood of the full refund coming into effect.\\n uint256 private constant _NOT_ENTERED = 1;\\n uint256 private constant _ENTERED = 2;\\n\\n uint256 private _status;\\n\\n constructor() {\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and making it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n // On the first call to nonReentrant, _notEntered will be true\\n require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n _status = _ENTERED;\\n\\n _;\\n\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n _status = _NOT_ENTERED;\\n }\\n}\\n\",\"keccak256\":\"0x0e9621f60b2faabe65549f7ed0f24e8853a45c1b7990d47e8160e523683f3935\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool _approved) external;\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x516a22876c1fab47f49b1bc22b4614491cd05338af8bd2e7b382da090a079990\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"@paulrberg/contracts/math/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\nimport \\\"prb-math/contracts/PRBMath.sol\\\";\\n\",\"keccak256\":\"0x42821345981bc0434a90ba2268a2f5278dfe9e38166981d72fc7f3b776a29495\",\"license\":\"Unlicense\"},\"contracts/JBSingleTokenPaymentTerminalStore3_1.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\\nimport '@paulrberg/contracts/math/PRBMath.sol';\\nimport './interfaces/IJBController3_1.sol';\\nimport './interfaces/IJBFundingCycleDataSource.sol';\\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\\nimport './libraries/JBConstants.sol';\\nimport './libraries/JBCurrencies.sol';\\nimport './libraries/JBFixedPointNumber.sol';\\nimport './libraries/JBFundingCycleMetadataResolver.sol';\\nimport './structs/JBPayDelegateAllocation.sol';\\nimport './structs/JBPayParamsData.sol';\\n\\n/**\\n @notice\\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\\n\\n @dev\\n Adheres to:\\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n\\n @dev\\n Inherits from -\\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\\n\\n @dev\\n This Store expects a project's controller to be an IJBController3_1. This is the only difference between this version and the original.\\n*/\\ncontract JBSingleTokenPaymentTerminalStore3_1 is\\n ReentrancyGuard,\\n IJBSingleTokenPaymentTerminalStore\\n{\\n // A library that parses the packed funding cycle metadata into a friendlier format.\\n using JBFundingCycleMetadataResolver for JBFundingCycle;\\n\\n //*********************************************************************//\\n // --------------------------- custom errors ------------------------- //\\n //*********************************************************************//\\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\\n error CURRENCY_MISMATCH();\\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\\n error FUNDING_CYCLE_PAYMENT_PAUSED();\\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\\n error FUNDING_CYCLE_REDEEM_PAUSED();\\n error INADEQUATE_CONTROLLER_ALLOWANCE();\\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\\n error INSUFFICIENT_TOKENS();\\n error INVALID_FUNDING_CYCLE();\\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\\n\\n //*********************************************************************//\\n // -------------------------- private constants ---------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \\n */\\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\\n\\n //*********************************************************************//\\n // ---------------- public immutable stored properties --------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The directory of terminals and controllers for projects.\\n */\\n IJBDirectory public immutable override directory;\\n\\n /**\\n @notice\\n The contract storing all funding cycle configurations.\\n */\\n IJBFundingCycleStore public immutable override fundingCycleStore;\\n\\n /**\\n @notice\\n The contract that exposes price feeds.\\n */\\n IJBPrices public immutable override prices;\\n\\n //*********************************************************************//\\n // --------------------- public stored properties -------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\\n\\n @dev\\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\\n\\n _terminal The terminal to which the balance applies.\\n _projectId The ID of the project to get the balance of.\\n */\\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\\n\\n /**\\n @notice\\n 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.\\n\\n @dev\\n Increases as projects use their preconfigured distribution limits.\\n\\n @dev\\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\\n\\n _terminal The terminal to which the used distribution limit applies.\\n _projectId The ID of the project to get the used distribution limit of.\\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\\n */\\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\\n public\\n override usedDistributionLimitOf;\\n\\n /**\\n @notice\\n 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.\\n\\n @dev\\n Increases as projects use their allowance.\\n\\n @dev\\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\\n\\n _terminal The terminal to which the overflow allowance applies.\\n _projectId The ID of the project to get the used overflow allowance of.\\n _configuration The configuration of the during which the allowance was used.\\n */\\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\\n public\\n override usedOverflowAllowanceOf;\\n\\n //*********************************************************************//\\n // ------------------------- external views -------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Gets the current overflowed amount in a terminal for a specified project.\\n\\n @dev\\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\\n\\n @param _terminal The terminal for which the overflow is being calculated.\\n @param _projectId The ID of the project to get overflow for.\\n\\n @return The current amount of overflow that project has in the specified terminal.\\n */\\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\\n external\\n view\\n override\\n returns (uint256)\\n {\\n // Return the overflow during the project's current funding cycle.\\n return\\n _overflowDuring(\\n _terminal,\\n _projectId,\\n fundingCycleStore.currentOf(_projectId),\\n _terminal.currency()\\n );\\n }\\n\\n /**\\n @notice\\n Gets the current overflowed amount for a specified project across all terminals.\\n\\n @param _projectId The ID of the project to get total overflow for.\\n @param _decimals The number of decimals that the fixed point overflow should include.\\n @param _currency The currency that the total overflow should be in terms of.\\n\\n @return The current total amount of overflow that project has across all terminals.\\n */\\n function currentTotalOverflowOf(\\n uint256 _projectId,\\n uint256 _decimals,\\n uint256 _currency\\n ) external view override returns (uint256) {\\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\\n }\\n\\n /**\\n @notice\\n 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.\\n\\n @dev \\n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\\n\\n @dev\\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\\n\\n @dev\\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\\n\\n @param _terminal The terminal from which the reclaimable amount would come.\\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\\n @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`.\\n\\n @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`.\\n */\\n function currentReclaimableOverflowOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n bool _useTotalOverflow\\n ) external view override returns (uint256) {\\n // Get a reference to the project's current funding cycle.\\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // Get the amount of current overflow.\\n // 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.\\n uint256 _currentOverflow = _useTotalOverflow\\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\\n\\n // If there's no overflow, there's no reclaimable overflow.\\n if (_currentOverflow == 0) return 0;\\n\\n // Get the number of outstanding tokens the project has.\\n uint256 _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\\n .totalOutstandingTokensOf(_projectId);\\n\\n // Can't redeem more tokens that is in the supply.\\n if (_tokenCount > _totalSupply) return 0;\\n\\n // Return the reclaimable overflow amount.\\n return\\n _reclaimableOverflowDuring(\\n _projectId,\\n _fundingCycle,\\n _tokenCount,\\n _totalSupply,\\n _currentOverflow\\n );\\n }\\n\\n /**\\n @notice\\n 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.\\n\\n @dev \\n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\\n\\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\\n\\n @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`.\\n */\\n function currentReclaimableOverflowOf(\\n uint256 _projectId,\\n uint256 _tokenCount,\\n uint256 _totalSupply,\\n uint256 _overflow\\n ) external view override returns (uint256) {\\n // If there's no overflow, there's no reclaimable overflow.\\n if (_overflow == 0) return 0;\\n\\n // Can't redeem more tokens that is in the supply.\\n if (_tokenCount > _totalSupply) return 0;\\n\\n // Get a reference to the project's current funding cycle.\\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // Return the reclaimable overflow amount.\\n return\\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\\n }\\n\\n //*********************************************************************//\\n // -------------------------- constructor ---------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @param _directory A contract storing directories of terminals and controllers for each project.\\n @param _fundingCycleStore A contract storing all funding cycle configurations.\\n @param _prices A contract that exposes price feeds.\\n */\\n constructor(\\n IJBDirectory _directory,\\n IJBFundingCycleStore _fundingCycleStore,\\n IJBPrices _prices\\n ) {\\n directory = _directory;\\n fundingCycleStore = _fundingCycleStore;\\n prices = _prices;\\n }\\n\\n //*********************************************************************//\\n // ---------------------- external transactions ---------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Records newly contributed tokens to a project.\\n\\n @dev\\n 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.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\\n\\n @param _payer The original address that sent the payment to the terminal.\\n @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.\\n @param _projectId The ID of the project being paid.\\n @param _baseWeightCurrency The currency to base token issuance on.\\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\\n @param _metadata Bytes to send along to the data source, if one is provided.\\n\\n @return fundingCycle The project's funding cycle during which payment was made.\\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\\n @return memo A memo that should be passed along to the emitted event.\\n */\\n function recordPaymentFrom(\\n address _payer,\\n JBTokenAmount calldata _amount,\\n uint256 _projectId,\\n uint256 _baseWeightCurrency,\\n address _beneficiary,\\n string calldata _memo,\\n bytes memory _metadata\\n )\\n external\\n override\\n nonReentrant\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 tokenCount,\\n JBPayDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n )\\n {\\n // Get a reference to the current funding cycle for the project.\\n fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // The project must have a funding cycle configured.\\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\\n\\n // Must not be paused.\\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\\n\\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\\n uint256 _weight;\\n\\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\\n // Create the params that'll be sent to the data source.\\n JBPayParamsData memory _data = JBPayParamsData(\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n _payer,\\n _amount,\\n _projectId,\\n fundingCycle.configuration,\\n _beneficiary,\\n fundingCycle.weight,\\n fundingCycle.reservedRate(),\\n _memo,\\n _metadata\\n );\\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\\n .payParams(_data);\\n }\\n // Otherwise use the funding cycle's weight\\n else {\\n _weight = fundingCycle.weight;\\n memo = _memo;\\n }\\n\\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\\n {\\n // Keep a reference to the amount that should be added to the project's balance.\\n uint256 _balanceDiff = _amount.value;\\n\\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\\n if (delegateAllocations.length != 0) {\\n for (uint256 _i; _i < delegateAllocations.length; ) {\\n // Get a reference to the amount to be delegated.\\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\\n\\n // Validate if non-zero.\\n if (_delegatedAmount != 0) {\\n // Can't delegate more than was paid.\\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\\n\\n // Decrement the total amount being added to the balance.\\n _balanceDiff = _balanceDiff - _delegatedAmount;\\n }\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n\\n // If there's no amount being recorded, there's nothing left to do.\\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\\n\\n // Add the correct balance difference to the token balance of the project.\\n if (_balanceDiff != 0)\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\\n _balanceDiff;\\n }\\n\\n // If there's no weight, token count must be 0 so there's nothing left to do.\\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\\n\\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\\n uint256 _decimals = _amount.decimals;\\n\\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\\n // 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`.\\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\\n ? 10**_decimals\\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\\n\\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\\n }\\n\\n /**\\n @notice\\n Records newly redeemed tokens of a project.\\n\\n @dev\\n 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.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\\n\\n @param _holder The account that is having its tokens redeemed.\\n @param _projectId The ID of the project to which the tokens being redeemed belong.\\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Bytes to send along to the data source, if one is provided.\\n\\n @return fundingCycle The funding cycle during which the redemption was made.\\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\\n @return memo A memo that should be passed along to the emitted event.\\n */\\n function recordRedemptionFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n string memory _memo,\\n bytes memory _metadata\\n )\\n external\\n override\\n nonReentrant\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 reclaimAmount,\\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n )\\n {\\n // Get a reference to the project's current funding cycle.\\n fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // The current funding cycle must not be paused.\\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\\n\\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\\n {\\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\\n JBTokenAmount memory _reclaimedTokenAmount;\\n uint256 _currentOverflow;\\n uint256 _totalSupply;\\n\\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\\n {\\n // Get a reference to the terminal's tokens.\\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\\n\\n // Get a reference to the terminal's decimals.\\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\\n\\n // Get areference to the terminal's currency.\\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\\n\\n // Get the amount of current overflow.\\n // 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.\\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\\n : _overflowDuring(\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n _projectId,\\n fundingCycle,\\n _currency\\n );\\n\\n // Get the number of outstanding tokens the project has.\\n _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\\n .totalOutstandingTokensOf(_projectId);\\n\\n // Can't redeem more tokens that is in the supply.\\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\\n\\n if (_currentOverflow != 0)\\n // Calculate reclaim amount using the current overflow amount.\\n reclaimAmount = _reclaimableOverflowDuring(\\n _projectId,\\n fundingCycle,\\n _tokenCount,\\n _totalSupply,\\n _currentOverflow\\n );\\n\\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\\n }\\n\\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\\n {\\n // Get a reference to the ballot state.\\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\\n\\n // Create the params that'll be sent to the data source.\\n JBRedeemParamsData memory _data = JBRedeemParamsData(\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n _holder,\\n _projectId,\\n fundingCycle.configuration,\\n _tokenCount,\\n _totalSupply,\\n _currentOverflow,\\n _reclaimedTokenAmount,\\n fundingCycle.useTotalOverflowForRedemptions(),\\n _state == JBBallotState.Active\\n ? fundingCycle.ballotRedemptionRate()\\n : fundingCycle.redemptionRate(),\\n _memo,\\n _metadata\\n );\\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\\n fundingCycle.dataSource()\\n ).redeemParams(_data);\\n }\\n } else {\\n memo = _memo;\\n }\\n }\\n\\n // Keep a reference to the amount that should be subtracted from the project's balance.\\n uint256 _balanceDiff = reclaimAmount;\\n\\n if (delegateAllocations.length != 0) {\\n // Validate all delegated amounts.\\n for (uint256 _i; _i < delegateAllocations.length; ) {\\n // Get a reference to the amount to be delegated.\\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\\n\\n // Validate if non-zero.\\n if (_delegatedAmount != 0)\\n // Increment the total amount being subtracted from the balance.\\n _balanceDiff = _balanceDiff + _delegatedAmount;\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n\\n // The amount being reclaimed must be within the project's balance.\\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\\n\\n // Remove the reclaimed funds from the project's balance.\\n if (_balanceDiff != 0) {\\n unchecked {\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\\n _balanceDiff;\\n }\\n }\\n }\\n\\n /**\\n @notice\\n Records newly distributed funds for a project.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \\n\\n @param _projectId The ID of the project that is having funds distributed.\\n @param _amount The amount to use from the distribution limit, as a fixed point number.\\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\\n\\n @return fundingCycle The funding cycle during which the distribution was made.\\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\\n */\\n function recordDistributionFor(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n )\\n external\\n override\\n nonReentrant\\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\\n {\\n // Get a reference to the project's current funding cycle.\\n fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // The funding cycle must not be configured to have distributions paused.\\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\\n\\n // The new total amount that has been distributed during this funding cycle.\\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\\n IJBSingleTokenPaymentTerminal(msg.sender)\\n ][_projectId][fundingCycle.number] + _amount;\\n\\n // Amount must be within what is still distributable.\\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController3_1(\\n directory.controllerOf(_projectId)\\n ).fundAccessConstraintsStore().distributionLimitOf(\\n _projectId,\\n fundingCycle.configuration,\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n IJBSingleTokenPaymentTerminal(msg.sender).token()\\n );\\n\\n // Make sure the new used amount is within the distribution limit.\\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\\n\\n // Make sure the currencies match.\\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\\n\\n // Get a reference to the terminal's currency.\\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\\n\\n // Convert the amount to the balance's currency.\\n distributedAmount = (_currency == _balanceCurrency)\\n ? _amount\\n : PRBMath.mulDiv(\\n _amount,\\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\\n );\\n\\n // The amount being distributed must be available.\\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\\n\\n // Store the new amount.\\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\\n fundingCycle.number\\n ] = _newUsedDistributionLimitOf;\\n\\n // Removed the distributed funds from the project's token balance.\\n unchecked {\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\\n distributedAmount;\\n }\\n }\\n\\n /**\\n @notice\\n Records newly used allowance funds of a project.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \\n\\n @param _projectId The ID of the project to use the allowance of.\\n @param _amount The amount to use from the allowance, as a fixed point number. \\n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\\n\\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\\n */\\n function recordUsedAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n )\\n external\\n override\\n nonReentrant\\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\\n {\\n // Get a reference to the project's current funding cycle.\\n fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\\n IJBSingleTokenPaymentTerminal(msg.sender)\\n ][_projectId][fundingCycle.configuration] + _amount;\\n\\n // There must be sufficient allowance available.\\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController3_1(\\n directory.controllerOf(_projectId)\\n ).fundAccessConstraintsStore().overflowAllowanceOf(\\n _projectId,\\n fundingCycle.configuration,\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n IJBSingleTokenPaymentTerminal(msg.sender).token()\\n );\\n\\n // Make sure the new used amount is within the allowance.\\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\\n\\n // Make sure the currencies match.\\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\\n\\n // Get a reference to the terminal's currency.\\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\\n\\n // Convert the amount to this store's terminal's token.\\n usedAmount = (_currency == _balanceCurrency)\\n ? _amount\\n : PRBMath.mulDiv(\\n _amount,\\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\\n );\\n\\n // The amount being distributed must be available in the overflow.\\n if (\\n usedAmount >\\n _overflowDuring(\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n _projectId,\\n fundingCycle,\\n _balanceCurrency\\n )\\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\\n\\n // Store the incremented value.\\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\\n fundingCycle.configuration\\n ] = _newUsedOverflowAllowanceOf;\\n\\n // Update the project's balance.\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\\n usedAmount;\\n }\\n\\n /**\\n @notice\\n Records newly added funds for the project.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \\n\\n @param _projectId The ID of the project to which the funds being added belong.\\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\\n */\\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\\n // Increment the balance.\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\\n _amount;\\n }\\n\\n /**\\n @notice\\n Records the migration of funds from this store.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\\n\\n @param _projectId The ID of the project being migrated.\\n\\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\\n */\\n function recordMigration(uint256 _projectId)\\n external\\n override\\n nonReentrant\\n returns (uint256 balance)\\n {\\n // Get a reference to the project's current funding cycle.\\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // Migration must be allowed.\\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\\n\\n // Return the current balance.\\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\\n\\n // Set the balance to 0.\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\\n }\\n\\n //*********************************************************************//\\n // --------------------- private helper functions -------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\\n\\n @dev \\n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\\n\\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\\n @param _overflow The amount of overflow to make the calculation with.\\n\\n @return The amount of overflowed tokens that can be reclaimed.\\n */\\n function _reclaimableOverflowDuring(\\n uint256 _projectId,\\n JBFundingCycle memory _fundingCycle,\\n uint256 _tokenCount,\\n uint256 _totalSupply,\\n uint256 _overflow\\n ) private view returns (uint256) {\\n // If the amount being redeemed is the total supply, return the rest of the overflow.\\n if (_tokenCount == _totalSupply) return _overflow;\\n\\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\\n JBBallotState.Active\\n ? _fundingCycle.ballotRedemptionRate()\\n : _fundingCycle.redemptionRate();\\n\\n // If the redemption rate is 0, nothing is claimable.\\n if (_redemptionRate == 0) return 0;\\n\\n // Get a reference to the linear proportion.\\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\\n\\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\\n\\n return\\n PRBMath.mulDiv(\\n _base,\\n _redemptionRate +\\n PRBMath.mulDiv(\\n _tokenCount,\\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\\n _totalSupply\\n ),\\n JBConstants.MAX_REDEMPTION_RATE\\n );\\n }\\n\\n /**\\n @notice\\n Gets the amount that is overflowing when measured from the specified funding cycle.\\n\\n @dev\\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\\n\\n @param _terminal The terminal for which the overflow is being calculated.\\n @param _projectId The ID of the project to get overflow for.\\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\\n\\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\\n */\\n function _overflowDuring(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n JBFundingCycle memory _fundingCycle,\\n uint256 _balanceCurrency\\n ) private view returns (uint256) {\\n // Get the current balance of the project.\\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\\n\\n // If there's no balance, there's no overflow.\\n if (_balanceOf == 0) return 0;\\n\\n // Get a reference to the distribution limit during the funding cycle.\\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController3_1(\\n directory.controllerOf(_projectId)\\n ).fundAccessConstraintsStore().distributionLimitOf(\\n _projectId,\\n _fundingCycle.configuration,\\n _terminal,\\n _terminal.token()\\n );\\n\\n // Get a reference to the amount still distributable during the funding cycle.\\n uint256 _distributionLimitRemaining = _distributionLimit -\\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\\n\\n // Convert the _distributionRemaining to be in terms of the provided currency.\\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\\n _distributionLimitRemaining = PRBMath.mulDiv(\\n _distributionLimitRemaining,\\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\\n );\\n\\n // Overflow is the balance of this project minus the amount that can still be distributed.\\n unchecked {\\n return\\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\\n }\\n }\\n\\n /**\\n @notice\\n Gets the amount that is currently overflowing across all of a project's terminals. \\n\\n @dev\\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\\n\\n @param _projectId The ID of the project to get the total overflow for.\\n @param _decimals The number of decimals that the fixed point overflow should include.\\n @param _currency The currency that the overflow should be in terms of.\\n\\n @return overflow The total overflow of a project's funds.\\n */\\n function _currentTotalOverflowOf(\\n uint256 _projectId,\\n uint256 _decimals,\\n uint256 _currency\\n ) private view returns (uint256) {\\n // Get a reference to the project's terminals.\\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\\n\\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\\n uint256 _ethOverflow;\\n\\n // Add the current ETH overflow for each terminal.\\n for (uint256 _i; _i < _terminals.length; ) {\\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\\n unchecked {\\n ++_i;\\n }\\n }\\n\\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.ETH\\n ? _ethOverflow\\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.ETH, _currency, 18));\\n\\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\\n return\\n (_decimals == 18)\\n ? _totalOverflow18Decimal\\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\\n }\\n}\\n\",\"keccak256\":\"0x7fc9e05a77c0d37c10709df6f479562d73d684b9aec28d0227e83beffa4d2a01\",\"license\":\"MIT\"},\"contracts/enums/JBBallotState.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nenum JBBallotState {\\n Active,\\n Approved,\\n Failed\\n}\\n\",\"keccak256\":\"0x891fcac63470398b3a11239da7feba6b07d640809fcefd2404303b823d7378f8\",\"license\":\"MIT\"},\"contracts/interfaces/IJBController.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBFundAccessConstraints.sol';\\nimport './../structs/JBFundingCycleData.sol';\\nimport './../structs/JBFundingCycleMetadata.sol';\\nimport './../structs/JBGroupedSplits.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBMigratable.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBSplitsStore.sol';\\nimport './IJBTokenStore.sol';\\n\\ninterface IJBController is IERC165 {\\n event LaunchProject(uint256 configuration, uint256 projectId, string memo, address caller);\\n\\n event LaunchFundingCycles(uint256 configuration, uint256 projectId, string memo, address caller);\\n\\n event ReconfigureFundingCycles(\\n uint256 configuration,\\n uint256 projectId,\\n string memo,\\n address caller\\n );\\n\\n event SetFundAccessConstraints(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n JBFundAccessConstraints constraints,\\n address caller\\n );\\n\\n event DistributeReservedTokens(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address beneficiary,\\n uint256 tokenCount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n address caller\\n );\\n\\n event DistributeToReservedTokenSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n uint256 tokenCount,\\n address caller\\n );\\n\\n event MintTokens(\\n address indexed beneficiary,\\n uint256 indexed projectId,\\n uint256 tokenCount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n uint256 reservedRate,\\n address caller\\n );\\n\\n event BurnTokens(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 tokenCount,\\n string memo,\\n address caller\\n );\\n\\n event Migrate(uint256 indexed projectId, IJBMigratable to, address caller);\\n\\n event PrepMigration(uint256 indexed projectId, address from, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function tokenStore() external view returns (IJBTokenStore);\\n\\n function splitsStore() external view returns (IJBSplitsStore);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function reservedTokenBalanceOf(uint256 _projectId, uint256 _reservedRate)\\n external\\n view\\n returns (uint256);\\n\\n function distributionLimitOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n IJBPaymentTerminal _terminal,\\n address _token\\n ) external view returns (uint256 distributionLimit, uint256 distributionLimitCurrency);\\n\\n function overflowAllowanceOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n IJBPaymentTerminal _terminal,\\n address _token\\n ) external view returns (uint256 overflowAllowance, uint256 overflowAllowanceCurrency);\\n\\n function totalOutstandingTokensOf(uint256 _projectId, uint256 _reservedRate)\\n external\\n view\\n returns (uint256);\\n\\n function getFundingCycleOf(uint256 _projectId, uint256 _configuration)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function latestConfiguredFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (\\n JBFundingCycle memory,\\n JBFundingCycleMetadata memory metadata,\\n JBBallotState\\n );\\n\\n function currentFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function queuedFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function launchProjectFor(\\n address _owner,\\n JBProjectMetadata calldata _projectMetadata,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n IJBPaymentTerminal[] memory _terminals,\\n string calldata _memo\\n ) external returns (uint256 projectId);\\n\\n function launchFundingCyclesFor(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n IJBPaymentTerminal[] memory _terminals,\\n string calldata _memo\\n ) external returns (uint256 configuration);\\n\\n function reconfigureFundingCyclesOf(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n string calldata _memo\\n ) external returns (uint256);\\n\\n function mintTokensOf(\\n uint256 _projectId,\\n uint256 _tokenCount,\\n address _beneficiary,\\n string calldata _memo,\\n bool _preferClaimedTokens,\\n bool _useReservedRate\\n ) external returns (uint256 beneficiaryTokenCount);\\n\\n function burnTokensOf(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n string calldata _memo,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function distributeReservedTokensOf(uint256 _projectId, string memory _memo)\\n external\\n returns (uint256);\\n\\n function migrate(uint256 _projectId, IJBMigratable _to) external;\\n}\\n\",\"keccak256\":\"0xb1ee4b41f2a06f28f69c74cb729b8964f2e75f3c545a68f85bd9082b5575bc85\",\"license\":\"MIT\"},\"contracts/interfaces/IJBController3_0_1.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBFundAccessConstraints.sol';\\nimport './../structs/JBFundingCycleData.sol';\\nimport './../structs/JBFundingCycleMetadata.sol';\\nimport './../structs/JBGroupedSplits.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBController.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBMigratable.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBSplitsStore.sol';\\nimport './IJBTokenStore.sol';\\n\\ninterface IJBController3_0_1 {\\n function reservedTokenBalanceOf(uint256 _projectId) external view returns (uint256);\\n function totalOutstandingTokensOf(uint256 _projectId) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xf853badd9b8c149b7e1cd01b1123a949bc64036cfcc9e4b6d237b6911eccb058\",\"license\":\"MIT\"},\"contracts/interfaces/IJBController3_1.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBFundAccessConstraints.sol';\\nimport './../structs/JBFundingCycleData.sol';\\nimport './../structs/JBFundingCycleMetadata.sol';\\nimport './../structs/JBGroupedSplits.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBController3_0_1.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFundAccessConstraintsStore.sol';\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBMigratable.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBSplitsStore.sol';\\nimport './IJBTokenStore.sol';\\n\\ninterface IJBController3_1 is IJBController3_0_1, IERC165 {\\n event LaunchProject(uint256 configuration, uint256 projectId, string memo, address caller);\\n\\n event LaunchFundingCycles(uint256 configuration, uint256 projectId, string memo, address caller);\\n\\n event ReconfigureFundingCycles(\\n uint256 configuration,\\n uint256 projectId,\\n string memo,\\n address caller\\n );\\n\\n event DistributeReservedTokens(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address beneficiary,\\n uint256 tokenCount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n address caller\\n );\\n\\n event DistributeToReservedTokenSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n uint256 tokenCount,\\n address caller\\n );\\n\\n event MintTokens(\\n address indexed beneficiary,\\n uint256 indexed projectId,\\n uint256 tokenCount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n uint256 reservedRate,\\n address caller\\n );\\n\\n event BurnTokens(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 tokenCount,\\n string memo,\\n address caller\\n );\\n\\n event Migrate(uint256 indexed projectId, IJBMigratable to, address caller);\\n\\n event PrepMigration(uint256 indexed projectId, address from, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function tokenStore() external view returns (IJBTokenStore);\\n\\n function splitsStore() external view returns (IJBSplitsStore);\\n\\n function fundAccessConstraintsStore() external view returns (IJBFundAccessConstraintsStore);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function reservedTokenBalanceOf(uint256 _projectId) external view returns (uint256);\\n\\n function totalOutstandingTokensOf(uint256 _projectId) external view returns (uint256);\\n\\n function getFundingCycleOf(uint256 _projectId, uint256 _configuration)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function latestConfiguredFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (\\n JBFundingCycle memory,\\n JBFundingCycleMetadata memory metadata,\\n JBBallotState\\n );\\n\\n function currentFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function queuedFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function launchProjectFor(\\n address _owner,\\n JBProjectMetadata calldata _projectMetadata,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n IJBPaymentTerminal[] memory _terminals,\\n string calldata _memo\\n ) external returns (uint256 projectId);\\n\\n function launchFundingCyclesFor(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n IJBPaymentTerminal[] memory _terminals,\\n string calldata _memo\\n ) external returns (uint256 configuration);\\n\\n function reconfigureFundingCyclesOf(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n string calldata _memo\\n ) external returns (uint256);\\n\\n function mintTokensOf(\\n uint256 _projectId,\\n uint256 _tokenCount,\\n address _beneficiary,\\n string calldata _memo,\\n bool _preferClaimedTokens,\\n bool _useReservedRate\\n ) external returns (uint256 beneficiaryTokenCount);\\n\\n function burnTokensOf(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n string calldata _memo,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function distributeReservedTokensOf(uint256 _projectId, string memory _memo)\\n external\\n returns (uint256);\\n\\n function migrate(uint256 _projectId, IJBMigratable _to) external;\\n}\\n\",\"keccak256\":\"0x9aea97f1a77f48d313aee6c9ea97dffdfdb4f50c1cfd94f0b360a8ce6e383f4c\",\"license\":\"MIT\"},\"contracts/interfaces/IJBDirectory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBProjects.sol';\\n\\ninterface IJBDirectory {\\n event SetController(uint256 indexed projectId, address indexed controller, address caller);\\n\\n event AddTerminal(uint256 indexed projectId, IJBPaymentTerminal indexed terminal, address caller);\\n\\n event SetTerminals(uint256 indexed projectId, IJBPaymentTerminal[] terminals, address caller);\\n\\n event SetPrimaryTerminal(\\n uint256 indexed projectId,\\n address indexed token,\\n IJBPaymentTerminal indexed terminal,\\n address caller\\n );\\n\\n event SetIsAllowedToSetFirstController(address indexed addr, bool indexed flag, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function controllerOf(uint256 _projectId) external view returns (address);\\n\\n function isAllowedToSetFirstController(address _address) external view returns (bool);\\n\\n function terminalsOf(uint256 _projectId) external view returns (IJBPaymentTerminal[] memory);\\n\\n function isTerminalOf(uint256 _projectId, IJBPaymentTerminal _terminal)\\n external\\n view\\n returns (bool);\\n\\n function primaryTerminalOf(uint256 _projectId, address _token)\\n external\\n view\\n returns (IJBPaymentTerminal);\\n\\n function setControllerOf(uint256 _projectId, address _controller) external;\\n\\n function setTerminalsOf(uint256 _projectId, IJBPaymentTerminal[] calldata _terminals) external;\\n\\n function setPrimaryTerminalOf(\\n uint256 _projectId,\\n address _token,\\n IJBPaymentTerminal _terminal\\n ) external;\\n\\n function setIsAllowedToSetFirstController(address _address, bool _flag) external;\\n}\\n\",\"keccak256\":\"0x715321646db00514d1355ed43c40cd3f01e94959552fd07797b315d9c49cdb1d\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundAccessConstraintsStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBFundAccessConstraints.sol';\\nimport './IJBPaymentTerminal.sol';\\n\\ninterface IJBFundAccessConstraintsStore is IERC165 {\\n event SetFundAccessConstraints(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed projectId,\\n JBFundAccessConstraints constraints,\\n address caller\\n );\\n\\n function distributionLimitOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n IJBPaymentTerminal _terminal,\\n address _token\\n ) external view returns (uint256 distributionLimit, uint256 distributionLimitCurrency);\\n\\n function overflowAllowanceOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n IJBPaymentTerminal _terminal,\\n address _token\\n ) external view returns (uint256 overflowAllowance, uint256 overflowAllowanceCurrency);\\n\\n function setFor(\\n uint256 _projectId,\\n uint256 _configuration,\\n JBFundAccessConstraints[] memory _fundAccessConstaints\\n ) external;\\n}\\n\",\"keccak256\":\"0x3158c6cab1b81827a5a2d90a5936a0c7f8ba0d1bcdb05ae8b8a1ac7f03d0c999\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleBallot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../enums/JBBallotState.sol';\\n\\ninterface IJBFundingCycleBallot is IERC165 {\\n function duration() external view returns (uint256);\\n\\n function stateOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n uint256 _start\\n ) external view returns (JBBallotState);\\n}\\n\",\"keccak256\":\"0x49553a56209237846bc400cf27f260824a6bd06fd8094a7eb5abb9de75779598\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleDataSource.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBPayDelegateAllocation.sol';\\nimport './../structs/JBPayParamsData.sol';\\nimport './../structs/JBRedeemParamsData.sol';\\nimport './../structs/JBRedemptionDelegateAllocation.sol';\\n\\n/**\\n @title\\n Datasource\\n\\n @notice\\n The datasource is called by JBPaymentTerminal on pay and redemption, and provide an extra layer of logic to use \\n a custom weight, a custom memo and/or a pay/redeem delegate\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n*/\\ninterface IJBFundingCycleDataSource is IERC165 {\\n /**\\n @notice\\n The datasource implementation for JBPaymentTerminal.pay(..)\\n\\n @param _data the data passed to the data source in terminal.pay(..), as a JBPayParamsData struct:\\n IJBPaymentTerminal terminal;\\n address payer;\\n JBTokenAmount amount;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n address beneficiary;\\n uint256 weight;\\n uint256 reservedRate;\\n string memo;\\n bytes metadata;\\n\\n @return weight the weight to use to override the funding cycle weight\\n @return memo the memo to override the pay(..) memo\\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\\n */\\n function payParams(JBPayParamsData calldata _data)\\n external\\n returns (\\n uint256 weight,\\n string memory memo,\\n JBPayDelegateAllocation[] memory delegateAllocations\\n );\\n\\n /**\\n @notice\\n The datasource implementation for JBPaymentTerminal.redeemTokensOf(..)\\n\\n @param _data the data passed to the data source in terminal.redeemTokensOf(..), as a JBRedeemParamsData struct:\\n IJBPaymentTerminal terminal;\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 tokenCount;\\n uint256 totalSupply;\\n uint256 overflow;\\n JBTokenAmount reclaimAmount;\\n bool useTotalOverflow;\\n uint256 redemptionRate;\\n uint256 ballotRedemptionRate;\\n string memo;\\n bytes metadata;\\n\\n @return reclaimAmount The amount to claim, overriding the terminal logic.\\n @return memo The memo to override the redeemTokensOf(..) memo.\\n @return delegateAllocations The amount to send to delegates instead of adding to the beneficiary.\\n */\\n function redeemParams(JBRedeemParamsData calldata _data)\\n external\\n returns (\\n uint256 reclaimAmount,\\n string memory memo,\\n JBRedemptionDelegateAllocation[] memory delegateAllocations\\n );\\n}\\n\",\"keccak256\":\"0xa424abc146a61b69db83e511c064492da6fab6d8226e13d1580bc9fbc50d6738\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../enums/JBBallotState.sol';\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBFundingCycleData.sol';\\n\\ninterface IJBFundingCycleStore {\\n event Configure(\\n uint256 indexed configuration,\\n uint256 indexed projectId,\\n JBFundingCycleData data,\\n uint256 metadata,\\n uint256 mustStartAtOrAfter,\\n address caller\\n );\\n\\n event Init(uint256 indexed configuration, uint256 indexed projectId, uint256 indexed basedOn);\\n\\n function latestConfigurationOf(uint256 _projectId) external view returns (uint256);\\n\\n function get(uint256 _projectId, uint256 _configuration)\\n external\\n view\\n returns (JBFundingCycle memory);\\n\\n function latestConfiguredOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBBallotState ballotState);\\n\\n function queuedOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentBallotStateOf(uint256 _projectId) external view returns (JBBallotState);\\n\\n function configureFor(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n uint256 _metadata,\\n uint256 _mustStartAtOrAfter\\n ) external returns (JBFundingCycle memory fundingCycle);\\n}\\n\",\"keccak256\":\"0xaead823851433be0c2ddc8f8086813e6cd647de3a1bc0f7570a5d6b38c378b5a\",\"license\":\"MIT\"},\"contracts/interfaces/IJBMigratable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBMigratable {\\n function prepForMigrationOf(uint256 _projectId, address _from) external;\\n}\\n\",\"keccak256\":\"0xc81053e4b4754fc510aa04fecd3ab1460f01e3e27761e7a8c94f631a978ae127\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPayDelegate.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBDidPayData.sol';\\n\\n/**\\n @title\\n Pay delegate\\n\\n @notice\\n Delegate called after JBTerminal.pay(..) logic completion (if passed by the funding cycle datasource)\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n*/\\ninterface IJBPayDelegate is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.pay(..), after the execution of its logic\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control\\n \\n @param _data the data passed by the terminal, as a JBDidPayData struct:\\n address payer;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n JBTokenAmount amount;\\n JBTokenAmount forwardedAmount;\\n uint256 projectTokenCount;\\n address beneficiary;\\n bool preferClaimedTokens;\\n string memo;\\n bytes metadata;\\n */\\n function didPay(JBDidPayData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0xa797de18b69eceba117e1f0b3810cf3cc2d2791417d580a5bdc510d1b868ab26\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\n\\ninterface IJBPaymentTerminal is IERC165 {\\n function acceptsToken(address _token, uint256 _projectId) external view returns (bool);\\n\\n function currencyForToken(address _token) external view returns (uint256);\\n\\n function decimalsForToken(address _token) external view returns (uint256);\\n\\n // Return value must be a fixed point number with 18 decimals.\\n function currentEthOverflowOf(uint256 _projectId) external view returns (uint256);\\n\\n function pay(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable returns (uint256 beneficiaryTokenCount);\\n\\n function addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable;\\n}\\n\",\"keccak256\":\"0xb7826f5ed609359ce322c09e83236c47ba385df1c3cad3607e56fd0a2e00eee2\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPriceFeed.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBPriceFeed {\\n function currentPrice(uint256 _targetDecimals) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x57c71282fec1b34b00cf991ffed2e36031c393e35bfa7ca5d723eb6572fb7122\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPrices.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBPriceFeed.sol';\\n\\ninterface IJBPrices {\\n event AddFeed(uint256 indexed currency, uint256 indexed base, IJBPriceFeed feed);\\n\\n function feedFor(uint256 _currency, uint256 _base) external view returns (IJBPriceFeed);\\n\\n function priceFor(\\n uint256 _currency,\\n uint256 _base,\\n uint256 _decimals\\n ) external view returns (uint256);\\n\\n function addFeedFor(\\n uint256 _currency,\\n uint256 _base,\\n IJBPriceFeed _priceFeed\\n ) external;\\n}\\n\",\"keccak256\":\"0x82a175b1f4b95b506c98406576cd59cbe04615e3df24f9cf3587b61b8ee323b1\",\"license\":\"MIT\"},\"contracts/interfaces/IJBProjects.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBTokenUriResolver.sol';\\n\\ninterface IJBProjects is IERC721 {\\n event Create(\\n uint256 indexed projectId,\\n address indexed owner,\\n JBProjectMetadata metadata,\\n address caller\\n );\\n\\n event SetMetadata(uint256 indexed projectId, JBProjectMetadata metadata, address caller);\\n\\n event SetTokenUriResolver(IJBTokenUriResolver indexed resolver, address caller);\\n\\n function count() external view returns (uint256);\\n\\n function metadataContentOf(uint256 _projectId, uint256 _domain)\\n external\\n view\\n returns (string memory);\\n\\n function tokenUriResolver() external view returns (IJBTokenUriResolver);\\n\\n function createFor(address _owner, JBProjectMetadata calldata _metadata)\\n external\\n returns (uint256 projectId);\\n\\n function setMetadataOf(uint256 _projectId, JBProjectMetadata calldata _metadata) external;\\n\\n function setTokenUriResolver(IJBTokenUriResolver _newResolver) external;\\n}\\n\",\"keccak256\":\"0x7cfc021d0bd7e73b1ba8f4845d7d35e3419d6a14d3d25ca3a8010e7f91062fe4\",\"license\":\"MIT\"},\"contracts/interfaces/IJBRedemptionDelegate.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBDidRedeemData.sol';\\n\\n/**\\n @title\\n Redemption delegate\\n\\n @notice\\n Delegate called after JBTerminal.redeemTokensOf(..) logic completion (if passed by the funding cycle datasource)\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n*/\\ninterface IJBRedemptionDelegate is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.redeemTokensOf(..), after the execution of its logic\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control\\n \\n @param _data the data passed by the terminal, as a JBDidRedeemData struct:\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 projectTokenCount;\\n JBTokenAmount reclaimedAmount;\\n JBTokenAmount forwardedAmount;\\n address payable beneficiary;\\n string memo;\\n bytes metadata;\\n */\\n function didRedeem(JBDidRedeemData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0x172d2c0be65e72e54f71ae521907067f0fa30e8ca05c4f88826903208aa437e2\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSingleTokenPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBPaymentTerminal.sol';\\n\\ninterface IJBSingleTokenPaymentTerminal is IJBPaymentTerminal {\\n function token() external view returns (address);\\n\\n function currency() external view returns (uint256);\\n\\n function decimals() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xf6e78323caa9af7bbf024f44b2032a83fed0394e0b3a242a6346e73c85b2e46f\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSingleTokenPaymentTerminalStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBPayDelegateAllocation.sol';\\nimport './../structs/JBRedemptionDelegateAllocation.sol';\\nimport './../structs/JBTokenAmount.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBPrices.sol';\\nimport './IJBSingleTokenPaymentTerminal.sol';\\n\\ninterface IJBSingleTokenPaymentTerminalStore {\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function prices() external view returns (IJBPrices);\\n\\n function balanceOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\\n external\\n view\\n returns (uint256);\\n\\n function usedDistributionLimitOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _fundingCycleNumber\\n ) external view returns (uint256);\\n\\n function usedOverflowAllowanceOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _fundingCycleConfiguration\\n ) external view returns (uint256);\\n\\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\\n external\\n view\\n returns (uint256);\\n\\n function currentTotalOverflowOf(\\n uint256 _projectId,\\n uint256 _decimals,\\n uint256 _currency\\n ) external view returns (uint256);\\n\\n function currentReclaimableOverflowOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n bool _useTotalOverflow\\n ) external view returns (uint256);\\n\\n function currentReclaimableOverflowOf(\\n uint256 _projectId,\\n uint256 _tokenCount,\\n uint256 _totalSupply,\\n uint256 _overflow\\n ) external view returns (uint256);\\n\\n function recordPaymentFrom(\\n address _payer,\\n JBTokenAmount memory _amount,\\n uint256 _projectId,\\n uint256 _baseWeightCurrency,\\n address _beneficiary,\\n string calldata _memo,\\n bytes calldata _metadata\\n )\\n external\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 tokenCount,\\n JBPayDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n );\\n\\n function recordRedemptionFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n string calldata _memo,\\n bytes calldata _metadata\\n )\\n external\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 reclaimAmount,\\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n );\\n\\n function recordDistributionFor(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n ) external returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount);\\n\\n function recordUsedAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n ) external returns (JBFundingCycle memory fundingCycle, uint256 withdrawnAmount);\\n\\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external;\\n\\n function recordMigration(uint256 _projectId) external returns (uint256 balance);\\n}\\n\",\"keccak256\":\"0xd78929c9371fd7895b829ef5e4ad4b3786523c3580ac3f6f5f25d2b5941c0dd3\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSplitAllocator.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport '../structs/JBSplitAllocationData.sol';\\n\\n/**\\n @title\\n Split allocator\\n\\n @notice\\n Provide a way to process a single split with extra logic\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n\\n @dev\\n The contract address should be set as an allocator in the adequate split\\n*/\\ninterface IJBSplitAllocator is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.distributePayoutOf(..), during the processing of the split including it\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control. The token and/or eth are optimistically transfered\\n to the allocator for its logic.\\n \\n @param _data the data passed by the terminal, as a JBSplitAllocationData struct:\\n address token;\\n uint256 amount;\\n uint256 decimals;\\n uint256 projectId;\\n uint256 group;\\n JBSplit split;\\n */\\n function allocate(JBSplitAllocationData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0x5efb6f51fc161f42ff58989386ad99028e4039a0ba897d66f358c3dfcf686105\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSplitsStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBGroupedSplits.sol';\\nimport './../structs/JBSplit.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBProjects.sol';\\n\\ninterface IJBSplitsStore {\\n event SetSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n address caller\\n );\\n\\n function projects() external view returns (IJBProjects);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function splitsOf(\\n uint256 _projectId,\\n uint256 _domain,\\n uint256 _group\\n ) external view returns (JBSplit[] memory);\\n\\n function set(\\n uint256 _projectId,\\n uint256 _domain,\\n JBGroupedSplits[] memory _groupedSplits\\n ) external;\\n}\\n\",\"keccak256\":\"0x66dab3dd394e318b850401ca92c2963b906cc0ad5562fa5d4f6f850175d1c77a\",\"license\":\"MIT\"},\"contracts/interfaces/IJBToken.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBToken {\\n function projectId() external view returns (uint256);\\n\\n function decimals() external view returns (uint8);\\n\\n function totalSupply(uint256 _projectId) external view returns (uint256);\\n\\n function balanceOf(address _account, uint256 _projectId) external view returns (uint256);\\n\\n function mint(\\n uint256 _projectId,\\n address _account,\\n uint256 _amount\\n ) external;\\n\\n function burn(\\n uint256 _projectId,\\n address _account,\\n uint256 _amount\\n ) external;\\n\\n function approve(\\n uint256,\\n address _spender,\\n uint256 _amount\\n ) external;\\n\\n function transfer(\\n uint256 _projectId,\\n address _to,\\n uint256 _amount\\n ) external;\\n\\n function transferFrom(\\n uint256 _projectId,\\n address _from,\\n address _to,\\n uint256 _amount\\n ) external;\\n}\\n\",\"keccak256\":\"0xe8969210417736c85d71101bf1c0bd8ebbf9d1e62a93e758148bd5709a6c7097\",\"license\":\"MIT\"},\"contracts/interfaces/IJBTokenStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBProjects.sol';\\nimport './IJBToken.sol';\\n\\ninterface IJBTokenStore {\\n event Issue(\\n uint256 indexed projectId,\\n IJBToken indexed token,\\n string name,\\n string symbol,\\n address caller\\n );\\n\\n event Mint(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 amount,\\n bool tokensWereClaimed,\\n bool preferClaimedTokens,\\n address caller\\n );\\n\\n event Burn(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 amount,\\n uint256 initialUnclaimedBalance,\\n uint256 initialClaimedBalance,\\n bool preferClaimedTokens,\\n address caller\\n );\\n\\n event Claim(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 initialUnclaimedBalance,\\n uint256 amount,\\n address caller\\n );\\n\\n event Set(uint256 indexed projectId, IJBToken indexed newToken, address caller);\\n\\n event Transfer(\\n address indexed holder,\\n uint256 indexed projectId,\\n address indexed recipient,\\n uint256 amount,\\n address caller\\n );\\n\\n function tokenOf(uint256 _projectId) external view returns (IJBToken);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function unclaimedBalanceOf(address _holder, uint256 _projectId) external view returns (uint256);\\n\\n function unclaimedTotalSupplyOf(uint256 _projectId) external view returns (uint256);\\n\\n function totalSupplyOf(uint256 _projectId) external view returns (uint256);\\n\\n function balanceOf(address _holder, uint256 _projectId) external view returns (uint256 _result);\\n\\n function issueFor(\\n uint256 _projectId,\\n string calldata _name,\\n string calldata _symbol\\n ) external returns (IJBToken token);\\n\\n function setFor(uint256 _projectId, IJBToken _token) external;\\n\\n function burnFrom(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function mintFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function claimFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount\\n ) external;\\n\\n function transferFrom(\\n address _holder,\\n uint256 _projectId,\\n address _recipient,\\n uint256 _amount\\n ) external;\\n}\\n\",\"keccak256\":\"0x98459e3af050d41dfeffdc97f1c93330207ba450f8ff3613224b49a89eeca9c6\",\"license\":\"MIT\"},\"contracts/interfaces/IJBTokenUriResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBTokenUriResolver {\\n function getUri(uint256 _projectId) external view returns (string memory tokenUri);\\n}\\n\",\"keccak256\":\"0xd267fd8ca7c21c2c71794acdb9a98314c33a35fc559e0bf0897a6686d196d174\",\"license\":\"MIT\"},\"contracts/libraries/JBConstants.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/**\\n @notice\\n Global constants used across Juicebox contracts.\\n*/\\nlibrary JBConstants {\\n uint256 public constant MAX_RESERVED_RATE = 10_000;\\n uint256 public constant MAX_REDEMPTION_RATE = 10_000;\\n uint256 public constant MAX_DISCOUNT_RATE = 1_000_000_000;\\n uint256 public constant SPLITS_TOTAL_PERCENT = 1_000_000_000;\\n uint256 public constant MAX_FEE = 1_000_000_000;\\n uint256 public constant MAX_FEE_DISCOUNT = 1_000_000_000;\\n}\\n\",\"keccak256\":\"0x34362846a1cd428a8bdedf4ab6857e11402f345cb87b994b2e7fb6d2474b808d\",\"license\":\"MIT\"},\"contracts/libraries/JBCurrencies.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBCurrencies {\\n uint256 public constant ETH = 1;\\n uint256 public constant USD = 2;\\n}\\n\",\"keccak256\":\"0x7e417ff25c173608ee4fe6d9fc3dcd5e1458c78c889af12bac47b1189a436076\",\"license\":\"MIT\"},\"contracts/libraries/JBFixedPointNumber.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nlibrary JBFixedPointNumber {\\n function adjustDecimals(\\n uint256 _value,\\n uint256 _decimals,\\n uint256 _targetDecimals\\n ) internal pure returns (uint256) {\\n // If decimals need adjusting, multiply or divide the price by the decimal adjuster to get the normalized result.\\n if (_targetDecimals == _decimals) return _value;\\n else if (_targetDecimals > _decimals) return _value * 10**(_targetDecimals - _decimals);\\n else return _value / 10**(_decimals - _targetDecimals);\\n }\\n}\\n\",\"keccak256\":\"0x18efac48269f3a3bd7e9a1c770776f950e0afa86769e6f8b128002c3b8c6742c\",\"license\":\"MIT\"},\"contracts/libraries/JBFundingCycleMetadataResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBFundingCycleMetadata.sol';\\nimport './../structs/JBGlobalFundingCycleMetadata.sol';\\nimport './JBConstants.sol';\\nimport './JBGlobalFundingCycleMetadataResolver.sol';\\n\\nlibrary JBFundingCycleMetadataResolver {\\n function global(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (JBGlobalFundingCycleMetadata memory)\\n {\\n return JBGlobalFundingCycleMetadataResolver.expandMetadata(uint8(_fundingCycle.metadata >> 8));\\n }\\n\\n function reservedRate(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n return uint256(uint16(_fundingCycle.metadata >> 24));\\n }\\n\\n function redemptionRate(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n // Redemption rate is a number 0-10000. It's inverse was stored so the most common case of 100% results in no storage needs.\\n return JBConstants.MAX_REDEMPTION_RATE - uint256(uint16(_fundingCycle.metadata >> 40));\\n }\\n\\n function ballotRedemptionRate(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (uint256)\\n {\\n // Redemption rate is a number 0-10000. It's inverse was stored so the most common case of 100% results in no storage needs.\\n return JBConstants.MAX_REDEMPTION_RATE - uint256(uint16(_fundingCycle.metadata >> 56));\\n }\\n\\n function payPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 72) & 1) == 1;\\n }\\n\\n function distributionsPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 73) & 1) == 1;\\n }\\n\\n function redeemPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 74) & 1) == 1;\\n }\\n\\n function burnPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 75) & 1) == 1;\\n }\\n\\n function mintingAllowed(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 76) & 1) == 1;\\n }\\n\\n function terminalMigrationAllowed(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 77) & 1) == 1;\\n }\\n\\n function controllerMigrationAllowed(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 78) & 1) == 1;\\n }\\n\\n function shouldHoldFees(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 79) & 1) == 1;\\n }\\n\\n function preferClaimedTokenOverride(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 80) & 1) == 1;\\n }\\n\\n function useTotalOverflowForRedemptions(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 81) & 1) == 1;\\n }\\n\\n function useDataSourceForPay(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return (_fundingCycle.metadata >> 82) & 1 == 1;\\n }\\n\\n function useDataSourceForRedeem(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return (_fundingCycle.metadata >> 83) & 1 == 1;\\n }\\n\\n function dataSource(JBFundingCycle memory _fundingCycle) internal pure returns (address) {\\n return address(uint160(_fundingCycle.metadata >> 84));\\n }\\n\\n function metadata(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n return uint256(uint8(_fundingCycle.metadata >> 244));\\n }\\n\\n /**\\n @notice\\n Pack the funding cycle metadata.\\n\\n @param _metadata The metadata to validate and pack.\\n\\n @return packed The packed uint256 of all metadata params. The first 8 bits specify the version.\\n */\\n function packFundingCycleMetadata(JBFundingCycleMetadata memory _metadata)\\n internal\\n pure\\n returns (uint256 packed)\\n {\\n // version 1 in the bits 0-7 (8 bits).\\n packed = 1;\\n // global metadta in bits 8-23 (16 bits).\\n packed |=\\n JBGlobalFundingCycleMetadataResolver.packFundingCycleGlobalMetadata(_metadata.global) <<\\n 8;\\n // reserved rate in bits 24-39 (16 bits).\\n packed |= _metadata.reservedRate << 24;\\n // redemption rate in bits 40-55 (16 bits).\\n // redemption rate is a number 0-10000. Store the reverse so the most common case of 100% results in no storage needs.\\n packed |= (JBConstants.MAX_REDEMPTION_RATE - _metadata.redemptionRate) << 40;\\n // ballot redemption rate rate in bits 56-71 (16 bits).\\n // ballot redemption rate is a number 0-10000. Store the reverse so the most common case of 100% results in no storage needs.\\n packed |= (JBConstants.MAX_REDEMPTION_RATE - _metadata.ballotRedemptionRate) << 56;\\n // pause pay in bit 72.\\n if (_metadata.pausePay) packed |= 1 << 72;\\n // pause tap in bit 73.\\n if (_metadata.pauseDistributions) packed |= 1 << 73;\\n // pause redeem in bit 74.\\n if (_metadata.pauseRedeem) packed |= 1 << 74;\\n // pause burn in bit 75.\\n if (_metadata.pauseBurn) packed |= 1 << 75;\\n // allow minting in bit 76.\\n if (_metadata.allowMinting) packed |= 1 << 76;\\n // allow terminal migration in bit 77.\\n if (_metadata.allowTerminalMigration) packed |= 1 << 77;\\n // allow controller migration in bit 78.\\n if (_metadata.allowControllerMigration) packed |= 1 << 78;\\n // hold fees in bit 79.\\n if (_metadata.holdFees) packed |= 1 << 79;\\n // prefer claimed token override in bit 80.\\n if (_metadata.preferClaimedTokenOverride) packed |= 1 << 80;\\n // useTotalOverflowForRedemptions in bit 81.\\n if (_metadata.useTotalOverflowForRedemptions) packed |= 1 << 81;\\n // use pay data source in bit 82.\\n if (_metadata.useDataSourceForPay) packed |= 1 << 82;\\n // use redeem data source in bit 83.\\n if (_metadata.useDataSourceForRedeem) packed |= 1 << 83;\\n // data source address in bits 84-243.\\n packed |= uint256(uint160(address(_metadata.dataSource))) << 84;\\n // metadata in bits 244-252 (8 bits).\\n packed |= _metadata.metadata << 244;\\n }\\n\\n /**\\n @notice\\n Expand the funding cycle metadata.\\n\\n @param _fundingCycle The funding cycle having its metadata expanded.\\n\\n @return metadata The metadata object.\\n */\\n function expandMetadata(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (JBFundingCycleMetadata memory)\\n {\\n return\\n JBFundingCycleMetadata(\\n global(_fundingCycle),\\n reservedRate(_fundingCycle),\\n redemptionRate(_fundingCycle),\\n ballotRedemptionRate(_fundingCycle),\\n payPaused(_fundingCycle),\\n distributionsPaused(_fundingCycle),\\n redeemPaused(_fundingCycle),\\n burnPaused(_fundingCycle),\\n mintingAllowed(_fundingCycle),\\n terminalMigrationAllowed(_fundingCycle),\\n controllerMigrationAllowed(_fundingCycle),\\n shouldHoldFees(_fundingCycle),\\n preferClaimedTokenOverride(_fundingCycle),\\n useTotalOverflowForRedemptions(_fundingCycle),\\n useDataSourceForPay(_fundingCycle),\\n useDataSourceForRedeem(_fundingCycle),\\n dataSource(_fundingCycle),\\n metadata(_fundingCycle)\\n );\\n }\\n}\\n\",\"keccak256\":\"0x3d045c38593102cfb6ac67f3ddf2232e1ff5518d6d021423ae2681387599fbd3\",\"license\":\"MIT\"},\"contracts/libraries/JBGlobalFundingCycleMetadataResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport './../structs/JBFundingCycleMetadata.sol';\\n\\nlibrary JBGlobalFundingCycleMetadataResolver {\\n function setTerminalsAllowed(uint8 _data) internal pure returns (bool) {\\n return (_data & 1) == 1;\\n }\\n\\n function setControllerAllowed(uint8 _data) internal pure returns (bool) {\\n return ((_data >> 1) & 1) == 1;\\n }\\n\\n function transfersPaused(uint8 _data) internal pure returns (bool) {\\n return ((_data >> 2) & 1) == 1;\\n }\\n\\n /**\\n @notice\\n Pack the global funding cycle metadata.\\n\\n @param _metadata The metadata to validate and pack.\\n\\n @return packed The packed uint256 of all global metadata params. The first 8 bits specify the version.\\n */\\n function packFundingCycleGlobalMetadata(JBGlobalFundingCycleMetadata memory _metadata)\\n internal\\n pure\\n returns (uint256 packed)\\n {\\n // allow set terminals in bit 0.\\n if (_metadata.allowSetTerminals) packed |= 1;\\n // allow set controller in bit 1.\\n if (_metadata.allowSetController) packed |= 1 << 1;\\n // pause transfers in bit 2.\\n if (_metadata.pauseTransfers) packed |= 1 << 2;\\n }\\n\\n /**\\n @notice\\n Expand the global funding cycle metadata.\\n\\n @param _packedMetadata The packed metadata to expand.\\n\\n @return metadata The global metadata object.\\n */\\n function expandMetadata(uint8 _packedMetadata)\\n internal\\n pure\\n returns (JBGlobalFundingCycleMetadata memory metadata)\\n {\\n return\\n JBGlobalFundingCycleMetadata(\\n setTerminalsAllowed(_packedMetadata),\\n setControllerAllowed(_packedMetadata),\\n transfersPaused(_packedMetadata)\\n );\\n }\\n}\\n\",\"keccak256\":\"0x0d998f938026edeb755987a79421267cf860801161b5f171206a200b60f1061f\",\"license\":\"MIT\"},\"contracts/structs/JBDidPayData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member payer The address from which the payment originated.\\n @member projectId The ID of the project for which the payment was made.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the payment is being made.\\n @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.\\n @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.\\n @member projectTokenCount The number of project tokens minted for the beneficiary.\\n @member beneficiary The address to which the tokens were minted.\\n @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.\\n @member memo The memo that is being emitted alongside the payment.\\n @member metadata Extra data to send to the delegate.\\n*/\\nstruct JBDidPayData {\\n address payer;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n JBTokenAmount amount;\\n JBTokenAmount forwardedAmount;\\n uint256 projectTokenCount;\\n address beneficiary;\\n bool preferClaimedTokens;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0xf3c664309b37790f16047ae97b0459889ae0242dfcde7fc8902c8d10c7f8e6b6\",\"license\":\"MIT\"},\"contracts/structs/JBDidRedeemData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member holder The holder of the tokens being redeemed.\\n @member projectId The ID of the project with which the redeemed tokens are associated.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the redemption is being made.\\n @member projectTokenCount The number of project tokens being redeemed.\\n @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.\\n @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.\\n @member beneficiary The address to which the reclaimed amount will be sent.\\n @member memo The memo that is being emitted alongside the redemption.\\n @member metadata Extra data to send to the delegate.\\n*/\\nstruct JBDidRedeemData {\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 projectTokenCount;\\n JBTokenAmount reclaimedAmount;\\n JBTokenAmount forwardedAmount;\\n address payable beneficiary;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0xe2c401f39723a7ce915b8bef328744c66daaf57460843964b941456c2258a412\",\"license\":\"MIT\"},\"contracts/structs/JBFundAccessConstraints.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBPaymentTerminal.sol';\\n\\n/** \\n @member terminal The terminal within which the distribution limit and the overflow allowance applies.\\n @member token The token for which the fund access constraints apply.\\n @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.\\n @member distributionLimitCurrency The currency of the distribution limit.\\n @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.\\n @member overflowAllowanceCurrency The currency of the overflow allowance.\\n*/\\nstruct JBFundAccessConstraints {\\n IJBPaymentTerminal terminal;\\n address token;\\n uint256 distributionLimit;\\n uint256 distributionLimitCurrency;\\n uint256 overflowAllowance;\\n uint256 overflowAllowanceCurrency;\\n}\\n\",\"keccak256\":\"0x85ebaa57b788cbdedc7a3d0eec4892eda5d79db7c1a6103797f10d0d989775b2\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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.\\n @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.\\n @member basedOn The `configuration` of the funding cycle that was active when this cycle was created.\\n @member start The timestamp marking the moment from which the funding cycle is considered active. It is a unix timestamp measured in seconds.\\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n @member metadata Extra data that can be associated with a funding cycle.\\n*/\\nstruct JBFundingCycle {\\n uint256 number;\\n uint256 configuration;\\n uint256 basedOn;\\n uint256 start;\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n uint256 metadata;\\n}\\n\",\"keccak256\":\"0xcdd3ac9b6fa67e62ada88d09b73bc35ade1cd77d43db712289266a788928b4c2\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycleData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n*/\\nstruct JBFundingCycleData {\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n}\\n\",\"keccak256\":\"0x2aa6368bf4dfc5797e8b02a978293de0c777fae2658de2c825a103587240f3b0\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycleMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBGlobalFundingCycleMetadata.sol';\\n\\n/** \\n @member global Data used globally in non-migratable ecosystem contracts.\\n @member reservedRate The reserved rate of the funding cycle. This number is a percentage calculated out of `JBConstants.MAX_RESERVED_RATE`.\\n @member redemptionRate The redemption rate of the funding cycle. This number is a percentage calculated out of `JBConstants.MAX_REDEMPTION_RATE`.\\n @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`.\\n @member pausePay A flag indicating if the pay functionality should be paused during the funding cycle.\\n @member pauseDistributions A flag indicating if the distribute functionality should be paused during the funding cycle.\\n @member pauseRedeem A flag indicating if the redeem functionality should be paused during the funding cycle.\\n @member pauseBurn A flag indicating if the burn functionality should be paused during the funding cycle.\\n @member allowMinting A flag indicating if minting tokens should be allowed during this funding cycle.\\n @member allowTerminalMigration A flag indicating if migrating terminals should be allowed during this funding cycle.\\n @member allowControllerMigration A flag indicating if migrating controllers should be allowed during this funding cycle.\\n @member holdFees A flag indicating if fees should be held during this funding cycle.\\n @member preferClaimedTokenOverride A flag indicating if claimed tokens should always be prefered to unclaimed tokens when minting.\\n @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.\\n @member useDataSourceForPay A flag indicating if the data source should be used for pay transactions during this funding cycle.\\n @member useDataSourceForRedeem A flag indicating if the data source should be used for redeem transactions during this funding cycle.\\n @member dataSource The data source to use during this funding cycle.\\n @member metadata Metadata of the metadata, up to uint8 in size.\\n*/\\nstruct JBFundingCycleMetadata {\\n JBGlobalFundingCycleMetadata global;\\n uint256 reservedRate;\\n uint256 redemptionRate;\\n uint256 ballotRedemptionRate;\\n bool pausePay;\\n bool pauseDistributions;\\n bool pauseRedeem;\\n bool pauseBurn;\\n bool allowMinting;\\n bool allowTerminalMigration;\\n bool allowControllerMigration;\\n bool holdFees;\\n bool preferClaimedTokenOverride;\\n bool useTotalOverflowForRedemptions;\\n bool useDataSourceForPay;\\n bool useDataSourceForRedeem;\\n address dataSource;\\n uint256 metadata;\\n}\\n\",\"keccak256\":\"0x783604440cac8d176332eab28166f188ee5c230378c08cfc95fea4f7187dc77d\",\"license\":\"MIT\"},\"contracts/structs/JBGlobalFundingCycleMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member allowSetTerminals A flag indicating if setting terminals should be allowed during this funding cycle.\\n @member allowSetController A flag indicating if setting a new controller should be allowed during this funding cycle.\\n @member pauseTransfers A flag indicating if the project token transfer functionality should be paused during the funding cycle.\\n*/\\nstruct JBGlobalFundingCycleMetadata {\\n bool allowSetTerminals;\\n bool allowSetController;\\n bool pauseTransfers;\\n}\\n\",\"keccak256\":\"0x05d85530305fec6d6eca54cdbc2cd9110cbda0146598032b0203aa4b622944ff\",\"license\":\"MIT\"},\"contracts/structs/JBGroupedSplits.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBSplit.sol';\\n\\n/** \\n @member group The group indentifier.\\n @member splits The splits to associate with the group.\\n*/\\nstruct JBGroupedSplits {\\n uint256 group;\\n JBSplit[] splits;\\n}\\n\",\"keccak256\":\"0x80be1b220da4ac04851ea540ebb94c1ec2b0442ec5bd1e88fdf78a56becd8b5a\",\"license\":\"MIT\"},\"contracts/structs/JBPayDelegateAllocation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '../interfaces/IJBPayDelegate.sol';\\n\\n/** \\n @member delegate A delegate contract to use for subsequent calls.\\n @member amount The amount to send to the delegate.\\n*/\\nstruct JBPayDelegateAllocation {\\n IJBPayDelegate delegate;\\n uint256 amount;\\n}\\n\",\"keccak256\":\"0xb4e558dc62231d89e9b48998012577d22c3e52b58e23401f22d9096827f6ea0c\",\"license\":\"MIT\"},\"contracts/structs/JBPayParamsData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBPaymentTerminal.sol';\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member terminal The terminal that is facilitating the payment.\\n @member payer The address from which the payment originated.\\n @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.\\n @member projectId The ID of the project being paid.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the payment is being made.\\n @member beneficiary The specified address that should be the beneficiary of anything that results from the payment.\\n @member weight The weight of the funding cycle during which the payment is being made.\\n @member reservedRate The reserved rate of the funding cycle during which the payment is being made.\\n @member memo The memo that was sent alongside the payment.\\n @member metadata Extra data provided by the payer.\\n*/\\nstruct JBPayParamsData {\\n IJBPaymentTerminal terminal;\\n address payer;\\n JBTokenAmount amount;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n address beneficiary;\\n uint256 weight;\\n uint256 reservedRate;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0x05007b26feb5d9a026b883c6d734a341b5a49ef7b8215fb40507882e2c14e24d\",\"license\":\"MIT\"},\"contracts/structs/JBProjectMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member content The metadata content.\\n @member domain The domain within which the metadata applies.\\n*/\\nstruct JBProjectMetadata {\\n string content;\\n uint256 domain;\\n}\\n\",\"keccak256\":\"0x90ad7b1014c0a9f945fe7a2efde9d5de41e40574fa27969070b1d2ff52033ea0\",\"license\":\"MIT\"},\"contracts/structs/JBRedeemParamsData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBPaymentTerminal.sol';\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member terminal The terminal that is facilitating the redemption.\\n @member holder The holder of the tokens being redeemed.\\n @member projectId The ID of the project whos tokens are being redeemed.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the redemption is being made.\\n @member tokenCount The proposed number of tokens being redeemed, as a fixed point number with 18 decimals.\\n @member totalSupply The total supply of tokens used in the calculation, as a fixed point number with 18 decimals.\\n @member overflow The amount of overflow used in the reclaim amount calculation.\\n @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.\\n @member useTotalOverflow If overflow across all of a project's terminals is being used when making redemptions.\\n @member redemptionRate The redemption rate of the funding cycle during which the redemption is being made.\\n @member memo The proposed memo that is being emitted alongside the redemption.\\n @member metadata Extra data provided by the redeemer.\\n*/\\nstruct JBRedeemParamsData {\\n IJBPaymentTerminal terminal;\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 tokenCount;\\n uint256 totalSupply;\\n uint256 overflow;\\n JBTokenAmount reclaimAmount;\\n bool useTotalOverflow;\\n uint256 redemptionRate;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0x5065a824ebb34952f016c6dfa47e8a7ac28427b719470e74a41022c11ace7788\",\"license\":\"MIT\"},\"contracts/structs/JBRedemptionDelegateAllocation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '../interfaces/IJBRedemptionDelegate.sol';\\n\\n/** \\n @member delegate A delegate contract to use for subsequent calls.\\n @member amount The amount to send to the delegate.\\n*/\\nstruct JBRedemptionDelegateAllocation {\\n IJBRedemptionDelegate delegate;\\n uint256 amount;\\n}\\n\",\"keccak256\":\"0x10c29d33dd0d875a0d4692a2b9a9355c2ebf433cc06a9a60253d4366b60d4d31\",\"license\":\"MIT\"},\"contracts/structs/JBSplit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBSplitAllocator.sol';\\n\\n/** \\n @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.\\n @member preferAddToBalance A flag indicating if a distribution to a project should prefer triggering it's addToBalance function instead of its pay function.\\n @member percent The percent of the whole group that this split occupies. This number is out of `JBConstants.SPLITS_TOTAL_PERCENT`.\\n @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.\\n @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.\\n @member lockedUntil Specifies if the split should be unchangeable until the specified time, with the exception of extending the locked period.\\n @member allocator If an allocator is specified, funds will be sent to the allocator contract along with all properties of this split.\\n*/\\nstruct JBSplit {\\n bool preferClaimed;\\n bool preferAddToBalance;\\n uint256 percent;\\n uint256 projectId;\\n address payable beneficiary;\\n uint256 lockedUntil;\\n IJBSplitAllocator allocator;\\n}\\n\",\"keccak256\":\"0xc80a16606da8abf76d0f73abc38aee041e24f29342c1939018f70c286e89f105\",\"license\":\"MIT\"},\"contracts/structs/JBSplitAllocationData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBSplit.sol';\\n\\n/** \\n @member token The token being sent to the split allocator.\\n @member amount The amount being sent to the split allocator, as a fixed point number.\\n @member decimals The number of decimals in the amount.\\n @member projectId The project to which the split belongs.\\n @member group The group to which the split belongs.\\n @member split The split that caused the allocation.\\n*/\\nstruct JBSplitAllocationData {\\n address token;\\n uint256 amount;\\n uint256 decimals;\\n uint256 projectId;\\n uint256 group;\\n JBSplit split;\\n}\\n\",\"keccak256\":\"0x39f5c41bd31d36774744698ac94484b6cab62d7038df2f29d947668959782e63\",\"license\":\"MIT\"},\"contracts/structs/JBTokenAmount.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/* \\n @member token The token the payment was made in.\\n @member value The amount of tokens that was paid, as a fixed point number.\\n @member decimals The number of decimals included in the value fixed point number.\\n @member currency The expected currency of the value.\\n**/\\nstruct JBTokenAmount {\\n address token;\\n uint256 value;\\n uint256 decimals;\\n uint256 currency;\\n}\\n\",\"keccak256\":\"0x4a778e779ba257ba5638c5469e07a4d21b55a3128d56db5a0fdfacb1f3301c51\",\"license\":\"MIT\"},\"prb-math/contracts/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivFixedPointOverflow(uint256 prod1);\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivOverflow(uint256 prod1, uint256 denominator);\\n\\n/// @notice Emitted when one of the inputs is type(int256).min.\\nerror PRBMath__MulDivSignedInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows int256.\\nerror PRBMath__MulDivSignedOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is MIN_SD59x18.\\nerror PRBMathSD59x18__AbsInputTooSmall();\\n\\n/// @notice Emitted when ceiling a number overflows SD59x18.\\nerror PRBMathSD59x18__CeilOverflow(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__DivInputTooSmall();\\n\\n/// @notice Emitted when one of the intermediary unsigned results overflows SD59x18.\\nerror PRBMathSD59x18__DivOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathSD59x18__ExpInputTooBig(int256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathSD59x18__Exp2InputTooBig(int256 x);\\n\\n/// @notice Emitted when flooring a number underflows SD59x18.\\nerror PRBMathSD59x18__FloorUnderflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format overflows SD59x18.\\nerror PRBMathSD59x18__FromIntOverflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format underflows SD59x18.\\nerror PRBMathSD59x18__FromIntUnderflow(int256 x);\\n\\n/// @notice Emitted when the product of the inputs is negative.\\nerror PRBMathSD59x18__GmNegativeProduct(int256 x, int256 y);\\n\\n/// @notice Emitted when multiplying the inputs overflows SD59x18.\\nerror PRBMathSD59x18__GmOverflow(int256 x, int256 y);\\n\\n/// @notice Emitted when the input is less than or equal to zero.\\nerror PRBMathSD59x18__LogInputTooSmall(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__MulInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__MulOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__PowuOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is negative.\\nerror PRBMathSD59x18__SqrtNegativeInput(int256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows SD59x18.\\nerror PRBMathSD59x18__SqrtOverflow(int256 x);\\n\\n/// @notice Emitted when addition overflows UD60x18.\\nerror PRBMathUD60x18__AddOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when ceiling a number overflows UD60x18.\\nerror PRBMathUD60x18__CeilOverflow(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathUD60x18__ExpInputTooBig(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathUD60x18__Exp2InputTooBig(uint256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format format overflows UD60x18.\\nerror PRBMathUD60x18__FromUintOverflow(uint256 x);\\n\\n/// @notice Emitted when multiplying the inputs overflows UD60x18.\\nerror PRBMathUD60x18__GmOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when the input is less than 1.\\nerror PRBMathUD60x18__LogInputTooSmall(uint256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows UD60x18.\\nerror PRBMathUD60x18__SqrtOverflow(uint256 x);\\n\\n/// @notice Emitted when subtraction underflows UD60x18.\\nerror PRBMathUD60x18__SubUnderflow(uint256 x, uint256 y);\\n\\n/// @dev Common mathematical functions used in both PRBMathSD59x18 and PRBMathUD60x18. Note that this shared library\\n/// does not always assume the signed 59.18-decimal fixed-point or the unsigned 60.18-decimal fixed-point\\n/// representation. When it does not, it is explicitly mentioned in the NatSpec documentation.\\nlibrary PRBMath {\\n /// STRUCTS ///\\n\\n struct SD59x18 {\\n int256 value;\\n }\\n\\n struct UD60x18 {\\n uint256 value;\\n }\\n\\n /// STORAGE ///\\n\\n /// @dev How many trailing decimals can be represented.\\n uint256 internal constant SCALE = 1e18;\\n\\n /// @dev Largest power of two divisor of SCALE.\\n uint256 internal constant SCALE_LPOTD = 262144;\\n\\n /// @dev SCALE inverted mod 2^256.\\n uint256 internal constant SCALE_INVERSE =\\n 78156646155174841979727994598816262306175212592076161876661_508869554232690281;\\n\\n /// FUNCTIONS ///\\n\\n /// @notice Calculates the binary exponent of x using the binary fraction method.\\n /// @dev Has to use 192.64-bit fixed-point numbers.\\n /// See https://ethereum.stackexchange.com/a/96594/24693.\\n /// @param x The exponent as an unsigned 192.64-bit fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp2(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n // Start from 0.5 in the 192.64-bit fixed-point format.\\n result = 0x800000000000000000000000000000000000000000000000;\\n\\n // Multiply the result by root(2, 2^-i) when the bit at position i is 1. None of the intermediary results overflows\\n // because the initial result is 2^191 and all magic factors are less than 2^65.\\n if (x & 0x8000000000000000 > 0) {\\n result = (result * 0x16A09E667F3BCC909) >> 64;\\n }\\n if (x & 0x4000000000000000 > 0) {\\n result = (result * 0x1306FE0A31B7152DF) >> 64;\\n }\\n if (x & 0x2000000000000000 > 0) {\\n result = (result * 0x1172B83C7D517ADCE) >> 64;\\n }\\n if (x & 0x1000000000000000 > 0) {\\n result = (result * 0x10B5586CF9890F62A) >> 64;\\n }\\n if (x & 0x800000000000000 > 0) {\\n result = (result * 0x1059B0D31585743AE) >> 64;\\n }\\n if (x & 0x400000000000000 > 0) {\\n result = (result * 0x102C9A3E778060EE7) >> 64;\\n }\\n if (x & 0x200000000000000 > 0) {\\n result = (result * 0x10163DA9FB33356D8) >> 64;\\n }\\n if (x & 0x100000000000000 > 0) {\\n result = (result * 0x100B1AFA5ABCBED61) >> 64;\\n }\\n if (x & 0x80000000000000 > 0) {\\n result = (result * 0x10058C86DA1C09EA2) >> 64;\\n }\\n if (x & 0x40000000000000 > 0) {\\n result = (result * 0x1002C605E2E8CEC50) >> 64;\\n }\\n if (x & 0x20000000000000 > 0) {\\n result = (result * 0x100162F3904051FA1) >> 64;\\n }\\n if (x & 0x10000000000000 > 0) {\\n result = (result * 0x1000B175EFFDC76BA) >> 64;\\n }\\n if (x & 0x8000000000000 > 0) {\\n result = (result * 0x100058BA01FB9F96D) >> 64;\\n }\\n if (x & 0x4000000000000 > 0) {\\n result = (result * 0x10002C5CC37DA9492) >> 64;\\n }\\n if (x & 0x2000000000000 > 0) {\\n result = (result * 0x1000162E525EE0547) >> 64;\\n }\\n if (x & 0x1000000000000 > 0) {\\n result = (result * 0x10000B17255775C04) >> 64;\\n }\\n if (x & 0x800000000000 > 0) {\\n result = (result * 0x1000058B91B5BC9AE) >> 64;\\n }\\n if (x & 0x400000000000 > 0) {\\n result = (result * 0x100002C5C89D5EC6D) >> 64;\\n }\\n if (x & 0x200000000000 > 0) {\\n result = (result * 0x10000162E43F4F831) >> 64;\\n }\\n if (x & 0x100000000000 > 0) {\\n result = (result * 0x100000B1721BCFC9A) >> 64;\\n }\\n if (x & 0x80000000000 > 0) {\\n result = (result * 0x10000058B90CF1E6E) >> 64;\\n }\\n if (x & 0x40000000000 > 0) {\\n result = (result * 0x1000002C5C863B73F) >> 64;\\n }\\n if (x & 0x20000000000 > 0) {\\n result = (result * 0x100000162E430E5A2) >> 64;\\n }\\n if (x & 0x10000000000 > 0) {\\n result = (result * 0x1000000B172183551) >> 64;\\n }\\n if (x & 0x8000000000 > 0) {\\n result = (result * 0x100000058B90C0B49) >> 64;\\n }\\n if (x & 0x4000000000 > 0) {\\n result = (result * 0x10000002C5C8601CC) >> 64;\\n }\\n if (x & 0x2000000000 > 0) {\\n result = (result * 0x1000000162E42FFF0) >> 64;\\n }\\n if (x & 0x1000000000 > 0) {\\n result = (result * 0x10000000B17217FBB) >> 64;\\n }\\n if (x & 0x800000000 > 0) {\\n result = (result * 0x1000000058B90BFCE) >> 64;\\n }\\n if (x & 0x400000000 > 0) {\\n result = (result * 0x100000002C5C85FE3) >> 64;\\n }\\n if (x & 0x200000000 > 0) {\\n result = (result * 0x10000000162E42FF1) >> 64;\\n }\\n if (x & 0x100000000 > 0) {\\n result = (result * 0x100000000B17217F8) >> 64;\\n }\\n if (x & 0x80000000 > 0) {\\n result = (result * 0x10000000058B90BFC) >> 64;\\n }\\n if (x & 0x40000000 > 0) {\\n result = (result * 0x1000000002C5C85FE) >> 64;\\n }\\n if (x & 0x20000000 > 0) {\\n result = (result * 0x100000000162E42FF) >> 64;\\n }\\n if (x & 0x10000000 > 0) {\\n result = (result * 0x1000000000B17217F) >> 64;\\n }\\n if (x & 0x8000000 > 0) {\\n result = (result * 0x100000000058B90C0) >> 64;\\n }\\n if (x & 0x4000000 > 0) {\\n result = (result * 0x10000000002C5C860) >> 64;\\n }\\n if (x & 0x2000000 > 0) {\\n result = (result * 0x1000000000162E430) >> 64;\\n }\\n if (x & 0x1000000 > 0) {\\n result = (result * 0x10000000000B17218) >> 64;\\n }\\n if (x & 0x800000 > 0) {\\n result = (result * 0x1000000000058B90C) >> 64;\\n }\\n if (x & 0x400000 > 0) {\\n result = (result * 0x100000000002C5C86) >> 64;\\n }\\n if (x & 0x200000 > 0) {\\n result = (result * 0x10000000000162E43) >> 64;\\n }\\n if (x & 0x100000 > 0) {\\n result = (result * 0x100000000000B1721) >> 64;\\n }\\n if (x & 0x80000 > 0) {\\n result = (result * 0x10000000000058B91) >> 64;\\n }\\n if (x & 0x40000 > 0) {\\n result = (result * 0x1000000000002C5C8) >> 64;\\n }\\n if (x & 0x20000 > 0) {\\n result = (result * 0x100000000000162E4) >> 64;\\n }\\n if (x & 0x10000 > 0) {\\n result = (result * 0x1000000000000B172) >> 64;\\n }\\n if (x & 0x8000 > 0) {\\n result = (result * 0x100000000000058B9) >> 64;\\n }\\n if (x & 0x4000 > 0) {\\n result = (result * 0x10000000000002C5D) >> 64;\\n }\\n if (x & 0x2000 > 0) {\\n result = (result * 0x1000000000000162E) >> 64;\\n }\\n if (x & 0x1000 > 0) {\\n result = (result * 0x10000000000000B17) >> 64;\\n }\\n if (x & 0x800 > 0) {\\n result = (result * 0x1000000000000058C) >> 64;\\n }\\n if (x & 0x400 > 0) {\\n result = (result * 0x100000000000002C6) >> 64;\\n }\\n if (x & 0x200 > 0) {\\n result = (result * 0x10000000000000163) >> 64;\\n }\\n if (x & 0x100 > 0) {\\n result = (result * 0x100000000000000B1) >> 64;\\n }\\n if (x & 0x80 > 0) {\\n result = (result * 0x10000000000000059) >> 64;\\n }\\n if (x & 0x40 > 0) {\\n result = (result * 0x1000000000000002C) >> 64;\\n }\\n if (x & 0x20 > 0) {\\n result = (result * 0x10000000000000016) >> 64;\\n }\\n if (x & 0x10 > 0) {\\n result = (result * 0x1000000000000000B) >> 64;\\n }\\n if (x & 0x8 > 0) {\\n result = (result * 0x10000000000000006) >> 64;\\n }\\n if (x & 0x4 > 0) {\\n result = (result * 0x10000000000000003) >> 64;\\n }\\n if (x & 0x2 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n if (x & 0x1 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n\\n // We're doing two things at the same time:\\n //\\n // 1. Multiply the result by 2^n + 1, where \\\"2^n\\\" is the integer part and the one is added to account for\\n // the fact that we initially set the result to 0.5. This is accomplished by subtracting from 191\\n // rather than 192.\\n // 2. Convert the result to the unsigned 60.18-decimal fixed-point format.\\n //\\n // This works because 2^(191-ip) = 2^ip / 2^191, where \\\"ip\\\" is the integer part \\\"2^n\\\".\\n result *= SCALE;\\n result >>= (191 - (x >> 64));\\n }\\n }\\n\\n /// @notice Finds the zero-based index of the first one in the binary representation of x.\\n /// @dev See the note on msb in the \\\"Find First Set\\\" Wikipedia article https://en.wikipedia.org/wiki/Find_first_set\\n /// @param x The uint256 number for which to find the index of the most significant bit.\\n /// @return msb The index of the most significant bit as an uint256.\\n function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\\n if (x >= 2**128) {\\n x >>= 128;\\n msb += 128;\\n }\\n if (x >= 2**64) {\\n x >>= 64;\\n msb += 64;\\n }\\n if (x >= 2**32) {\\n x >>= 32;\\n msb += 32;\\n }\\n if (x >= 2**16) {\\n x >>= 16;\\n msb += 16;\\n }\\n if (x >= 2**8) {\\n x >>= 8;\\n msb += 8;\\n }\\n if (x >= 2**4) {\\n x >>= 4;\\n msb += 4;\\n }\\n if (x >= 2**2) {\\n x >>= 2;\\n msb += 2;\\n }\\n if (x >= 2**1) {\\n // No need to shift x any more.\\n msb += 1;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.\\n ///\\n /// Requirements:\\n /// - The denominator cannot be zero.\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The multiplicand as an uint256.\\n /// @param y The multiplier as an uint256.\\n /// @param denominator The divisor as an uint256.\\n /// @return result The result as an uint256.\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n unchecked {\\n result = prod0 / denominator;\\n }\\n return result;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n if (prod1 >= denominator) {\\n revert PRBMath__MulDivOverflow(prod1, denominator);\\n }\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n unchecked {\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 lpotdod = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by lpotdod.\\n denominator := div(denominator, lpotdod)\\n\\n // Divide [prod1 prod0] by lpotdod.\\n prod0 := div(prod0, lpotdod)\\n\\n // Flip lpotdod such that it is 2^256 / lpotdod. If lpotdod is zero, then it becomes one.\\n lpotdod := add(div(sub(0, lpotdod), lpotdod), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * lpotdod;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f71e18) with full precision.\\n ///\\n /// @dev Variant of \\\"mulDiv\\\" with constant folding, i.e. in which the denominator is always 1e18. Before returning the\\n /// final result, we add 1 if (x * y) % SCALE >= HALF_SCALE. Without this, 6.6e-19 would be truncated to 0 instead of\\n /// being rounded to 1e-18. See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717.\\n ///\\n /// Requirements:\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - The body is purposely left uncommented; see the NatSpec comments in \\\"PRBMath.mulDiv\\\" to understand how this works.\\n /// - It is assumed that the result can never be type(uint256).max when x and y solve the following two equations:\\n /// 1. x * y = type(uint256).max * SCALE\\n /// 2. (x * y) % SCALE >= SCALE / 2\\n ///\\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function mulDivFixedPoint(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n uint256 prod0;\\n uint256 prod1;\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n if (prod1 >= SCALE) {\\n revert PRBMath__MulDivFixedPointOverflow(prod1);\\n }\\n\\n uint256 remainder;\\n uint256 roundUpUnit;\\n assembly {\\n remainder := mulmod(x, y, SCALE)\\n roundUpUnit := gt(remainder, 499999999999999999)\\n }\\n\\n if (prod1 == 0) {\\n unchecked {\\n result = (prod0 / SCALE) + roundUpUnit;\\n return result;\\n }\\n }\\n\\n assembly {\\n result := add(\\n mul(\\n or(\\n div(sub(prod0, remainder), SCALE_LPOTD),\\n mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, SCALE_LPOTD), SCALE_LPOTD), 1))\\n ),\\n SCALE_INVERSE\\n ),\\n roundUpUnit\\n )\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev An extension of \\\"mulDiv\\\" for signed numbers. Works by computing the signs and the absolute values separately.\\n ///\\n /// Requirements:\\n /// - None of the inputs can be type(int256).min.\\n /// - The result must fit within int256.\\n ///\\n /// @param x The multiplicand as an int256.\\n /// @param y The multiplier as an int256.\\n /// @param denominator The divisor as an int256.\\n /// @return result The result as an int256.\\n function mulDivSigned(\\n int256 x,\\n int256 y,\\n int256 denominator\\n ) internal pure returns (int256 result) {\\n if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {\\n revert PRBMath__MulDivSignedInputTooSmall();\\n }\\n\\n // Get hold of the absolute values of x, y and the denominator.\\n uint256 ax;\\n uint256 ay;\\n uint256 ad;\\n unchecked {\\n ax = x < 0 ? uint256(-x) : uint256(x);\\n ay = y < 0 ? uint256(-y) : uint256(y);\\n ad = denominator < 0 ? uint256(-denominator) : uint256(denominator);\\n }\\n\\n // Compute the absolute value of (x*y)\\u00f7denominator. The result must fit within int256.\\n uint256 rAbs = mulDiv(ax, ay, ad);\\n if (rAbs > uint256(type(int256).max)) {\\n revert PRBMath__MulDivSignedOverflow(rAbs);\\n }\\n\\n // Get the signs of x, y and the denominator.\\n uint256 sx;\\n uint256 sy;\\n uint256 sd;\\n assembly {\\n sx := sgt(x, sub(0, 1))\\n sy := sgt(y, sub(0, 1))\\n sd := sgt(denominator, sub(0, 1))\\n }\\n\\n // XOR over sx, sy and sd. This is checking whether there are one or three negative signs in the inputs.\\n // If yes, the result should be negative.\\n result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs);\\n }\\n\\n /// @notice Calculates the square root of x, rounding down.\\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The uint256 number for which to calculate the square root.\\n /// @return result The result as an uint256.\\n function sqrt(uint256 x) internal pure returns (uint256 result) {\\n if (x == 0) {\\n return 0;\\n }\\n\\n // Set the initial guess to the closest power of two that is higher than x.\\n uint256 xAux = uint256(x);\\n result = 1;\\n if (xAux >= 0x100000000000000000000000000000000) {\\n xAux >>= 128;\\n result <<= 64;\\n }\\n if (xAux >= 0x10000000000000000) {\\n xAux >>= 64;\\n result <<= 32;\\n }\\n if (xAux >= 0x100000000) {\\n xAux >>= 32;\\n result <<= 16;\\n }\\n if (xAux >= 0x10000) {\\n xAux >>= 16;\\n result <<= 8;\\n }\\n if (xAux >= 0x100) {\\n xAux >>= 8;\\n result <<= 4;\\n }\\n if (xAux >= 0x10) {\\n xAux >>= 4;\\n result <<= 2;\\n }\\n if (xAux >= 0x8) {\\n result <<= 1;\\n }\\n\\n // The operations can never overflow because the result is max 2^127 when it enters this block.\\n unchecked {\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1; // Seven iterations should be enough\\n uint256 roundedDownResult = x / result;\\n return result >= roundedDownResult ? roundedDownResult : result;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x62cbabae4910e168e99b9c2c3e3b5c9c7ad5e7abd961dcc63b7ea3d83d8ea87e\",\"license\":\"Unlicense\"}},\"version\":1}", + "metadata": "{\"compiler\":{\"version\":\"0.8.16+commit.07a7930e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IJBDirectory\",\"name\":\"_directory\",\"type\":\"address\"},{\"internalType\":\"contract IJBFundingCycleStore\",\"name\":\"_fundingCycleStore\",\"type\":\"address\"},{\"internalType\":\"contract IJBPrices\",\"name\":\"_prices\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CURRENCY_MISMATCH\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DISTRIBUTION_AMOUNT_LIMIT_REACHED\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FUNDING_CYCLE_DISTRIBUTION_PAUSED\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FUNDING_CYCLE_PAYMENT_PAUSED\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FUNDING_CYCLE_REDEEM_PAUSED\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INADEQUATE_CONTROLLER_ALLOWANCE\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INSUFFICIENT_TOKENS\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INVALID_AMOUNT_TO_SEND_DELEGATE\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INVALID_FUNDING_CYCLE\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"prod1\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"denominator\",\"type\":\"uint256\"}],\"name\":\"PRBMath__MulDivOverflow\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminal\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminal\",\"name\":\"_terminal\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"}],\"name\":\"currentOverflowOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_tokenCount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_overflow\",\"type\":\"uint256\"}],\"name\":\"currentReclaimableOverflowOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminal\",\"name\":\"_terminal\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_tokenCount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"_useTotalOverflow\",\"type\":\"bool\"}],\"name\":\"currentReclaimableOverflowOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_decimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_currency\",\"type\":\"uint256\"}],\"name\":\"currentTotalOverflowOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"directory\",\"outputs\":[{\"internalType\":\"contract IJBDirectory\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fundingCycleStore\",\"outputs\":[{\"internalType\":\"contract IJBFundingCycleStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"prices\",\"outputs\":[{\"internalType\":\"contract IJBPrices\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"recordAddedBalanceFor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_currency\",\"type\":\"uint256\"}],\"name\":\"recordDistributionFor\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"configuration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"basedOn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"discountRate\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBFundingCycleBallot\",\"name\":\"ballot\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"metadata\",\"type\":\"uint256\"}],\"internalType\":\"struct JBFundingCycle\",\"name\":\"fundingCycle\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"distributedAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"}],\"name\":\"recordMigration\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_payer\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"decimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"currency\",\"type\":\"uint256\"}],\"internalType\":\"struct JBTokenAmount\",\"name\":\"_amount\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_baseWeightCurrency\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"recordPaymentFrom\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"configuration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"basedOn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"discountRate\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBFundingCycleBallot\",\"name\":\"ballot\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"metadata\",\"type\":\"uint256\"}],\"internalType\":\"struct JBFundingCycle\",\"name\":\"fundingCycle\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"tokenCount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"contract IJBPayDelegate\",\"name\":\"delegate\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"struct JBPayDelegateAllocation[]\",\"name\":\"delegateAllocations\",\"type\":\"tuple[]\"},{\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_holder\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_tokenCount\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"recordRedemptionFor\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"configuration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"basedOn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"discountRate\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBFundingCycleBallot\",\"name\":\"ballot\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"metadata\",\"type\":\"uint256\"}],\"internalType\":\"struct JBFundingCycle\",\"name\":\"fundingCycle\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"reclaimAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"contract IJBRedemptionDelegate\",\"name\":\"delegate\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"struct JBRedemptionDelegateAllocation[]\",\"name\":\"delegateAllocations\",\"type\":\"tuple[]\"},{\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_currency\",\"type\":\"uint256\"}],\"name\":\"recordUsedAllowanceOf\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"configuration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"basedOn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"discountRate\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBFundingCycleBallot\",\"name\":\"ballot\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"metadata\",\"type\":\"uint256\"}],\"internalType\":\"struct JBFundingCycle\",\"name\":\"fundingCycle\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"usedAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminal\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"usedDistributionLimitOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminal\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"usedOverflowAllowanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Adheres to: IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.Inherits from - ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.This Store expects a project's controller to be an IJBController3_1. This is the only difference between this version and the original.\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_directory\":\"A contract storing directories of terminals and controllers for each project.\",\"_fundingCycleStore\":\"A contract storing all funding cycle configurations.\",\"_prices\":\"A contract that exposes price feeds.\"}},\"currentOverflowOf(address,uint256)\":{\"details\":\"The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\",\"params\":{\"_projectId\":\"The ID of the project to get overflow for.\",\"_terminal\":\"The terminal for which the overflow is being calculated.\"},\"returns\":{\"_0\":\"The current amount of overflow that project has in the specified terminal.\"}},\"currentReclaimableOverflowOf(address,uint256,uint256,bool)\":{\"details\":\" If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.The current reclaimable overflow is returned in terms of the specified terminal's currency.The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\",\"params\":{\"_projectId\":\"The ID of the project to get the reclaimable overflow amount for.\",\"_terminal\":\"The terminal from which the reclaimable amount would come.\",\"_tokenCount\":\"The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\",\"_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`.\"},\"returns\":{\"_0\":\"The amount of overflowed tokens that can be reclaimed, as a fixed point number with the same number of decimals as the provided `_terminal`.\"}},\"currentReclaimableOverflowOf(uint256,uint256,uint256,uint256)\":{\"details\":\" If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\",\"params\":{\"_overflow\":\"The amount of overflow to make the calculation with, as a fixed point number.\",\"_projectId\":\"The ID of the project to get the reclaimable overflow amount for.\",\"_tokenCount\":\"The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\",\"_totalSupply\":\"The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\"},\"returns\":{\"_0\":\"The amount of overflowed tokens that can be reclaimed, as a fixed point number with the same number of decimals as the provided `_overflow`.\"}},\"currentTotalOverflowOf(uint256,uint256,uint256)\":{\"params\":{\"_currency\":\"The currency that the total overflow should be in terms of.\",\"_decimals\":\"The number of decimals that the fixed point overflow should include.\",\"_projectId\":\"The ID of the project to get total overflow for.\"},\"returns\":{\"_0\":\"The current total amount of overflow that project has across all terminals.\"}},\"recordAddedBalanceFor(uint256,uint256)\":{\"details\":\"The msg.sender must be an IJBSingleTokenPaymentTerminal. \",\"params\":{\"_amount\":\"The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\",\"_projectId\":\"The ID of the project to which the funds being added belong.\"}},\"recordDistributionFor(uint256,uint256,uint256)\":{\"details\":\"The msg.sender must be an IJBSingleTokenPaymentTerminal. \",\"params\":{\"_amount\":\"The amount to use from the distribution limit, as a fixed point number.\",\"_currency\":\"The currency of the `_amount`. This must match the project's current funding cycle's currency.\",\"_projectId\":\"The ID of the project that is having funds distributed.\"},\"returns\":{\"distributedAmount\":\"The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\",\"fundingCycle\":\"The funding cycle during which the distribution was made.\"}},\"recordMigration(uint256)\":{\"details\":\"The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\",\"params\":{\"_projectId\":\"The ID of the project being migrated.\"},\"returns\":{\"balance\":\"The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\"}},\"recordPaymentFrom(address,(address,uint256,uint256,uint256),uint256,uint256,address,string,bytes)\":{\"details\":\"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.The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\",\"params\":{\"_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.\",\"_baseWeightCurrency\":\"The currency to base token issuance on.\",\"_beneficiary\":\"The specified address that should be the beneficiary of anything that results from the payment.\",\"_memo\":\"A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\",\"_metadata\":\"Bytes to send along to the data source, if one is provided.\",\"_payer\":\"The original address that sent the payment to the terminal.\",\"_projectId\":\"The ID of the project being paid.\"},\"returns\":{\"delegateAllocations\":\"The amount to send to delegates instead of adding to the local balance.\",\"fundingCycle\":\"The project's funding cycle during which payment was made.\",\"memo\":\"A memo that should be passed along to the emitted event.\",\"tokenCount\":\"The number of project tokens that were minted, as a fixed point number with 18 decimals.\"}},\"recordRedemptionFor(address,uint256,uint256,string,bytes)\":{\"details\":\"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.The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\",\"params\":{\"_holder\":\"The account that is having its tokens redeemed.\",\"_memo\":\"A memo to pass along to the emitted event.\",\"_metadata\":\"Bytes to send along to the data source, if one is provided.\",\"_projectId\":\"The ID of the project to which the tokens being redeemed belong.\",\"_tokenCount\":\"The number of project tokens to redeem, as a fixed point number with 18 decimals.\"},\"returns\":{\"delegateAllocations\":\"The amount to send to delegates instead of sending to the beneficiary.\",\"fundingCycle\":\"The funding cycle during which the redemption was made.\",\"memo\":\"A memo that should be passed along to the emitted event.\",\"reclaimAmount\":\"The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\"}},\"recordUsedAllowanceOf(uint256,uint256,uint256)\":{\"details\":\"The msg.sender must be an IJBSingleTokenPaymentTerminal. \",\"params\":{\"_amount\":\"The amount to use from the allowance, as a fixed point number. \",\"_currency\":\"The currency of the `_amount`. Must match the currency of the overflow allowance.\",\"_projectId\":\"The ID of the project to use the allowance of.\"},\"returns\":{\"fundingCycle\":\"The funding cycle during which the overflow allowance is being used.\",\"usedAmount\":\"The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\"}}},\"stateVariables\":{\"balanceOf\":{\"details\":\"The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal. _terminal The terminal to which the balance applies. _projectId The ID of the project to get the balance of.\"},\"usedDistributionLimitOf\":{\"details\":\"Increases as projects use their preconfigured distribution limits.The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal. _terminal The terminal to which the used distribution limit applies. _projectId The ID of the project to get the used distribution limit of. _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\"},\"usedOverflowAllowanceOf\":{\"details\":\"Increases as projects use their allowance.The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal. _terminal The terminal to which the overflow allowance applies. _projectId The ID of the project to get the used overflow allowance of. _configuration The configuration of the during which the allowance was used.\"}},\"version\":1},\"userdoc\":{\"errors\":{\"PRBMath__MulDivOverflow(uint256,uint256)\":[{\"notice\":\"Emitted when the result overflows uint256.\"}]},\"kind\":\"user\",\"methods\":{\"balanceOf(address,uint256)\":{\"notice\":\"The amount of tokens that each project has for each terminal, in terms of the terminal's token.\"},\"currentOverflowOf(address,uint256)\":{\"notice\":\"Gets the current overflowed amount in a terminal for a specified project.\"},\"currentReclaimableOverflowOf(address,uint256,uint256,bool)\":{\"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.\"},\"currentReclaimableOverflowOf(uint256,uint256,uint256,uint256)\":{\"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.\"},\"currentTotalOverflowOf(uint256,uint256,uint256)\":{\"notice\":\"Gets the current overflowed amount for a specified project across all terminals.\"},\"directory()\":{\"notice\":\"The directory of terminals and controllers for projects.\"},\"fundingCycleStore()\":{\"notice\":\"The contract storing all funding cycle configurations.\"},\"prices()\":{\"notice\":\"The contract that exposes price feeds.\"},\"recordAddedBalanceFor(uint256,uint256)\":{\"notice\":\"Records newly added funds for the project.\"},\"recordDistributionFor(uint256,uint256,uint256)\":{\"notice\":\"Records newly distributed funds for a project.\"},\"recordMigration(uint256)\":{\"notice\":\"Records the migration of funds from this store.\"},\"recordPaymentFrom(address,(address,uint256,uint256,uint256),uint256,uint256,address,string,bytes)\":{\"notice\":\"Records newly contributed tokens to a project.\"},\"recordRedemptionFor(address,uint256,uint256,string,bytes)\":{\"notice\":\"Records newly redeemed tokens of a project.\"},\"recordUsedAllowanceOf(uint256,uint256,uint256)\":{\"notice\":\"Records newly used allowance funds of a project.\"},\"usedDistributionLimitOf(address,uint256,uint256)\":{\"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.\"},\"usedOverflowAllowanceOf(address,uint256,uint256)\":{\"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.\"}},\"notice\":\"Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/JBSingleTokenPaymentTerminalStore3_1.sol\":\"JBSingleTokenPaymentTerminalStore3_1\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/security/ReentrancyGuard.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuard {\\n // Booleans are more expensive than uint256 or any type that takes up a full\\n // word because each write operation emits an extra SLOAD to first read the\\n // slot's contents, replace the bits taken up by the boolean, and then write\\n // back. This is the compiler's defense against contract upgrades and\\n // pointer aliasing, and it cannot be disabled.\\n\\n // The values being non-zero value makes deployment a bit more expensive,\\n // but in exchange the refund on every call to nonReentrant will be lower in\\n // amount. Since refunds are capped to a percentage of the total\\n // transaction's gas, it is best to keep them low in cases like this one, to\\n // increase the likelihood of the full refund coming into effect.\\n uint256 private constant _NOT_ENTERED = 1;\\n uint256 private constant _ENTERED = 2;\\n\\n uint256 private _status;\\n\\n constructor() {\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and making it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n // On the first call to nonReentrant, _notEntered will be true\\n require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n _status = _ENTERED;\\n\\n _;\\n\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n _status = _NOT_ENTERED;\\n }\\n}\\n\",\"keccak256\":\"0x0e9621f60b2faabe65549f7ed0f24e8853a45c1b7990d47e8160e523683f3935\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool _approved) external;\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x516a22876c1fab47f49b1bc22b4614491cd05338af8bd2e7b382da090a079990\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"@paulrberg/contracts/math/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\nimport \\\"prb-math/contracts/PRBMath.sol\\\";\\n\",\"keccak256\":\"0x42821345981bc0434a90ba2268a2f5278dfe9e38166981d72fc7f3b776a29495\",\"license\":\"Unlicense\"},\"contracts/JBSingleTokenPaymentTerminalStore3_1.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\\nimport '@paulrberg/contracts/math/PRBMath.sol';\\nimport './interfaces/IJBController3_1.sol';\\nimport './interfaces/IJBFundingCycleDataSource.sol';\\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\\nimport './libraries/JBConstants.sol';\\nimport './libraries/JBCurrencies.sol';\\nimport './libraries/JBFixedPointNumber.sol';\\nimport './libraries/JBFundingCycleMetadataResolver.sol';\\nimport './structs/JBPayDelegateAllocation.sol';\\nimport './structs/JBPayParamsData.sol';\\n\\n/**\\n @notice\\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\\n\\n @dev\\n Adheres to:\\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n\\n @dev\\n Inherits from -\\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\\n\\n @dev\\n This Store expects a project's controller to be an IJBController3_1. This is the only difference between this version and the original.\\n*/\\ncontract JBSingleTokenPaymentTerminalStore3_1 is\\n ReentrancyGuard,\\n IJBSingleTokenPaymentTerminalStore\\n{\\n // A library that parses the packed funding cycle metadata into a friendlier format.\\n using JBFundingCycleMetadataResolver for JBFundingCycle;\\n\\n //*********************************************************************//\\n // --------------------------- custom errors ------------------------- //\\n //*********************************************************************//\\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\\n error CURRENCY_MISMATCH();\\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\\n error FUNDING_CYCLE_PAYMENT_PAUSED();\\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\\n error FUNDING_CYCLE_REDEEM_PAUSED();\\n error INADEQUATE_CONTROLLER_ALLOWANCE();\\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\\n error INSUFFICIENT_TOKENS();\\n error INVALID_FUNDING_CYCLE();\\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\\n\\n //*********************************************************************//\\n // -------------------------- private constants ---------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \\n */\\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\\n\\n //*********************************************************************//\\n // ---------------- public immutable stored properties --------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The directory of terminals and controllers for projects.\\n */\\n IJBDirectory public immutable override directory;\\n\\n /**\\n @notice\\n The contract storing all funding cycle configurations.\\n */\\n IJBFundingCycleStore public immutable override fundingCycleStore;\\n\\n /**\\n @notice\\n The contract that exposes price feeds.\\n */\\n IJBPrices public immutable override prices;\\n\\n //*********************************************************************//\\n // --------------------- public stored properties -------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\\n\\n @dev\\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\\n\\n _terminal The terminal to which the balance applies.\\n _projectId The ID of the project to get the balance of.\\n */\\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\\n\\n /**\\n @notice\\n 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.\\n\\n @dev\\n Increases as projects use their preconfigured distribution limits.\\n\\n @dev\\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\\n\\n _terminal The terminal to which the used distribution limit applies.\\n _projectId The ID of the project to get the used distribution limit of.\\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\\n */\\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\\n public\\n override usedDistributionLimitOf;\\n\\n /**\\n @notice\\n 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.\\n\\n @dev\\n Increases as projects use their allowance.\\n\\n @dev\\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\\n\\n _terminal The terminal to which the overflow allowance applies.\\n _projectId The ID of the project to get the used overflow allowance of.\\n _configuration The configuration of the during which the allowance was used.\\n */\\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\\n public\\n override usedOverflowAllowanceOf;\\n\\n //*********************************************************************//\\n // ------------------------- external views -------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Gets the current overflowed amount in a terminal for a specified project.\\n\\n @dev\\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\\n\\n @param _terminal The terminal for which the overflow is being calculated.\\n @param _projectId The ID of the project to get overflow for.\\n\\n @return The current amount of overflow that project has in the specified terminal.\\n */\\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\\n external\\n view\\n override\\n returns (uint256)\\n {\\n // Return the overflow during the project's current funding cycle.\\n return\\n _overflowDuring(\\n _terminal,\\n _projectId,\\n fundingCycleStore.currentOf(_projectId),\\n _terminal.currency()\\n );\\n }\\n\\n /**\\n @notice\\n Gets the current overflowed amount for a specified project across all terminals.\\n\\n @param _projectId The ID of the project to get total overflow for.\\n @param _decimals The number of decimals that the fixed point overflow should include.\\n @param _currency The currency that the total overflow should be in terms of.\\n\\n @return The current total amount of overflow that project has across all terminals.\\n */\\n function currentTotalOverflowOf(\\n uint256 _projectId,\\n uint256 _decimals,\\n uint256 _currency\\n ) external view override returns (uint256) {\\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\\n }\\n\\n /**\\n @notice\\n 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.\\n\\n @dev \\n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\\n\\n @dev\\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\\n\\n @dev\\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\\n\\n @param _terminal The terminal from which the reclaimable amount would come.\\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\\n @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`.\\n\\n @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`.\\n */\\n function currentReclaimableOverflowOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n bool _useTotalOverflow\\n ) external view override returns (uint256) {\\n // Get a reference to the project's current funding cycle.\\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // Get the amount of current overflow.\\n // 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.\\n uint256 _currentOverflow = _useTotalOverflow\\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\\n\\n // If there's no overflow, there's no reclaimable overflow.\\n if (_currentOverflow == 0) return 0;\\n\\n // Get the number of outstanding tokens the project has.\\n uint256 _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\\n .totalOutstandingTokensOf(_projectId);\\n\\n // Can't redeem more tokens that is in the supply.\\n if (_tokenCount > _totalSupply) return 0;\\n\\n // Return the reclaimable overflow amount.\\n return\\n _reclaimableOverflowDuring(\\n _projectId,\\n _fundingCycle,\\n _tokenCount,\\n _totalSupply,\\n _currentOverflow\\n );\\n }\\n\\n /**\\n @notice\\n 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.\\n\\n @dev \\n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\\n\\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\\n\\n @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`.\\n */\\n function currentReclaimableOverflowOf(\\n uint256 _projectId,\\n uint256 _tokenCount,\\n uint256 _totalSupply,\\n uint256 _overflow\\n ) external view override returns (uint256) {\\n // If there's no overflow, there's no reclaimable overflow.\\n if (_overflow == 0) return 0;\\n\\n // Can't redeem more tokens that is in the supply.\\n if (_tokenCount > _totalSupply) return 0;\\n\\n // Get a reference to the project's current funding cycle.\\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // Return the reclaimable overflow amount.\\n return\\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\\n }\\n\\n //*********************************************************************//\\n // -------------------------- constructor ---------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @param _directory A contract storing directories of terminals and controllers for each project.\\n @param _fundingCycleStore A contract storing all funding cycle configurations.\\n @param _prices A contract that exposes price feeds.\\n */\\n constructor(\\n IJBDirectory _directory,\\n IJBFundingCycleStore _fundingCycleStore,\\n IJBPrices _prices\\n ) {\\n directory = _directory;\\n fundingCycleStore = _fundingCycleStore;\\n prices = _prices;\\n }\\n\\n //*********************************************************************//\\n // ---------------------- external transactions ---------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Records newly contributed tokens to a project.\\n\\n @dev\\n 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.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\\n\\n @param _payer The original address that sent the payment to the terminal.\\n @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.\\n @param _projectId The ID of the project being paid.\\n @param _baseWeightCurrency The currency to base token issuance on.\\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\\n @param _metadata Bytes to send along to the data source, if one is provided.\\n\\n @return fundingCycle The project's funding cycle during which payment was made.\\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\\n @return memo A memo that should be passed along to the emitted event.\\n */\\n function recordPaymentFrom(\\n address _payer,\\n JBTokenAmount calldata _amount,\\n uint256 _projectId,\\n uint256 _baseWeightCurrency,\\n address _beneficiary,\\n string calldata _memo,\\n bytes memory _metadata\\n )\\n external\\n override\\n nonReentrant\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 tokenCount,\\n JBPayDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n )\\n {\\n // Get a reference to the current funding cycle for the project.\\n fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // The project must have a funding cycle configured.\\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\\n\\n // Must not be paused.\\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\\n\\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\\n uint256 _weight;\\n\\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\\n // Create the params that'll be sent to the data source.\\n JBPayParamsData memory _data = JBPayParamsData(\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n _payer,\\n _amount,\\n _projectId,\\n fundingCycle.configuration,\\n _beneficiary,\\n fundingCycle.weight,\\n fundingCycle.reservedRate(),\\n _memo,\\n _metadata\\n );\\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\\n .payParams(_data);\\n }\\n // Otherwise use the funding cycle's weight\\n else {\\n _weight = fundingCycle.weight;\\n memo = _memo;\\n }\\n\\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\\n {\\n // Keep a reference to the amount that should be added to the project's balance.\\n uint256 _balanceDiff = _amount.value;\\n\\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\\n if (delegateAllocations.length != 0) {\\n for (uint256 _i; _i < delegateAllocations.length; ) {\\n // Get a reference to the amount to be delegated.\\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\\n\\n // Validate if non-zero.\\n if (_delegatedAmount != 0) {\\n // Can't delegate more than was paid.\\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\\n\\n // Decrement the total amount being added to the balance.\\n _balanceDiff = _balanceDiff - _delegatedAmount;\\n }\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n\\n // If there's no amount being recorded, there's nothing left to do.\\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\\n\\n // Add the correct balance difference to the token balance of the project.\\n if (_balanceDiff != 0)\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\\n _balanceDiff;\\n }\\n\\n // If there's no weight, token count must be 0 so there's nothing left to do.\\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\\n\\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\\n uint256 _decimals = _amount.decimals;\\n\\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\\n // 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`.\\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\\n ? 10**_decimals\\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\\n\\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\\n }\\n\\n /**\\n @notice\\n Records newly redeemed tokens of a project.\\n\\n @dev\\n 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.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\\n\\n @param _holder The account that is having its tokens redeemed.\\n @param _projectId The ID of the project to which the tokens being redeemed belong.\\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Bytes to send along to the data source, if one is provided.\\n\\n @return fundingCycle The funding cycle during which the redemption was made.\\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\\n @return memo A memo that should be passed along to the emitted event.\\n */\\n function recordRedemptionFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n string memory _memo,\\n bytes memory _metadata\\n )\\n external\\n override\\n nonReentrant\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 reclaimAmount,\\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n )\\n {\\n // Get a reference to the project's current funding cycle.\\n fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // The current funding cycle must not be paused.\\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\\n\\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\\n {\\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\\n JBTokenAmount memory _reclaimedTokenAmount;\\n uint256 _currentOverflow;\\n uint256 _totalSupply;\\n\\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\\n {\\n // Get a reference to the terminal's tokens.\\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\\n\\n // Get a reference to the terminal's decimals.\\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\\n\\n // Get areference to the terminal's currency.\\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\\n\\n // Get the amount of current overflow.\\n // 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.\\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\\n : _overflowDuring(\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n _projectId,\\n fundingCycle,\\n _currency\\n );\\n\\n // Get the number of outstanding tokens the project has.\\n _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\\n .totalOutstandingTokensOf(_projectId);\\n\\n // Can't redeem more tokens that is in the supply.\\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\\n\\n if (_currentOverflow != 0)\\n // Calculate reclaim amount using the current overflow amount.\\n reclaimAmount = _reclaimableOverflowDuring(\\n _projectId,\\n fundingCycle,\\n _tokenCount,\\n _totalSupply,\\n _currentOverflow\\n );\\n\\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\\n }\\n\\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\\n {\\n // Get a reference to the ballot state.\\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\\n\\n // Create the params that'll be sent to the data source.\\n JBRedeemParamsData memory _data = JBRedeemParamsData(\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n _holder,\\n _projectId,\\n fundingCycle.configuration,\\n _tokenCount,\\n _totalSupply,\\n _currentOverflow,\\n _reclaimedTokenAmount,\\n fundingCycle.useTotalOverflowForRedemptions(),\\n _state == JBBallotState.Active\\n ? fundingCycle.ballotRedemptionRate()\\n : fundingCycle.redemptionRate(),\\n _memo,\\n _metadata\\n );\\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\\n fundingCycle.dataSource()\\n ).redeemParams(_data);\\n }\\n } else {\\n memo = _memo;\\n }\\n }\\n\\n // Keep a reference to the amount that should be subtracted from the project's balance.\\n uint256 _balanceDiff = reclaimAmount;\\n\\n if (delegateAllocations.length != 0) {\\n // Validate all delegated amounts.\\n for (uint256 _i; _i < delegateAllocations.length; ) {\\n // Get a reference to the amount to be delegated.\\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\\n\\n // Validate if non-zero.\\n if (_delegatedAmount != 0)\\n // Increment the total amount being subtracted from the balance.\\n _balanceDiff = _balanceDiff + _delegatedAmount;\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n\\n // The amount being reclaimed must be within the project's balance.\\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\\n\\n // Remove the reclaimed funds from the project's balance.\\n if (_balanceDiff != 0) {\\n unchecked {\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\\n _balanceDiff;\\n }\\n }\\n }\\n\\n /**\\n @notice\\n Records newly distributed funds for a project.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \\n\\n @param _projectId The ID of the project that is having funds distributed.\\n @param _amount The amount to use from the distribution limit, as a fixed point number.\\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\\n\\n @return fundingCycle The funding cycle during which the distribution was made.\\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\\n */\\n function recordDistributionFor(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n )\\n external\\n override\\n nonReentrant\\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\\n {\\n // Get a reference to the project's current funding cycle.\\n fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // The funding cycle must not be configured to have distributions paused.\\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\\n\\n // The new total amount that has been distributed during this funding cycle.\\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\\n IJBSingleTokenPaymentTerminal(msg.sender)\\n ][_projectId][fundingCycle.number] + _amount;\\n\\n // Amount must be within what is still distributable.\\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController3_1(\\n directory.controllerOf(_projectId)\\n ).fundAccessConstraintsStore().distributionLimitOf(\\n _projectId,\\n fundingCycle.configuration,\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n IJBSingleTokenPaymentTerminal(msg.sender).token()\\n );\\n\\n // Make sure the new used amount is within the distribution limit.\\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\\n\\n // Make sure the currencies match.\\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\\n\\n // Get a reference to the terminal's currency.\\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\\n\\n // Convert the amount to the balance's currency.\\n distributedAmount = (_currency == _balanceCurrency)\\n ? _amount\\n : PRBMath.mulDiv(\\n _amount,\\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\\n );\\n\\n // The amount being distributed must be available.\\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\\n\\n // Store the new amount.\\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\\n fundingCycle.number\\n ] = _newUsedDistributionLimitOf;\\n\\n // Removed the distributed funds from the project's token balance.\\n unchecked {\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\\n distributedAmount;\\n }\\n }\\n\\n /**\\n @notice\\n Records newly used allowance funds of a project.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \\n\\n @param _projectId The ID of the project to use the allowance of.\\n @param _amount The amount to use from the allowance, as a fixed point number. \\n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\\n\\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\\n */\\n function recordUsedAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n )\\n external\\n override\\n nonReentrant\\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\\n {\\n // Get a reference to the project's current funding cycle.\\n fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\\n IJBSingleTokenPaymentTerminal(msg.sender)\\n ][_projectId][fundingCycle.configuration] + _amount;\\n\\n // There must be sufficient allowance available.\\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController3_1(\\n directory.controllerOf(_projectId)\\n ).fundAccessConstraintsStore().overflowAllowanceOf(\\n _projectId,\\n fundingCycle.configuration,\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n IJBSingleTokenPaymentTerminal(msg.sender).token()\\n );\\n\\n // Make sure the new used amount is within the allowance.\\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\\n\\n // Make sure the currencies match.\\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\\n\\n // Get a reference to the terminal's currency.\\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\\n\\n // Convert the amount to this store's terminal's token.\\n usedAmount = (_currency == _balanceCurrency)\\n ? _amount\\n : PRBMath.mulDiv(\\n _amount,\\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\\n );\\n\\n // The amount being distributed must be available in the overflow.\\n if (\\n usedAmount >\\n _overflowDuring(\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n _projectId,\\n fundingCycle,\\n _balanceCurrency\\n )\\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\\n\\n // Store the incremented value.\\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\\n fundingCycle.configuration\\n ] = _newUsedOverflowAllowanceOf;\\n\\n // Update the project's balance.\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\\n usedAmount;\\n }\\n\\n /**\\n @notice\\n Records newly added funds for the project.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \\n\\n @param _projectId The ID of the project to which the funds being added belong.\\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\\n */\\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\\n // Increment the balance.\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\\n _amount;\\n }\\n\\n /**\\n @notice\\n Records the migration of funds from this store.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\\n\\n @param _projectId The ID of the project being migrated.\\n\\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\\n */\\n function recordMigration(uint256 _projectId)\\n external\\n override\\n nonReentrant\\n returns (uint256 balance)\\n {\\n // Get a reference to the project's current funding cycle.\\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // Migration must be allowed.\\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\\n\\n // Return the current balance.\\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\\n\\n // Set the balance to 0.\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\\n }\\n\\n //*********************************************************************//\\n // --------------------- private helper functions -------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\\n\\n @dev \\n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\\n\\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\\n @param _overflow The amount of overflow to make the calculation with.\\n\\n @return The amount of overflowed tokens that can be reclaimed.\\n */\\n function _reclaimableOverflowDuring(\\n uint256 _projectId,\\n JBFundingCycle memory _fundingCycle,\\n uint256 _tokenCount,\\n uint256 _totalSupply,\\n uint256 _overflow\\n ) private view returns (uint256) {\\n // If the amount being redeemed is the total supply, return the rest of the overflow.\\n if (_tokenCount == _totalSupply) return _overflow;\\n\\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\\n JBBallotState.Active\\n ? _fundingCycle.ballotRedemptionRate()\\n : _fundingCycle.redemptionRate();\\n\\n // If the redemption rate is 0, nothing is claimable.\\n if (_redemptionRate == 0) return 0;\\n\\n // Get a reference to the linear proportion.\\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\\n\\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\\n\\n return\\n PRBMath.mulDiv(\\n _base,\\n _redemptionRate +\\n PRBMath.mulDiv(\\n _tokenCount,\\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\\n _totalSupply\\n ),\\n JBConstants.MAX_REDEMPTION_RATE\\n );\\n }\\n\\n /**\\n @notice\\n Gets the amount that is overflowing when measured from the specified funding cycle.\\n\\n @dev\\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\\n\\n @param _terminal The terminal for which the overflow is being calculated.\\n @param _projectId The ID of the project to get overflow for.\\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\\n\\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\\n */\\n function _overflowDuring(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n JBFundingCycle memory _fundingCycle,\\n uint256 _balanceCurrency\\n ) private view returns (uint256) {\\n // Get the current balance of the project.\\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\\n\\n // If there's no balance, there's no overflow.\\n if (_balanceOf == 0) return 0;\\n\\n // Get a reference to the distribution limit during the funding cycle.\\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController3_1(\\n directory.controllerOf(_projectId)\\n ).fundAccessConstraintsStore().distributionLimitOf(\\n _projectId,\\n _fundingCycle.configuration,\\n _terminal,\\n _terminal.token()\\n );\\n\\n // Get a reference to the amount still distributable during the funding cycle.\\n uint256 _distributionLimitRemaining = _distributionLimit -\\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\\n\\n // Convert the _distributionRemaining to be in terms of the provided currency.\\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\\n _distributionLimitRemaining = PRBMath.mulDiv(\\n _distributionLimitRemaining,\\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\\n );\\n\\n // Overflow is the balance of this project minus the amount that can still be distributed.\\n unchecked {\\n return\\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\\n }\\n }\\n\\n /**\\n @notice\\n Gets the amount that is currently overflowing across all of a project's terminals. \\n\\n @dev\\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\\n\\n @param _projectId The ID of the project to get the total overflow for.\\n @param _decimals The number of decimals that the fixed point overflow should include.\\n @param _currency The currency that the overflow should be in terms of.\\n\\n @return overflow The total overflow of a project's funds.\\n */\\n function _currentTotalOverflowOf(\\n uint256 _projectId,\\n uint256 _decimals,\\n uint256 _currency\\n ) private view returns (uint256) {\\n // Get a reference to the project's terminals.\\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\\n\\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\\n uint256 _ethOverflow;\\n\\n // Add the current ETH overflow for each terminal.\\n for (uint256 _i; _i < _terminals.length; ) {\\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\\n unchecked {\\n ++_i;\\n }\\n }\\n\\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.GAS_CURRENCY\\n ? _ethOverflow\\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.GAS_CURRENCY, _currency, 18));\\n\\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\\n return\\n (_decimals == 18)\\n ? _totalOverflow18Decimal\\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\\n }\\n}\\n\",\"keccak256\":\"0x7fc9e05a77c0d37c10709df6f479562d73d684b9aec28d0227e83beffa4d2a01\",\"license\":\"MIT\"},\"contracts/enums/JBBallotState.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nenum JBBallotState {\\n Active,\\n Approved,\\n Failed\\n}\\n\",\"keccak256\":\"0x891fcac63470398b3a11239da7feba6b07d640809fcefd2404303b823d7378f8\",\"license\":\"MIT\"},\"contracts/interfaces/IJBController.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBFundAccessConstraints.sol';\\nimport './../structs/JBFundingCycleData.sol';\\nimport './../structs/JBFundingCycleMetadata.sol';\\nimport './../structs/JBGroupedSplits.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBMigratable.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBSplitsStore.sol';\\nimport './IJBTokenStore.sol';\\n\\ninterface IJBController is IERC165 {\\n event LaunchProject(uint256 configuration, uint256 projectId, string memo, address caller);\\n\\n event LaunchFundingCycles(uint256 configuration, uint256 projectId, string memo, address caller);\\n\\n event ReconfigureFundingCycles(\\n uint256 configuration,\\n uint256 projectId,\\n string memo,\\n address caller\\n );\\n\\n event SetFundAccessConstraints(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n JBFundAccessConstraints constraints,\\n address caller\\n );\\n\\n event DistributeReservedTokens(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address beneficiary,\\n uint256 tokenCount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n address caller\\n );\\n\\n event DistributeToReservedTokenSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n uint256 tokenCount,\\n address caller\\n );\\n\\n event MintTokens(\\n address indexed beneficiary,\\n uint256 indexed projectId,\\n uint256 tokenCount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n uint256 reservedRate,\\n address caller\\n );\\n\\n event BurnTokens(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 tokenCount,\\n string memo,\\n address caller\\n );\\n\\n event Migrate(uint256 indexed projectId, IJBMigratable to, address caller);\\n\\n event PrepMigration(uint256 indexed projectId, address from, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function tokenStore() external view returns (IJBTokenStore);\\n\\n function splitsStore() external view returns (IJBSplitsStore);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function reservedTokenBalanceOf(uint256 _projectId, uint256 _reservedRate)\\n external\\n view\\n returns (uint256);\\n\\n function distributionLimitOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n IJBPaymentTerminal _terminal,\\n address _token\\n ) external view returns (uint256 distributionLimit, uint256 distributionLimitCurrency);\\n\\n function overflowAllowanceOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n IJBPaymentTerminal _terminal,\\n address _token\\n ) external view returns (uint256 overflowAllowance, uint256 overflowAllowanceCurrency);\\n\\n function totalOutstandingTokensOf(uint256 _projectId, uint256 _reservedRate)\\n external\\n view\\n returns (uint256);\\n\\n function getFundingCycleOf(uint256 _projectId, uint256 _configuration)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function latestConfiguredFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (\\n JBFundingCycle memory,\\n JBFundingCycleMetadata memory metadata,\\n JBBallotState\\n );\\n\\n function currentFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function queuedFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function launchProjectFor(\\n address _owner,\\n JBProjectMetadata calldata _projectMetadata,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n IJBPaymentTerminal[] memory _terminals,\\n string calldata _memo\\n ) external returns (uint256 projectId);\\n\\n function launchFundingCyclesFor(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n IJBPaymentTerminal[] memory _terminals,\\n string calldata _memo\\n ) external returns (uint256 configuration);\\n\\n function reconfigureFundingCyclesOf(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n string calldata _memo\\n ) external returns (uint256);\\n\\n function mintTokensOf(\\n uint256 _projectId,\\n uint256 _tokenCount,\\n address _beneficiary,\\n string calldata _memo,\\n bool _preferClaimedTokens,\\n bool _useReservedRate\\n ) external returns (uint256 beneficiaryTokenCount);\\n\\n function burnTokensOf(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n string calldata _memo,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function distributeReservedTokensOf(uint256 _projectId, string memory _memo)\\n external\\n returns (uint256);\\n\\n function migrate(uint256 _projectId, IJBMigratable _to) external;\\n}\\n\",\"keccak256\":\"0xb1ee4b41f2a06f28f69c74cb729b8964f2e75f3c545a68f85bd9082b5575bc85\",\"license\":\"MIT\"},\"contracts/interfaces/IJBController3_0_1.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBFundAccessConstraints.sol';\\nimport './../structs/JBFundingCycleData.sol';\\nimport './../structs/JBFundingCycleMetadata.sol';\\nimport './../structs/JBGroupedSplits.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBController.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBMigratable.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBSplitsStore.sol';\\nimport './IJBTokenStore.sol';\\n\\ninterface IJBController3_0_1 {\\n function reservedTokenBalanceOf(uint256 _projectId) external view returns (uint256);\\n function totalOutstandingTokensOf(uint256 _projectId) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xf853badd9b8c149b7e1cd01b1123a949bc64036cfcc9e4b6d237b6911eccb058\",\"license\":\"MIT\"},\"contracts/interfaces/IJBController3_1.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBFundAccessConstraints.sol';\\nimport './../structs/JBFundingCycleData.sol';\\nimport './../structs/JBFundingCycleMetadata.sol';\\nimport './../structs/JBGroupedSplits.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBController3_0_1.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFundAccessConstraintsStore.sol';\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBMigratable.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBSplitsStore.sol';\\nimport './IJBTokenStore.sol';\\n\\ninterface IJBController3_1 is IJBController3_0_1, IERC165 {\\n event LaunchProject(uint256 configuration, uint256 projectId, string memo, address caller);\\n\\n event LaunchFundingCycles(uint256 configuration, uint256 projectId, string memo, address caller);\\n\\n event ReconfigureFundingCycles(\\n uint256 configuration,\\n uint256 projectId,\\n string memo,\\n address caller\\n );\\n\\n event DistributeReservedTokens(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address beneficiary,\\n uint256 tokenCount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n address caller\\n );\\n\\n event DistributeToReservedTokenSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n uint256 tokenCount,\\n address caller\\n );\\n\\n event MintTokens(\\n address indexed beneficiary,\\n uint256 indexed projectId,\\n uint256 tokenCount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n uint256 reservedRate,\\n address caller\\n );\\n\\n event BurnTokens(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 tokenCount,\\n string memo,\\n address caller\\n );\\n\\n event Migrate(uint256 indexed projectId, IJBMigratable to, address caller);\\n\\n event PrepMigration(uint256 indexed projectId, address from, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function tokenStore() external view returns (IJBTokenStore);\\n\\n function splitsStore() external view returns (IJBSplitsStore);\\n\\n function fundAccessConstraintsStore() external view returns (IJBFundAccessConstraintsStore);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function reservedTokenBalanceOf(uint256 _projectId) external view returns (uint256);\\n\\n function totalOutstandingTokensOf(uint256 _projectId) external view returns (uint256);\\n\\n function getFundingCycleOf(uint256 _projectId, uint256 _configuration)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function latestConfiguredFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (\\n JBFundingCycle memory,\\n JBFundingCycleMetadata memory metadata,\\n JBBallotState\\n );\\n\\n function currentFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function queuedFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function launchProjectFor(\\n address _owner,\\n JBProjectMetadata calldata _projectMetadata,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n IJBPaymentTerminal[] memory _terminals,\\n string calldata _memo\\n ) external returns (uint256 projectId);\\n\\n function launchFundingCyclesFor(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n IJBPaymentTerminal[] memory _terminals,\\n string calldata _memo\\n ) external returns (uint256 configuration);\\n\\n function reconfigureFundingCyclesOf(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n string calldata _memo\\n ) external returns (uint256);\\n\\n function mintTokensOf(\\n uint256 _projectId,\\n uint256 _tokenCount,\\n address _beneficiary,\\n string calldata _memo,\\n bool _preferClaimedTokens,\\n bool _useReservedRate\\n ) external returns (uint256 beneficiaryTokenCount);\\n\\n function burnTokensOf(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n string calldata _memo,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function distributeReservedTokensOf(uint256 _projectId, string memory _memo)\\n external\\n returns (uint256);\\n\\n function migrate(uint256 _projectId, IJBMigratable _to) external;\\n}\\n\",\"keccak256\":\"0x9aea97f1a77f48d313aee6c9ea97dffdfdb4f50c1cfd94f0b360a8ce6e383f4c\",\"license\":\"MIT\"},\"contracts/interfaces/IJBDirectory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBProjects.sol';\\n\\ninterface IJBDirectory {\\n event SetController(uint256 indexed projectId, address indexed controller, address caller);\\n\\n event AddTerminal(uint256 indexed projectId, IJBPaymentTerminal indexed terminal, address caller);\\n\\n event SetTerminals(uint256 indexed projectId, IJBPaymentTerminal[] terminals, address caller);\\n\\n event SetPrimaryTerminal(\\n uint256 indexed projectId,\\n address indexed token,\\n IJBPaymentTerminal indexed terminal,\\n address caller\\n );\\n\\n event SetIsAllowedToSetFirstController(address indexed addr, bool indexed flag, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function controllerOf(uint256 _projectId) external view returns (address);\\n\\n function isAllowedToSetFirstController(address _address) external view returns (bool);\\n\\n function terminalsOf(uint256 _projectId) external view returns (IJBPaymentTerminal[] memory);\\n\\n function isTerminalOf(uint256 _projectId, IJBPaymentTerminal _terminal)\\n external\\n view\\n returns (bool);\\n\\n function primaryTerminalOf(uint256 _projectId, address _token)\\n external\\n view\\n returns (IJBPaymentTerminal);\\n\\n function setControllerOf(uint256 _projectId, address _controller) external;\\n\\n function setTerminalsOf(uint256 _projectId, IJBPaymentTerminal[] calldata _terminals) external;\\n\\n function setPrimaryTerminalOf(\\n uint256 _projectId,\\n address _token,\\n IJBPaymentTerminal _terminal\\n ) external;\\n\\n function setIsAllowedToSetFirstController(address _address, bool _flag) external;\\n}\\n\",\"keccak256\":\"0x715321646db00514d1355ed43c40cd3f01e94959552fd07797b315d9c49cdb1d\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundAccessConstraintsStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBFundAccessConstraints.sol';\\nimport './IJBPaymentTerminal.sol';\\n\\ninterface IJBFundAccessConstraintsStore is IERC165 {\\n event SetFundAccessConstraints(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed projectId,\\n JBFundAccessConstraints constraints,\\n address caller\\n );\\n\\n function distributionLimitOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n IJBPaymentTerminal _terminal,\\n address _token\\n ) external view returns (uint256 distributionLimit, uint256 distributionLimitCurrency);\\n\\n function overflowAllowanceOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n IJBPaymentTerminal _terminal,\\n address _token\\n ) external view returns (uint256 overflowAllowance, uint256 overflowAllowanceCurrency);\\n\\n function setFor(\\n uint256 _projectId,\\n uint256 _configuration,\\n JBFundAccessConstraints[] memory _fundAccessConstaints\\n ) external;\\n}\\n\",\"keccak256\":\"0x3158c6cab1b81827a5a2d90a5936a0c7f8ba0d1bcdb05ae8b8a1ac7f03d0c999\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleBallot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../enums/JBBallotState.sol';\\n\\ninterface IJBFundingCycleBallot is IERC165 {\\n function duration() external view returns (uint256);\\n\\n function stateOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n uint256 _start\\n ) external view returns (JBBallotState);\\n}\\n\",\"keccak256\":\"0x49553a56209237846bc400cf27f260824a6bd06fd8094a7eb5abb9de75779598\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleDataSource.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBPayDelegateAllocation.sol';\\nimport './../structs/JBPayParamsData.sol';\\nimport './../structs/JBRedeemParamsData.sol';\\nimport './../structs/JBRedemptionDelegateAllocation.sol';\\n\\n/**\\n @title\\n Datasource\\n\\n @notice\\n The datasource is called by JBPaymentTerminal on pay and redemption, and provide an extra layer of logic to use \\n a custom weight, a custom memo and/or a pay/redeem delegate\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n*/\\ninterface IJBFundingCycleDataSource is IERC165 {\\n /**\\n @notice\\n The datasource implementation for JBPaymentTerminal.pay(..)\\n\\n @param _data the data passed to the data source in terminal.pay(..), as a JBPayParamsData struct:\\n IJBPaymentTerminal terminal;\\n address payer;\\n JBTokenAmount amount;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n address beneficiary;\\n uint256 weight;\\n uint256 reservedRate;\\n string memo;\\n bytes metadata;\\n\\n @return weight the weight to use to override the funding cycle weight\\n @return memo the memo to override the pay(..) memo\\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\\n */\\n function payParams(JBPayParamsData calldata _data)\\n external\\n returns (\\n uint256 weight,\\n string memory memo,\\n JBPayDelegateAllocation[] memory delegateAllocations\\n );\\n\\n /**\\n @notice\\n The datasource implementation for JBPaymentTerminal.redeemTokensOf(..)\\n\\n @param _data the data passed to the data source in terminal.redeemTokensOf(..), as a JBRedeemParamsData struct:\\n IJBPaymentTerminal terminal;\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 tokenCount;\\n uint256 totalSupply;\\n uint256 overflow;\\n JBTokenAmount reclaimAmount;\\n bool useTotalOverflow;\\n uint256 redemptionRate;\\n uint256 ballotRedemptionRate;\\n string memo;\\n bytes metadata;\\n\\n @return reclaimAmount The amount to claim, overriding the terminal logic.\\n @return memo The memo to override the redeemTokensOf(..) memo.\\n @return delegateAllocations The amount to send to delegates instead of adding to the beneficiary.\\n */\\n function redeemParams(JBRedeemParamsData calldata _data)\\n external\\n returns (\\n uint256 reclaimAmount,\\n string memory memo,\\n JBRedemptionDelegateAllocation[] memory delegateAllocations\\n );\\n}\\n\",\"keccak256\":\"0xa424abc146a61b69db83e511c064492da6fab6d8226e13d1580bc9fbc50d6738\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../enums/JBBallotState.sol';\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBFundingCycleData.sol';\\n\\ninterface IJBFundingCycleStore {\\n event Configure(\\n uint256 indexed configuration,\\n uint256 indexed projectId,\\n JBFundingCycleData data,\\n uint256 metadata,\\n uint256 mustStartAtOrAfter,\\n address caller\\n );\\n\\n event Init(uint256 indexed configuration, uint256 indexed projectId, uint256 indexed basedOn);\\n\\n function latestConfigurationOf(uint256 _projectId) external view returns (uint256);\\n\\n function get(uint256 _projectId, uint256 _configuration)\\n external\\n view\\n returns (JBFundingCycle memory);\\n\\n function latestConfiguredOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBBallotState ballotState);\\n\\n function queuedOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentBallotStateOf(uint256 _projectId) external view returns (JBBallotState);\\n\\n function configureFor(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n uint256 _metadata,\\n uint256 _mustStartAtOrAfter\\n ) external returns (JBFundingCycle memory fundingCycle);\\n}\\n\",\"keccak256\":\"0xaead823851433be0c2ddc8f8086813e6cd647de3a1bc0f7570a5d6b38c378b5a\",\"license\":\"MIT\"},\"contracts/interfaces/IJBMigratable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBMigratable {\\n function prepForMigrationOf(uint256 _projectId, address _from) external;\\n}\\n\",\"keccak256\":\"0xc81053e4b4754fc510aa04fecd3ab1460f01e3e27761e7a8c94f631a978ae127\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPayDelegate.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBDidPayData.sol';\\n\\n/**\\n @title\\n Pay delegate\\n\\n @notice\\n Delegate called after JBTerminal.pay(..) logic completion (if passed by the funding cycle datasource)\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n*/\\ninterface IJBPayDelegate is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.pay(..), after the execution of its logic\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control\\n \\n @param _data the data passed by the terminal, as a JBDidPayData struct:\\n address payer;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n JBTokenAmount amount;\\n JBTokenAmount forwardedAmount;\\n uint256 projectTokenCount;\\n address beneficiary;\\n bool preferClaimedTokens;\\n string memo;\\n bytes metadata;\\n */\\n function didPay(JBDidPayData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0xa797de18b69eceba117e1f0b3810cf3cc2d2791417d580a5bdc510d1b868ab26\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\n\\ninterface IJBPaymentTerminal is IERC165 {\\n function acceptsToken(address _token, uint256 _projectId) external view returns (bool);\\n\\n function currencyForToken(address _token) external view returns (uint256);\\n\\n function decimalsForToken(address _token) external view returns (uint256);\\n\\n // Return value must be a fixed point number with 18 decimals.\\n function currentEthOverflowOf(uint256 _projectId) external view returns (uint256);\\n\\n function pay(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable returns (uint256 beneficiaryTokenCount);\\n\\n function addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable;\\n}\\n\",\"keccak256\":\"0xb7826f5ed609359ce322c09e83236c47ba385df1c3cad3607e56fd0a2e00eee2\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPriceFeed.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBPriceFeed {\\n function currentPrice(uint256 _targetDecimals) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x57c71282fec1b34b00cf991ffed2e36031c393e35bfa7ca5d723eb6572fb7122\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPrices.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBPriceFeed.sol';\\n\\ninterface IJBPrices {\\n event AddFeed(uint256 indexed currency, uint256 indexed base, IJBPriceFeed feed);\\n\\n function feedFor(uint256 _currency, uint256 _base) external view returns (IJBPriceFeed);\\n\\n function priceFor(\\n uint256 _currency,\\n uint256 _base,\\n uint256 _decimals\\n ) external view returns (uint256);\\n\\n function addFeedFor(\\n uint256 _currency,\\n uint256 _base,\\n IJBPriceFeed _priceFeed\\n ) external;\\n}\\n\",\"keccak256\":\"0x82a175b1f4b95b506c98406576cd59cbe04615e3df24f9cf3587b61b8ee323b1\",\"license\":\"MIT\"},\"contracts/interfaces/IJBProjects.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBTokenUriResolver.sol';\\n\\ninterface IJBProjects is IERC721 {\\n event Create(\\n uint256 indexed projectId,\\n address indexed owner,\\n JBProjectMetadata metadata,\\n address caller\\n );\\n\\n event SetMetadata(uint256 indexed projectId, JBProjectMetadata metadata, address caller);\\n\\n event SetTokenUriResolver(IJBTokenUriResolver indexed resolver, address caller);\\n\\n function count() external view returns (uint256);\\n\\n function metadataContentOf(uint256 _projectId, uint256 _domain)\\n external\\n view\\n returns (string memory);\\n\\n function tokenUriResolver() external view returns (IJBTokenUriResolver);\\n\\n function createFor(address _owner, JBProjectMetadata calldata _metadata)\\n external\\n returns (uint256 projectId);\\n\\n function setMetadataOf(uint256 _projectId, JBProjectMetadata calldata _metadata) external;\\n\\n function setTokenUriResolver(IJBTokenUriResolver _newResolver) external;\\n}\\n\",\"keccak256\":\"0x7cfc021d0bd7e73b1ba8f4845d7d35e3419d6a14d3d25ca3a8010e7f91062fe4\",\"license\":\"MIT\"},\"contracts/interfaces/IJBRedemptionDelegate.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBDidRedeemData.sol';\\n\\n/**\\n @title\\n Redemption delegate\\n\\n @notice\\n Delegate called after JBTerminal.redeemTokensOf(..) logic completion (if passed by the funding cycle datasource)\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n*/\\ninterface IJBRedemptionDelegate is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.redeemTokensOf(..), after the execution of its logic\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control\\n \\n @param _data the data passed by the terminal, as a JBDidRedeemData struct:\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 projectTokenCount;\\n JBTokenAmount reclaimedAmount;\\n JBTokenAmount forwardedAmount;\\n address payable beneficiary;\\n string memo;\\n bytes metadata;\\n */\\n function didRedeem(JBDidRedeemData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0x172d2c0be65e72e54f71ae521907067f0fa30e8ca05c4f88826903208aa437e2\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSingleTokenPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBPaymentTerminal.sol';\\n\\ninterface IJBSingleTokenPaymentTerminal is IJBPaymentTerminal {\\n function token() external view returns (address);\\n\\n function currency() external view returns (uint256);\\n\\n function decimals() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xf6e78323caa9af7bbf024f44b2032a83fed0394e0b3a242a6346e73c85b2e46f\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSingleTokenPaymentTerminalStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBPayDelegateAllocation.sol';\\nimport './../structs/JBRedemptionDelegateAllocation.sol';\\nimport './../structs/JBTokenAmount.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBPrices.sol';\\nimport './IJBSingleTokenPaymentTerminal.sol';\\n\\ninterface IJBSingleTokenPaymentTerminalStore {\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function prices() external view returns (IJBPrices);\\n\\n function balanceOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\\n external\\n view\\n returns (uint256);\\n\\n function usedDistributionLimitOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _fundingCycleNumber\\n ) external view returns (uint256);\\n\\n function usedOverflowAllowanceOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _fundingCycleConfiguration\\n ) external view returns (uint256);\\n\\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\\n external\\n view\\n returns (uint256);\\n\\n function currentTotalOverflowOf(\\n uint256 _projectId,\\n uint256 _decimals,\\n uint256 _currency\\n ) external view returns (uint256);\\n\\n function currentReclaimableOverflowOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n bool _useTotalOverflow\\n ) external view returns (uint256);\\n\\n function currentReclaimableOverflowOf(\\n uint256 _projectId,\\n uint256 _tokenCount,\\n uint256 _totalSupply,\\n uint256 _overflow\\n ) external view returns (uint256);\\n\\n function recordPaymentFrom(\\n address _payer,\\n JBTokenAmount memory _amount,\\n uint256 _projectId,\\n uint256 _baseWeightCurrency,\\n address _beneficiary,\\n string calldata _memo,\\n bytes calldata _metadata\\n )\\n external\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 tokenCount,\\n JBPayDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n );\\n\\n function recordRedemptionFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n string calldata _memo,\\n bytes calldata _metadata\\n )\\n external\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 reclaimAmount,\\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n );\\n\\n function recordDistributionFor(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n ) external returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount);\\n\\n function recordUsedAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n ) external returns (JBFundingCycle memory fundingCycle, uint256 withdrawnAmount);\\n\\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external;\\n\\n function recordMigration(uint256 _projectId) external returns (uint256 balance);\\n}\\n\",\"keccak256\":\"0xd78929c9371fd7895b829ef5e4ad4b3786523c3580ac3f6f5f25d2b5941c0dd3\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSplitAllocator.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport '../structs/JBSplitAllocationData.sol';\\n\\n/**\\n @title\\n Split allocator\\n\\n @notice\\n Provide a way to process a single split with extra logic\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n\\n @dev\\n The contract address should be set as an allocator in the adequate split\\n*/\\ninterface IJBSplitAllocator is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.distributePayoutOf(..), during the processing of the split including it\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control. The token and/or eth are optimistically transfered\\n to the allocator for its logic.\\n \\n @param _data the data passed by the terminal, as a JBSplitAllocationData struct:\\n address token;\\n uint256 amount;\\n uint256 decimals;\\n uint256 projectId;\\n uint256 group;\\n JBSplit split;\\n */\\n function allocate(JBSplitAllocationData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0x5efb6f51fc161f42ff58989386ad99028e4039a0ba897d66f358c3dfcf686105\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSplitsStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBGroupedSplits.sol';\\nimport './../structs/JBSplit.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBProjects.sol';\\n\\ninterface IJBSplitsStore {\\n event SetSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n address caller\\n );\\n\\n function projects() external view returns (IJBProjects);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function splitsOf(\\n uint256 _projectId,\\n uint256 _domain,\\n uint256 _group\\n ) external view returns (JBSplit[] memory);\\n\\n function set(\\n uint256 _projectId,\\n uint256 _domain,\\n JBGroupedSplits[] memory _groupedSplits\\n ) external;\\n}\\n\",\"keccak256\":\"0x66dab3dd394e318b850401ca92c2963b906cc0ad5562fa5d4f6f850175d1c77a\",\"license\":\"MIT\"},\"contracts/interfaces/IJBToken.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBToken {\\n function projectId() external view returns (uint256);\\n\\n function decimals() external view returns (uint8);\\n\\n function totalSupply(uint256 _projectId) external view returns (uint256);\\n\\n function balanceOf(address _account, uint256 _projectId) external view returns (uint256);\\n\\n function mint(\\n uint256 _projectId,\\n address _account,\\n uint256 _amount\\n ) external;\\n\\n function burn(\\n uint256 _projectId,\\n address _account,\\n uint256 _amount\\n ) external;\\n\\n function approve(\\n uint256,\\n address _spender,\\n uint256 _amount\\n ) external;\\n\\n function transfer(\\n uint256 _projectId,\\n address _to,\\n uint256 _amount\\n ) external;\\n\\n function transferFrom(\\n uint256 _projectId,\\n address _from,\\n address _to,\\n uint256 _amount\\n ) external;\\n}\\n\",\"keccak256\":\"0xe8969210417736c85d71101bf1c0bd8ebbf9d1e62a93e758148bd5709a6c7097\",\"license\":\"MIT\"},\"contracts/interfaces/IJBTokenStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBProjects.sol';\\nimport './IJBToken.sol';\\n\\ninterface IJBTokenStore {\\n event Issue(\\n uint256 indexed projectId,\\n IJBToken indexed token,\\n string name,\\n string symbol,\\n address caller\\n );\\n\\n event Mint(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 amount,\\n bool tokensWereClaimed,\\n bool preferClaimedTokens,\\n address caller\\n );\\n\\n event Burn(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 amount,\\n uint256 initialUnclaimedBalance,\\n uint256 initialClaimedBalance,\\n bool preferClaimedTokens,\\n address caller\\n );\\n\\n event Claim(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 initialUnclaimedBalance,\\n uint256 amount,\\n address caller\\n );\\n\\n event Set(uint256 indexed projectId, IJBToken indexed newToken, address caller);\\n\\n event Transfer(\\n address indexed holder,\\n uint256 indexed projectId,\\n address indexed recipient,\\n uint256 amount,\\n address caller\\n );\\n\\n function tokenOf(uint256 _projectId) external view returns (IJBToken);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function unclaimedBalanceOf(address _holder, uint256 _projectId) external view returns (uint256);\\n\\n function unclaimedTotalSupplyOf(uint256 _projectId) external view returns (uint256);\\n\\n function totalSupplyOf(uint256 _projectId) external view returns (uint256);\\n\\n function balanceOf(address _holder, uint256 _projectId) external view returns (uint256 _result);\\n\\n function issueFor(\\n uint256 _projectId,\\n string calldata _name,\\n string calldata _symbol\\n ) external returns (IJBToken token);\\n\\n function setFor(uint256 _projectId, IJBToken _token) external;\\n\\n function burnFrom(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function mintFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function claimFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount\\n ) external;\\n\\n function transferFrom(\\n address _holder,\\n uint256 _projectId,\\n address _recipient,\\n uint256 _amount\\n ) external;\\n}\\n\",\"keccak256\":\"0x98459e3af050d41dfeffdc97f1c93330207ba450f8ff3613224b49a89eeca9c6\",\"license\":\"MIT\"},\"contracts/interfaces/IJBTokenUriResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBTokenUriResolver {\\n function getUri(uint256 _projectId) external view returns (string memory tokenUri);\\n}\\n\",\"keccak256\":\"0xd267fd8ca7c21c2c71794acdb9a98314c33a35fc559e0bf0897a6686d196d174\",\"license\":\"MIT\"},\"contracts/libraries/JBConstants.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/**\\n @notice\\n Global constants used across Juicebox contracts.\\n*/\\nlibrary JBConstants {\\n uint256 public constant MAX_RESERVED_RATE = 10_000;\\n uint256 public constant MAX_REDEMPTION_RATE = 10_000;\\n uint256 public constant MAX_DISCOUNT_RATE = 1_000_000_000;\\n uint256 public constant SPLITS_TOTAL_PERCENT = 1_000_000_000;\\n uint256 public constant MAX_FEE = 1_000_000_000;\\n uint256 public constant MAX_FEE_DISCOUNT = 1_000_000_000;\\n}\\n\",\"keccak256\":\"0x34362846a1cd428a8bdedf4ab6857e11402f345cb87b994b2e7fb6d2474b808d\",\"license\":\"MIT\"},\"contracts/libraries/JBCurrencies.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBCurrencies {\\n uint256 public constant ETH = 1;\\n uint256 public constant USD = 2;\\n}\\n\",\"keccak256\":\"0x7e417ff25c173608ee4fe6d9fc3dcd5e1458c78c889af12bac47b1189a436076\",\"license\":\"MIT\"},\"contracts/libraries/JBFixedPointNumber.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nlibrary JBFixedPointNumber {\\n function adjustDecimals(\\n uint256 _value,\\n uint256 _decimals,\\n uint256 _targetDecimals\\n ) internal pure returns (uint256) {\\n // If decimals need adjusting, multiply or divide the price by the decimal adjuster to get the normalized result.\\n if (_targetDecimals == _decimals) return _value;\\n else if (_targetDecimals > _decimals) return _value * 10**(_targetDecimals - _decimals);\\n else return _value / 10**(_decimals - _targetDecimals);\\n }\\n}\\n\",\"keccak256\":\"0x18efac48269f3a3bd7e9a1c770776f950e0afa86769e6f8b128002c3b8c6742c\",\"license\":\"MIT\"},\"contracts/libraries/JBFundingCycleMetadataResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBFundingCycleMetadata.sol';\\nimport './../structs/JBGlobalFundingCycleMetadata.sol';\\nimport './JBConstants.sol';\\nimport './JBGlobalFundingCycleMetadataResolver.sol';\\n\\nlibrary JBFundingCycleMetadataResolver {\\n function global(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (JBGlobalFundingCycleMetadata memory)\\n {\\n return JBGlobalFundingCycleMetadataResolver.expandMetadata(uint8(_fundingCycle.metadata >> 8));\\n }\\n\\n function reservedRate(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n return uint256(uint16(_fundingCycle.metadata >> 24));\\n }\\n\\n function redemptionRate(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n // Redemption rate is a number 0-10000. It's inverse was stored so the most common case of 100% results in no storage needs.\\n return JBConstants.MAX_REDEMPTION_RATE - uint256(uint16(_fundingCycle.metadata >> 40));\\n }\\n\\n function ballotRedemptionRate(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (uint256)\\n {\\n // Redemption rate is a number 0-10000. It's inverse was stored so the most common case of 100% results in no storage needs.\\n return JBConstants.MAX_REDEMPTION_RATE - uint256(uint16(_fundingCycle.metadata >> 56));\\n }\\n\\n function payPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 72) & 1) == 1;\\n }\\n\\n function distributionsPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 73) & 1) == 1;\\n }\\n\\n function redeemPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 74) & 1) == 1;\\n }\\n\\n function burnPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 75) & 1) == 1;\\n }\\n\\n function mintingAllowed(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 76) & 1) == 1;\\n }\\n\\n function terminalMigrationAllowed(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 77) & 1) == 1;\\n }\\n\\n function controllerMigrationAllowed(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 78) & 1) == 1;\\n }\\n\\n function shouldHoldFees(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 79) & 1) == 1;\\n }\\n\\n function preferClaimedTokenOverride(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 80) & 1) == 1;\\n }\\n\\n function useTotalOverflowForRedemptions(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 81) & 1) == 1;\\n }\\n\\n function useDataSourceForPay(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return (_fundingCycle.metadata >> 82) & 1 == 1;\\n }\\n\\n function useDataSourceForRedeem(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return (_fundingCycle.metadata >> 83) & 1 == 1;\\n }\\n\\n function dataSource(JBFundingCycle memory _fundingCycle) internal pure returns (address) {\\n return address(uint160(_fundingCycle.metadata >> 84));\\n }\\n\\n function metadata(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n return uint256(uint8(_fundingCycle.metadata >> 244));\\n }\\n\\n /**\\n @notice\\n Pack the funding cycle metadata.\\n\\n @param _metadata The metadata to validate and pack.\\n\\n @return packed The packed uint256 of all metadata params. The first 8 bits specify the version.\\n */\\n function packFundingCycleMetadata(JBFundingCycleMetadata memory _metadata)\\n internal\\n pure\\n returns (uint256 packed)\\n {\\n // version 1 in the bits 0-7 (8 bits).\\n packed = 1;\\n // global metadta in bits 8-23 (16 bits).\\n packed |=\\n JBGlobalFundingCycleMetadataResolver.packFundingCycleGlobalMetadata(_metadata.global) <<\\n 8;\\n // reserved rate in bits 24-39 (16 bits).\\n packed |= _metadata.reservedRate << 24;\\n // redemption rate in bits 40-55 (16 bits).\\n // redemption rate is a number 0-10000. Store the reverse so the most common case of 100% results in no storage needs.\\n packed |= (JBConstants.MAX_REDEMPTION_RATE - _metadata.redemptionRate) << 40;\\n // ballot redemption rate rate in bits 56-71 (16 bits).\\n // ballot redemption rate is a number 0-10000. Store the reverse so the most common case of 100% results in no storage needs.\\n packed |= (JBConstants.MAX_REDEMPTION_RATE - _metadata.ballotRedemptionRate) << 56;\\n // pause pay in bit 72.\\n if (_metadata.pausePay) packed |= 1 << 72;\\n // pause tap in bit 73.\\n if (_metadata.pauseDistributions) packed |= 1 << 73;\\n // pause redeem in bit 74.\\n if (_metadata.pauseRedeem) packed |= 1 << 74;\\n // pause burn in bit 75.\\n if (_metadata.pauseBurn) packed |= 1 << 75;\\n // allow minting in bit 76.\\n if (_metadata.allowMinting) packed |= 1 << 76;\\n // allow terminal migration in bit 77.\\n if (_metadata.allowTerminalMigration) packed |= 1 << 77;\\n // allow controller migration in bit 78.\\n if (_metadata.allowControllerMigration) packed |= 1 << 78;\\n // hold fees in bit 79.\\n if (_metadata.holdFees) packed |= 1 << 79;\\n // prefer claimed token override in bit 80.\\n if (_metadata.preferClaimedTokenOverride) packed |= 1 << 80;\\n // useTotalOverflowForRedemptions in bit 81.\\n if (_metadata.useTotalOverflowForRedemptions) packed |= 1 << 81;\\n // use pay data source in bit 82.\\n if (_metadata.useDataSourceForPay) packed |= 1 << 82;\\n // use redeem data source in bit 83.\\n if (_metadata.useDataSourceForRedeem) packed |= 1 << 83;\\n // data source address in bits 84-243.\\n packed |= uint256(uint160(address(_metadata.dataSource))) << 84;\\n // metadata in bits 244-252 (8 bits).\\n packed |= _metadata.metadata << 244;\\n }\\n\\n /**\\n @notice\\n Expand the funding cycle metadata.\\n\\n @param _fundingCycle The funding cycle having its metadata expanded.\\n\\n @return metadata The metadata object.\\n */\\n function expandMetadata(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (JBFundingCycleMetadata memory)\\n {\\n return\\n JBFundingCycleMetadata(\\n global(_fundingCycle),\\n reservedRate(_fundingCycle),\\n redemptionRate(_fundingCycle),\\n ballotRedemptionRate(_fundingCycle),\\n payPaused(_fundingCycle),\\n distributionsPaused(_fundingCycle),\\n redeemPaused(_fundingCycle),\\n burnPaused(_fundingCycle),\\n mintingAllowed(_fundingCycle),\\n terminalMigrationAllowed(_fundingCycle),\\n controllerMigrationAllowed(_fundingCycle),\\n shouldHoldFees(_fundingCycle),\\n preferClaimedTokenOverride(_fundingCycle),\\n useTotalOverflowForRedemptions(_fundingCycle),\\n useDataSourceForPay(_fundingCycle),\\n useDataSourceForRedeem(_fundingCycle),\\n dataSource(_fundingCycle),\\n metadata(_fundingCycle)\\n );\\n }\\n}\\n\",\"keccak256\":\"0x3d045c38593102cfb6ac67f3ddf2232e1ff5518d6d021423ae2681387599fbd3\",\"license\":\"MIT\"},\"contracts/libraries/JBGlobalFundingCycleMetadataResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport './../structs/JBFundingCycleMetadata.sol';\\n\\nlibrary JBGlobalFundingCycleMetadataResolver {\\n function setTerminalsAllowed(uint8 _data) internal pure returns (bool) {\\n return (_data & 1) == 1;\\n }\\n\\n function setControllerAllowed(uint8 _data) internal pure returns (bool) {\\n return ((_data >> 1) & 1) == 1;\\n }\\n\\n function transfersPaused(uint8 _data) internal pure returns (bool) {\\n return ((_data >> 2) & 1) == 1;\\n }\\n\\n /**\\n @notice\\n Pack the global funding cycle metadata.\\n\\n @param _metadata The metadata to validate and pack.\\n\\n @return packed The packed uint256 of all global metadata params. The first 8 bits specify the version.\\n */\\n function packFundingCycleGlobalMetadata(JBGlobalFundingCycleMetadata memory _metadata)\\n internal\\n pure\\n returns (uint256 packed)\\n {\\n // allow set terminals in bit 0.\\n if (_metadata.allowSetTerminals) packed |= 1;\\n // allow set controller in bit 1.\\n if (_metadata.allowSetController) packed |= 1 << 1;\\n // pause transfers in bit 2.\\n if (_metadata.pauseTransfers) packed |= 1 << 2;\\n }\\n\\n /**\\n @notice\\n Expand the global funding cycle metadata.\\n\\n @param _packedMetadata The packed metadata to expand.\\n\\n @return metadata The global metadata object.\\n */\\n function expandMetadata(uint8 _packedMetadata)\\n internal\\n pure\\n returns (JBGlobalFundingCycleMetadata memory metadata)\\n {\\n return\\n JBGlobalFundingCycleMetadata(\\n setTerminalsAllowed(_packedMetadata),\\n setControllerAllowed(_packedMetadata),\\n transfersPaused(_packedMetadata)\\n );\\n }\\n}\\n\",\"keccak256\":\"0x0d998f938026edeb755987a79421267cf860801161b5f171206a200b60f1061f\",\"license\":\"MIT\"},\"contracts/structs/JBDidPayData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member payer The address from which the payment originated.\\n @member projectId The ID of the project for which the payment was made.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the payment is being made.\\n @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.\\n @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.\\n @member projectTokenCount The number of project tokens minted for the beneficiary.\\n @member beneficiary The address to which the tokens were minted.\\n @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.\\n @member memo The memo that is being emitted alongside the payment.\\n @member metadata Extra data to send to the delegate.\\n*/\\nstruct JBDidPayData {\\n address payer;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n JBTokenAmount amount;\\n JBTokenAmount forwardedAmount;\\n uint256 projectTokenCount;\\n address beneficiary;\\n bool preferClaimedTokens;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0xf3c664309b37790f16047ae97b0459889ae0242dfcde7fc8902c8d10c7f8e6b6\",\"license\":\"MIT\"},\"contracts/structs/JBDidRedeemData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member holder The holder of the tokens being redeemed.\\n @member projectId The ID of the project with which the redeemed tokens are associated.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the redemption is being made.\\n @member projectTokenCount The number of project tokens being redeemed.\\n @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.\\n @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.\\n @member beneficiary The address to which the reclaimed amount will be sent.\\n @member memo The memo that is being emitted alongside the redemption.\\n @member metadata Extra data to send to the delegate.\\n*/\\nstruct JBDidRedeemData {\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 projectTokenCount;\\n JBTokenAmount reclaimedAmount;\\n JBTokenAmount forwardedAmount;\\n address payable beneficiary;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0xe2c401f39723a7ce915b8bef328744c66daaf57460843964b941456c2258a412\",\"license\":\"MIT\"},\"contracts/structs/JBFundAccessConstraints.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBPaymentTerminal.sol';\\n\\n/** \\n @member terminal The terminal within which the distribution limit and the overflow allowance applies.\\n @member token The token for which the fund access constraints apply.\\n @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.\\n @member distributionLimitCurrency The currency of the distribution limit.\\n @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.\\n @member overflowAllowanceCurrency The currency of the overflow allowance.\\n*/\\nstruct JBFundAccessConstraints {\\n IJBPaymentTerminal terminal;\\n address token;\\n uint256 distributionLimit;\\n uint256 distributionLimitCurrency;\\n uint256 overflowAllowance;\\n uint256 overflowAllowanceCurrency;\\n}\\n\",\"keccak256\":\"0x85ebaa57b788cbdedc7a3d0eec4892eda5d79db7c1a6103797f10d0d989775b2\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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.\\n @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.\\n @member basedOn The `configuration` of the funding cycle that was active when this cycle was created.\\n @member start The timestamp marking the moment from which the funding cycle is considered active. It is a unix timestamp measured in seconds.\\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n @member metadata Extra data that can be associated with a funding cycle.\\n*/\\nstruct JBFundingCycle {\\n uint256 number;\\n uint256 configuration;\\n uint256 basedOn;\\n uint256 start;\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n uint256 metadata;\\n}\\n\",\"keccak256\":\"0xcdd3ac9b6fa67e62ada88d09b73bc35ade1cd77d43db712289266a788928b4c2\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycleData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n*/\\nstruct JBFundingCycleData {\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n}\\n\",\"keccak256\":\"0x2aa6368bf4dfc5797e8b02a978293de0c777fae2658de2c825a103587240f3b0\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycleMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBGlobalFundingCycleMetadata.sol';\\n\\n/** \\n @member global Data used globally in non-migratable ecosystem contracts.\\n @member reservedRate The reserved rate of the funding cycle. This number is a percentage calculated out of `JBConstants.MAX_RESERVED_RATE`.\\n @member redemptionRate The redemption rate of the funding cycle. This number is a percentage calculated out of `JBConstants.MAX_REDEMPTION_RATE`.\\n @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`.\\n @member pausePay A flag indicating if the pay functionality should be paused during the funding cycle.\\n @member pauseDistributions A flag indicating if the distribute functionality should be paused during the funding cycle.\\n @member pauseRedeem A flag indicating if the redeem functionality should be paused during the funding cycle.\\n @member pauseBurn A flag indicating if the burn functionality should be paused during the funding cycle.\\n @member allowMinting A flag indicating if minting tokens should be allowed during this funding cycle.\\n @member allowTerminalMigration A flag indicating if migrating terminals should be allowed during this funding cycle.\\n @member allowControllerMigration A flag indicating if migrating controllers should be allowed during this funding cycle.\\n @member holdFees A flag indicating if fees should be held during this funding cycle.\\n @member preferClaimedTokenOverride A flag indicating if claimed tokens should always be prefered to unclaimed tokens when minting.\\n @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.\\n @member useDataSourceForPay A flag indicating if the data source should be used for pay transactions during this funding cycle.\\n @member useDataSourceForRedeem A flag indicating if the data source should be used for redeem transactions during this funding cycle.\\n @member dataSource The data source to use during this funding cycle.\\n @member metadata Metadata of the metadata, up to uint8 in size.\\n*/\\nstruct JBFundingCycleMetadata {\\n JBGlobalFundingCycleMetadata global;\\n uint256 reservedRate;\\n uint256 redemptionRate;\\n uint256 ballotRedemptionRate;\\n bool pausePay;\\n bool pauseDistributions;\\n bool pauseRedeem;\\n bool pauseBurn;\\n bool allowMinting;\\n bool allowTerminalMigration;\\n bool allowControllerMigration;\\n bool holdFees;\\n bool preferClaimedTokenOverride;\\n bool useTotalOverflowForRedemptions;\\n bool useDataSourceForPay;\\n bool useDataSourceForRedeem;\\n address dataSource;\\n uint256 metadata;\\n}\\n\",\"keccak256\":\"0x783604440cac8d176332eab28166f188ee5c230378c08cfc95fea4f7187dc77d\",\"license\":\"MIT\"},\"contracts/structs/JBGlobalFundingCycleMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member allowSetTerminals A flag indicating if setting terminals should be allowed during this funding cycle.\\n @member allowSetController A flag indicating if setting a new controller should be allowed during this funding cycle.\\n @member pauseTransfers A flag indicating if the project token transfer functionality should be paused during the funding cycle.\\n*/\\nstruct JBGlobalFundingCycleMetadata {\\n bool allowSetTerminals;\\n bool allowSetController;\\n bool pauseTransfers;\\n}\\n\",\"keccak256\":\"0x05d85530305fec6d6eca54cdbc2cd9110cbda0146598032b0203aa4b622944ff\",\"license\":\"MIT\"},\"contracts/structs/JBGroupedSplits.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBSplit.sol';\\n\\n/** \\n @member group The group indentifier.\\n @member splits The splits to associate with the group.\\n*/\\nstruct JBGroupedSplits {\\n uint256 group;\\n JBSplit[] splits;\\n}\\n\",\"keccak256\":\"0x80be1b220da4ac04851ea540ebb94c1ec2b0442ec5bd1e88fdf78a56becd8b5a\",\"license\":\"MIT\"},\"contracts/structs/JBPayDelegateAllocation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '../interfaces/IJBPayDelegate.sol';\\n\\n/** \\n @member delegate A delegate contract to use for subsequent calls.\\n @member amount The amount to send to the delegate.\\n*/\\nstruct JBPayDelegateAllocation {\\n IJBPayDelegate delegate;\\n uint256 amount;\\n}\\n\",\"keccak256\":\"0xb4e558dc62231d89e9b48998012577d22c3e52b58e23401f22d9096827f6ea0c\",\"license\":\"MIT\"},\"contracts/structs/JBPayParamsData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBPaymentTerminal.sol';\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member terminal The terminal that is facilitating the payment.\\n @member payer The address from which the payment originated.\\n @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.\\n @member projectId The ID of the project being paid.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the payment is being made.\\n @member beneficiary The specified address that should be the beneficiary of anything that results from the payment.\\n @member weight The weight of the funding cycle during which the payment is being made.\\n @member reservedRate The reserved rate of the funding cycle during which the payment is being made.\\n @member memo The memo that was sent alongside the payment.\\n @member metadata Extra data provided by the payer.\\n*/\\nstruct JBPayParamsData {\\n IJBPaymentTerminal terminal;\\n address payer;\\n JBTokenAmount amount;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n address beneficiary;\\n uint256 weight;\\n uint256 reservedRate;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0x05007b26feb5d9a026b883c6d734a341b5a49ef7b8215fb40507882e2c14e24d\",\"license\":\"MIT\"},\"contracts/structs/JBProjectMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member content The metadata content.\\n @member domain The domain within which the metadata applies.\\n*/\\nstruct JBProjectMetadata {\\n string content;\\n uint256 domain;\\n}\\n\",\"keccak256\":\"0x90ad7b1014c0a9f945fe7a2efde9d5de41e40574fa27969070b1d2ff52033ea0\",\"license\":\"MIT\"},\"contracts/structs/JBRedeemParamsData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBPaymentTerminal.sol';\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member terminal The terminal that is facilitating the redemption.\\n @member holder The holder of the tokens being redeemed.\\n @member projectId The ID of the project whos tokens are being redeemed.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the redemption is being made.\\n @member tokenCount The proposed number of tokens being redeemed, as a fixed point number with 18 decimals.\\n @member totalSupply The total supply of tokens used in the calculation, as a fixed point number with 18 decimals.\\n @member overflow The amount of overflow used in the reclaim amount calculation.\\n @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.\\n @member useTotalOverflow If overflow across all of a project's terminals is being used when making redemptions.\\n @member redemptionRate The redemption rate of the funding cycle during which the redemption is being made.\\n @member memo The proposed memo that is being emitted alongside the redemption.\\n @member metadata Extra data provided by the redeemer.\\n*/\\nstruct JBRedeemParamsData {\\n IJBPaymentTerminal terminal;\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 tokenCount;\\n uint256 totalSupply;\\n uint256 overflow;\\n JBTokenAmount reclaimAmount;\\n bool useTotalOverflow;\\n uint256 redemptionRate;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0x5065a824ebb34952f016c6dfa47e8a7ac28427b719470e74a41022c11ace7788\",\"license\":\"MIT\"},\"contracts/structs/JBRedemptionDelegateAllocation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '../interfaces/IJBRedemptionDelegate.sol';\\n\\n/** \\n @member delegate A delegate contract to use for subsequent calls.\\n @member amount The amount to send to the delegate.\\n*/\\nstruct JBRedemptionDelegateAllocation {\\n IJBRedemptionDelegate delegate;\\n uint256 amount;\\n}\\n\",\"keccak256\":\"0x10c29d33dd0d875a0d4692a2b9a9355c2ebf433cc06a9a60253d4366b60d4d31\",\"license\":\"MIT\"},\"contracts/structs/JBSplit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBSplitAllocator.sol';\\n\\n/** \\n @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.\\n @member preferAddToBalance A flag indicating if a distribution to a project should prefer triggering it's addToBalance function instead of its pay function.\\n @member percent The percent of the whole group that this split occupies. This number is out of `JBConstants.SPLITS_TOTAL_PERCENT`.\\n @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.\\n @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.\\n @member lockedUntil Specifies if the split should be unchangeable until the specified time, with the exception of extending the locked period.\\n @member allocator If an allocator is specified, funds will be sent to the allocator contract along with all properties of this split.\\n*/\\nstruct JBSplit {\\n bool preferClaimed;\\n bool preferAddToBalance;\\n uint256 percent;\\n uint256 projectId;\\n address payable beneficiary;\\n uint256 lockedUntil;\\n IJBSplitAllocator allocator;\\n}\\n\",\"keccak256\":\"0xc80a16606da8abf76d0f73abc38aee041e24f29342c1939018f70c286e89f105\",\"license\":\"MIT\"},\"contracts/structs/JBSplitAllocationData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBSplit.sol';\\n\\n/** \\n @member token The token being sent to the split allocator.\\n @member amount The amount being sent to the split allocator, as a fixed point number.\\n @member decimals The number of decimals in the amount.\\n @member projectId The project to which the split belongs.\\n @member group The group to which the split belongs.\\n @member split The split that caused the allocation.\\n*/\\nstruct JBSplitAllocationData {\\n address token;\\n uint256 amount;\\n uint256 decimals;\\n uint256 projectId;\\n uint256 group;\\n JBSplit split;\\n}\\n\",\"keccak256\":\"0x39f5c41bd31d36774744698ac94484b6cab62d7038df2f29d947668959782e63\",\"license\":\"MIT\"},\"contracts/structs/JBTokenAmount.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/* \\n @member token The token the payment was made in.\\n @member value The amount of tokens that was paid, as a fixed point number.\\n @member decimals The number of decimals included in the value fixed point number.\\n @member currency The expected currency of the value.\\n**/\\nstruct JBTokenAmount {\\n address token;\\n uint256 value;\\n uint256 decimals;\\n uint256 currency;\\n}\\n\",\"keccak256\":\"0x4a778e779ba257ba5638c5469e07a4d21b55a3128d56db5a0fdfacb1f3301c51\",\"license\":\"MIT\"},\"prb-math/contracts/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivFixedPointOverflow(uint256 prod1);\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivOverflow(uint256 prod1, uint256 denominator);\\n\\n/// @notice Emitted when one of the inputs is type(int256).min.\\nerror PRBMath__MulDivSignedInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows int256.\\nerror PRBMath__MulDivSignedOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is MIN_SD59x18.\\nerror PRBMathSD59x18__AbsInputTooSmall();\\n\\n/// @notice Emitted when ceiling a number overflows SD59x18.\\nerror PRBMathSD59x18__CeilOverflow(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__DivInputTooSmall();\\n\\n/// @notice Emitted when one of the intermediary unsigned results overflows SD59x18.\\nerror PRBMathSD59x18__DivOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathSD59x18__ExpInputTooBig(int256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathSD59x18__Exp2InputTooBig(int256 x);\\n\\n/// @notice Emitted when flooring a number underflows SD59x18.\\nerror PRBMathSD59x18__FloorUnderflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format overflows SD59x18.\\nerror PRBMathSD59x18__FromIntOverflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format underflows SD59x18.\\nerror PRBMathSD59x18__FromIntUnderflow(int256 x);\\n\\n/// @notice Emitted when the product of the inputs is negative.\\nerror PRBMathSD59x18__GmNegativeProduct(int256 x, int256 y);\\n\\n/// @notice Emitted when multiplying the inputs overflows SD59x18.\\nerror PRBMathSD59x18__GmOverflow(int256 x, int256 y);\\n\\n/// @notice Emitted when the input is less than or equal to zero.\\nerror PRBMathSD59x18__LogInputTooSmall(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__MulInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__MulOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__PowuOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is negative.\\nerror PRBMathSD59x18__SqrtNegativeInput(int256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows SD59x18.\\nerror PRBMathSD59x18__SqrtOverflow(int256 x);\\n\\n/// @notice Emitted when addition overflows UD60x18.\\nerror PRBMathUD60x18__AddOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when ceiling a number overflows UD60x18.\\nerror PRBMathUD60x18__CeilOverflow(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathUD60x18__ExpInputTooBig(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathUD60x18__Exp2InputTooBig(uint256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format format overflows UD60x18.\\nerror PRBMathUD60x18__FromUintOverflow(uint256 x);\\n\\n/// @notice Emitted when multiplying the inputs overflows UD60x18.\\nerror PRBMathUD60x18__GmOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when the input is less than 1.\\nerror PRBMathUD60x18__LogInputTooSmall(uint256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows UD60x18.\\nerror PRBMathUD60x18__SqrtOverflow(uint256 x);\\n\\n/// @notice Emitted when subtraction underflows UD60x18.\\nerror PRBMathUD60x18__SubUnderflow(uint256 x, uint256 y);\\n\\n/// @dev Common mathematical functions used in both PRBMathSD59x18 and PRBMathUD60x18. Note that this shared library\\n/// does not always assume the signed 59.18-decimal fixed-point or the unsigned 60.18-decimal fixed-point\\n/// representation. When it does not, it is explicitly mentioned in the NatSpec documentation.\\nlibrary PRBMath {\\n /// STRUCTS ///\\n\\n struct SD59x18 {\\n int256 value;\\n }\\n\\n struct UD60x18 {\\n uint256 value;\\n }\\n\\n /// STORAGE ///\\n\\n /// @dev How many trailing decimals can be represented.\\n uint256 internal constant SCALE = 1e18;\\n\\n /// @dev Largest power of two divisor of SCALE.\\n uint256 internal constant SCALE_LPOTD = 262144;\\n\\n /// @dev SCALE inverted mod 2^256.\\n uint256 internal constant SCALE_INVERSE =\\n 78156646155174841979727994598816262306175212592076161876661_508869554232690281;\\n\\n /// FUNCTIONS ///\\n\\n /// @notice Calculates the binary exponent of x using the binary fraction method.\\n /// @dev Has to use 192.64-bit fixed-point numbers.\\n /// See https://ethereum.stackexchange.com/a/96594/24693.\\n /// @param x The exponent as an unsigned 192.64-bit fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp2(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n // Start from 0.5 in the 192.64-bit fixed-point format.\\n result = 0x800000000000000000000000000000000000000000000000;\\n\\n // Multiply the result by root(2, 2^-i) when the bit at position i is 1. None of the intermediary results overflows\\n // because the initial result is 2^191 and all magic factors are less than 2^65.\\n if (x & 0x8000000000000000 > 0) {\\n result = (result * 0x16A09E667F3BCC909) >> 64;\\n }\\n if (x & 0x4000000000000000 > 0) {\\n result = (result * 0x1306FE0A31B7152DF) >> 64;\\n }\\n if (x & 0x2000000000000000 > 0) {\\n result = (result * 0x1172B83C7D517ADCE) >> 64;\\n }\\n if (x & 0x1000000000000000 > 0) {\\n result = (result * 0x10B5586CF9890F62A) >> 64;\\n }\\n if (x & 0x800000000000000 > 0) {\\n result = (result * 0x1059B0D31585743AE) >> 64;\\n }\\n if (x & 0x400000000000000 > 0) {\\n result = (result * 0x102C9A3E778060EE7) >> 64;\\n }\\n if (x & 0x200000000000000 > 0) {\\n result = (result * 0x10163DA9FB33356D8) >> 64;\\n }\\n if (x & 0x100000000000000 > 0) {\\n result = (result * 0x100B1AFA5ABCBED61) >> 64;\\n }\\n if (x & 0x80000000000000 > 0) {\\n result = (result * 0x10058C86DA1C09EA2) >> 64;\\n }\\n if (x & 0x40000000000000 > 0) {\\n result = (result * 0x1002C605E2E8CEC50) >> 64;\\n }\\n if (x & 0x20000000000000 > 0) {\\n result = (result * 0x100162F3904051FA1) >> 64;\\n }\\n if (x & 0x10000000000000 > 0) {\\n result = (result * 0x1000B175EFFDC76BA) >> 64;\\n }\\n if (x & 0x8000000000000 > 0) {\\n result = (result * 0x100058BA01FB9F96D) >> 64;\\n }\\n if (x & 0x4000000000000 > 0) {\\n result = (result * 0x10002C5CC37DA9492) >> 64;\\n }\\n if (x & 0x2000000000000 > 0) {\\n result = (result * 0x1000162E525EE0547) >> 64;\\n }\\n if (x & 0x1000000000000 > 0) {\\n result = (result * 0x10000B17255775C04) >> 64;\\n }\\n if (x & 0x800000000000 > 0) {\\n result = (result * 0x1000058B91B5BC9AE) >> 64;\\n }\\n if (x & 0x400000000000 > 0) {\\n result = (result * 0x100002C5C89D5EC6D) >> 64;\\n }\\n if (x & 0x200000000000 > 0) {\\n result = (result * 0x10000162E43F4F831) >> 64;\\n }\\n if (x & 0x100000000000 > 0) {\\n result = (result * 0x100000B1721BCFC9A) >> 64;\\n }\\n if (x & 0x80000000000 > 0) {\\n result = (result * 0x10000058B90CF1E6E) >> 64;\\n }\\n if (x & 0x40000000000 > 0) {\\n result = (result * 0x1000002C5C863B73F) >> 64;\\n }\\n if (x & 0x20000000000 > 0) {\\n result = (result * 0x100000162E430E5A2) >> 64;\\n }\\n if (x & 0x10000000000 > 0) {\\n result = (result * 0x1000000B172183551) >> 64;\\n }\\n if (x & 0x8000000000 > 0) {\\n result = (result * 0x100000058B90C0B49) >> 64;\\n }\\n if (x & 0x4000000000 > 0) {\\n result = (result * 0x10000002C5C8601CC) >> 64;\\n }\\n if (x & 0x2000000000 > 0) {\\n result = (result * 0x1000000162E42FFF0) >> 64;\\n }\\n if (x & 0x1000000000 > 0) {\\n result = (result * 0x10000000B17217FBB) >> 64;\\n }\\n if (x & 0x800000000 > 0) {\\n result = (result * 0x1000000058B90BFCE) >> 64;\\n }\\n if (x & 0x400000000 > 0) {\\n result = (result * 0x100000002C5C85FE3) >> 64;\\n }\\n if (x & 0x200000000 > 0) {\\n result = (result * 0x10000000162E42FF1) >> 64;\\n }\\n if (x & 0x100000000 > 0) {\\n result = (result * 0x100000000B17217F8) >> 64;\\n }\\n if (x & 0x80000000 > 0) {\\n result = (result * 0x10000000058B90BFC) >> 64;\\n }\\n if (x & 0x40000000 > 0) {\\n result = (result * 0x1000000002C5C85FE) >> 64;\\n }\\n if (x & 0x20000000 > 0) {\\n result = (result * 0x100000000162E42FF) >> 64;\\n }\\n if (x & 0x10000000 > 0) {\\n result = (result * 0x1000000000B17217F) >> 64;\\n }\\n if (x & 0x8000000 > 0) {\\n result = (result * 0x100000000058B90C0) >> 64;\\n }\\n if (x & 0x4000000 > 0) {\\n result = (result * 0x10000000002C5C860) >> 64;\\n }\\n if (x & 0x2000000 > 0) {\\n result = (result * 0x1000000000162E430) >> 64;\\n }\\n if (x & 0x1000000 > 0) {\\n result = (result * 0x10000000000B17218) >> 64;\\n }\\n if (x & 0x800000 > 0) {\\n result = (result * 0x1000000000058B90C) >> 64;\\n }\\n if (x & 0x400000 > 0) {\\n result = (result * 0x100000000002C5C86) >> 64;\\n }\\n if (x & 0x200000 > 0) {\\n result = (result * 0x10000000000162E43) >> 64;\\n }\\n if (x & 0x100000 > 0) {\\n result = (result * 0x100000000000B1721) >> 64;\\n }\\n if (x & 0x80000 > 0) {\\n result = (result * 0x10000000000058B91) >> 64;\\n }\\n if (x & 0x40000 > 0) {\\n result = (result * 0x1000000000002C5C8) >> 64;\\n }\\n if (x & 0x20000 > 0) {\\n result = (result * 0x100000000000162E4) >> 64;\\n }\\n if (x & 0x10000 > 0) {\\n result = (result * 0x1000000000000B172) >> 64;\\n }\\n if (x & 0x8000 > 0) {\\n result = (result * 0x100000000000058B9) >> 64;\\n }\\n if (x & 0x4000 > 0) {\\n result = (result * 0x10000000000002C5D) >> 64;\\n }\\n if (x & 0x2000 > 0) {\\n result = (result * 0x1000000000000162E) >> 64;\\n }\\n if (x & 0x1000 > 0) {\\n result = (result * 0x10000000000000B17) >> 64;\\n }\\n if (x & 0x800 > 0) {\\n result = (result * 0x1000000000000058C) >> 64;\\n }\\n if (x & 0x400 > 0) {\\n result = (result * 0x100000000000002C6) >> 64;\\n }\\n if (x & 0x200 > 0) {\\n result = (result * 0x10000000000000163) >> 64;\\n }\\n if (x & 0x100 > 0) {\\n result = (result * 0x100000000000000B1) >> 64;\\n }\\n if (x & 0x80 > 0) {\\n result = (result * 0x10000000000000059) >> 64;\\n }\\n if (x & 0x40 > 0) {\\n result = (result * 0x1000000000000002C) >> 64;\\n }\\n if (x & 0x20 > 0) {\\n result = (result * 0x10000000000000016) >> 64;\\n }\\n if (x & 0x10 > 0) {\\n result = (result * 0x1000000000000000B) >> 64;\\n }\\n if (x & 0x8 > 0) {\\n result = (result * 0x10000000000000006) >> 64;\\n }\\n if (x & 0x4 > 0) {\\n result = (result * 0x10000000000000003) >> 64;\\n }\\n if (x & 0x2 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n if (x & 0x1 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n\\n // We're doing two things at the same time:\\n //\\n // 1. Multiply the result by 2^n + 1, where \\\"2^n\\\" is the integer part and the one is added to account for\\n // the fact that we initially set the result to 0.5. This is accomplished by subtracting from 191\\n // rather than 192.\\n // 2. Convert the result to the unsigned 60.18-decimal fixed-point format.\\n //\\n // This works because 2^(191-ip) = 2^ip / 2^191, where \\\"ip\\\" is the integer part \\\"2^n\\\".\\n result *= SCALE;\\n result >>= (191 - (x >> 64));\\n }\\n }\\n\\n /// @notice Finds the zero-based index of the first one in the binary representation of x.\\n /// @dev See the note on msb in the \\\"Find First Set\\\" Wikipedia article https://en.wikipedia.org/wiki/Find_first_set\\n /// @param x The uint256 number for which to find the index of the most significant bit.\\n /// @return msb The index of the most significant bit as an uint256.\\n function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\\n if (x >= 2**128) {\\n x >>= 128;\\n msb += 128;\\n }\\n if (x >= 2**64) {\\n x >>= 64;\\n msb += 64;\\n }\\n if (x >= 2**32) {\\n x >>= 32;\\n msb += 32;\\n }\\n if (x >= 2**16) {\\n x >>= 16;\\n msb += 16;\\n }\\n if (x >= 2**8) {\\n x >>= 8;\\n msb += 8;\\n }\\n if (x >= 2**4) {\\n x >>= 4;\\n msb += 4;\\n }\\n if (x >= 2**2) {\\n x >>= 2;\\n msb += 2;\\n }\\n if (x >= 2**1) {\\n // No need to shift x any more.\\n msb += 1;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.\\n ///\\n /// Requirements:\\n /// - The denominator cannot be zero.\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The multiplicand as an uint256.\\n /// @param y The multiplier as an uint256.\\n /// @param denominator The divisor as an uint256.\\n /// @return result The result as an uint256.\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n unchecked {\\n result = prod0 / denominator;\\n }\\n return result;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n if (prod1 >= denominator) {\\n revert PRBMath__MulDivOverflow(prod1, denominator);\\n }\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n unchecked {\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 lpotdod = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by lpotdod.\\n denominator := div(denominator, lpotdod)\\n\\n // Divide [prod1 prod0] by lpotdod.\\n prod0 := div(prod0, lpotdod)\\n\\n // Flip lpotdod such that it is 2^256 / lpotdod. If lpotdod is zero, then it becomes one.\\n lpotdod := add(div(sub(0, lpotdod), lpotdod), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * lpotdod;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f71e18) with full precision.\\n ///\\n /// @dev Variant of \\\"mulDiv\\\" with constant folding, i.e. in which the denominator is always 1e18. Before returning the\\n /// final result, we add 1 if (x * y) % SCALE >= HALF_SCALE. Without this, 6.6e-19 would be truncated to 0 instead of\\n /// being rounded to 1e-18. See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717.\\n ///\\n /// Requirements:\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - The body is purposely left uncommented; see the NatSpec comments in \\\"PRBMath.mulDiv\\\" to understand how this works.\\n /// - It is assumed that the result can never be type(uint256).max when x and y solve the following two equations:\\n /// 1. x * y = type(uint256).max * SCALE\\n /// 2. (x * y) % SCALE >= SCALE / 2\\n ///\\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function mulDivFixedPoint(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n uint256 prod0;\\n uint256 prod1;\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n if (prod1 >= SCALE) {\\n revert PRBMath__MulDivFixedPointOverflow(prod1);\\n }\\n\\n uint256 remainder;\\n uint256 roundUpUnit;\\n assembly {\\n remainder := mulmod(x, y, SCALE)\\n roundUpUnit := gt(remainder, 499999999999999999)\\n }\\n\\n if (prod1 == 0) {\\n unchecked {\\n result = (prod0 / SCALE) + roundUpUnit;\\n return result;\\n }\\n }\\n\\n assembly {\\n result := add(\\n mul(\\n or(\\n div(sub(prod0, remainder), SCALE_LPOTD),\\n mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, SCALE_LPOTD), SCALE_LPOTD), 1))\\n ),\\n SCALE_INVERSE\\n ),\\n roundUpUnit\\n )\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev An extension of \\\"mulDiv\\\" for signed numbers. Works by computing the signs and the absolute values separately.\\n ///\\n /// Requirements:\\n /// - None of the inputs can be type(int256).min.\\n /// - The result must fit within int256.\\n ///\\n /// @param x The multiplicand as an int256.\\n /// @param y The multiplier as an int256.\\n /// @param denominator The divisor as an int256.\\n /// @return result The result as an int256.\\n function mulDivSigned(\\n int256 x,\\n int256 y,\\n int256 denominator\\n ) internal pure returns (int256 result) {\\n if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {\\n revert PRBMath__MulDivSignedInputTooSmall();\\n }\\n\\n // Get hold of the absolute values of x, y and the denominator.\\n uint256 ax;\\n uint256 ay;\\n uint256 ad;\\n unchecked {\\n ax = x < 0 ? uint256(-x) : uint256(x);\\n ay = y < 0 ? uint256(-y) : uint256(y);\\n ad = denominator < 0 ? uint256(-denominator) : uint256(denominator);\\n }\\n\\n // Compute the absolute value of (x*y)\\u00f7denominator. The result must fit within int256.\\n uint256 rAbs = mulDiv(ax, ay, ad);\\n if (rAbs > uint256(type(int256).max)) {\\n revert PRBMath__MulDivSignedOverflow(rAbs);\\n }\\n\\n // Get the signs of x, y and the denominator.\\n uint256 sx;\\n uint256 sy;\\n uint256 sd;\\n assembly {\\n sx := sgt(x, sub(0, 1))\\n sy := sgt(y, sub(0, 1))\\n sd := sgt(denominator, sub(0, 1))\\n }\\n\\n // XOR over sx, sy and sd. This is checking whether there are one or three negative signs in the inputs.\\n // If yes, the result should be negative.\\n result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs);\\n }\\n\\n /// @notice Calculates the square root of x, rounding down.\\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The uint256 number for which to calculate the square root.\\n /// @return result The result as an uint256.\\n function sqrt(uint256 x) internal pure returns (uint256 result) {\\n if (x == 0) {\\n return 0;\\n }\\n\\n // Set the initial guess to the closest power of two that is higher than x.\\n uint256 xAux = uint256(x);\\n result = 1;\\n if (xAux >= 0x100000000000000000000000000000000) {\\n xAux >>= 128;\\n result <<= 64;\\n }\\n if (xAux >= 0x10000000000000000) {\\n xAux >>= 64;\\n result <<= 32;\\n }\\n if (xAux >= 0x100000000) {\\n xAux >>= 32;\\n result <<= 16;\\n }\\n if (xAux >= 0x10000) {\\n xAux >>= 16;\\n result <<= 8;\\n }\\n if (xAux >= 0x100) {\\n xAux >>= 8;\\n result <<= 4;\\n }\\n if (xAux >= 0x10) {\\n xAux >>= 4;\\n result <<= 2;\\n }\\n if (xAux >= 0x8) {\\n result <<= 1;\\n }\\n\\n // The operations can never overflow because the result is max 2^127 when it enters this block.\\n unchecked {\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1; // Seven iterations should be enough\\n uint256 roundedDownResult = x / result;\\n return result >= roundedDownResult ? roundedDownResult : result;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x62cbabae4910e168e99b9c2c3e3b5c9c7ad5e7abd961dcc63b7ea3d83d8ea87e\",\"license\":\"Unlicense\"}},\"version\":1}", "bytecode": "0x60e06040523480156200001157600080fd5b5060405162003c2338038062003c23833981016040819052620000349162000070565b60016000556001600160a01b0392831660805290821660a0521660c052620000c4565b6001600160a01b03811681146200006d57600080fd5b50565b6000806000606084860312156200008657600080fd5b8351620000938162000057565b6020850151909350620000a68162000057565b6040850151909250620000b98162000057565b809150509250925092565b60805160a05160c051613aa36200018060003960008181610263015281816107f201528181610e6c01528181612767015261297601526000818161018b0152818161040e01528181610a2b01528181610fb90152818161119b015281816115d8015281816118d4015281816119b601528181611dbb0152818161225b0152612a16015260008181610229015281816104be015281816113f401528181611bb101528181611ead015281816124ee01526127fc0152613aa36000f3fe608060405234801561001057600080fd5b50600436106100ff5760003560e01c8063c294b2f411610097578063d49031c011610066578063d49031c014610285578063d4c3a8d214610298578063e7c8e3e3146102c9578063e8ba563a146102de57600080fd5b8063c294b2f414610211578063c41c2f2414610224578063c66445971461024b578063d3419bf31461025e57600080fd5b80636bb6a5ad116100d35780636bb6a5ad146101c5578063a2df1f95146101d8578063a57c7f59146101eb578063b753d7e9146101fe57600080fd5b8062fdd58e1461010457806325386715146101425780632fa1b39114610163578063557e715514610186575b600080fd5b61012f610112366004612bd4565b600160209081526000928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b610155610150366004612c00565b61030f565b604051610139929190612c2c565b610176610171366004612e23565b61092e565b6040516101399493929190612f34565b6101ad7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610139565b61012f6101d3366004613011565b610f15565b6101766101e636600461302a565b61109e565b61012f6101f93660046130cb565b611880565b61012f61020c366004612c00565b611963565b61012f61021f3660046130fd565b61197a565b6101ad7f000000000000000000000000000000000000000000000000000000000000000081565b610155610259366004612c00565b611cc1565b6101ad7f000000000000000000000000000000000000000000000000000000000000000081565b61012f610293366004612bd4565b612252565b61012f6102a636600461314c565b600360209081526000938452604080852082529284528284209052825290205481565b6102dc6102d7366004613181565b612330565b005b61012f6102ec36600461314c565b600260209081526000938452604080852082529284528284209052825290205481565b6103676040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b60006002600054036103da576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b60026000556040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018690527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa15801561045e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061048291906131b3565b3360009081526003602090815260408083208984528252808320828501518452909152812054919350906104b7908690613262565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635dd8f6aa896040518263ffffffff1660e01b815260040161050a91815260200190565b602060405180830381865afa158015610527573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061054b9190613275565b6001600160a01b031663a29a68146040518163ffffffff1660e01b8152600401602060405180830381865afa158015610588573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ac9190613275565b6001600160a01b0316637a81b56289876020015133336001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105ff573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106239190613275565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e087901b168152600481019490945260248401929092526001600160a01b0390811660448401521660648201526084016040805180830381865afa158015610694573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106b89190613292565b91509150818311806106c8575081155b156106ff576040517fb6ecab1200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b808614610738576040517fe56ea4e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000336001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610778573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061079c91906132b6565b90508087146108705761086b886107b56012600a6133ef565b6040517fa4d0caf2000000000000000000000000000000000000000000000000000000008152600481018b905260248101859052601260448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a4d0caf2906064015b602060405180830381865afa158015610842573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061086691906132b6565b612379565b610872565b875b9450610880338a888461247d565b8511156108b9576040517f2fca7ece00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360008181526003602090815260408083208d845282528083208a83015184528252808320889055928252600181528282208c8352905220546108fd9086906133fb565b3360009081526001602081815260408084209d84529c90529a81209190915598909855509296919550909350505050565b6109866040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b60006060806002600054036109f7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103d1565b60026000556040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018b90527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa158015610a7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a9f91906131b3565b8051909450600003610add576040517f2e96671a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61010084015160481c600190811603610b22576040517fa3bb913300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61010084015160009060521c6001908116148015610b5857506000610b4c86610100015160541c90565b6001600160a01b031614155b15610caa576000604051806101400160405280336001600160a01b031681526020018f6001600160a01b031681526020018e803603810190610b9a919061340e565b815260208082018f905288015160408201526001600160a01b038c16606082015260a080890151608083015261010089015191019060181c61ffff1681526020018a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050908252506020018890529050610c2b86610100015160541c90565b6001600160a01b031663d46cf171826040518263ffffffff1660e01b8152600401610c56919061347d565b6000604051808303816000875af1158015610c75573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610c9d91908101906135eb565b955093509150610ceb9050565b8460a00151905087878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294505050505b825160208d01359015610d805760005b8451811015610d7e576000858281518110610d1857610d186136dc565b602002602001015160200151905080600014610d755782811115610d68576040517f6d51b52600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d7281846133fb565b92505b50600101610cfb565b505b8c60200135600003610d98575060009350610efe9050565b8015610dff573360009081526001602090815260408083208f8452909152902054610dc4908290613262565b60016000336001600160a01b03166001600160a01b0316815260200190815260200160002060008e8152602001908152602001600020819055505b5080600003610e12575060009250610efe565b60408c0135600060608e01358c14610edc576040517fa4d0caf200000000000000000000000000000000000000000000000000000000815260608f01356004820152602481018d9052604481018390526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a4d0caf290606401602060405180830381865afa158015610eb3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ed791906132b6565b610ee7565b610ee782600a6133ef565b9050610ef88e602001358483612379565b95505050505b600160008190555098509850985098945050505050565b6000600260005403610f83576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103d1565b600260009081556040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa158015611009573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061102d91906131b3565b610100810151909150604d1c600190811614611075576040517fe7c9e0be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505033600090815260016020818152604080842094845293905291812080549082905591905590565b6110f66040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b6000606080600260005403611167576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103d1565b60026000556040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa1580156111eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061120f91906131b3565b610100810151909450604a1c600190811603611257576040517fa97cf58f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61128b604051806080016040528060006001600160a01b031681526020016000815260200160008152602001600081525090565b6000806000336001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f29190613275565b90506000336001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611334573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061135891906132b6565b90506000336001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561139a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113be91906132b6565b6101008b015190915060511c6001908116146113e5576113e0338f8c8461247d565b6113f0565b6113f08e83836127c0565b94507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635dd8f6aa8f6040518263ffffffff1660e01b815260040161144091815260200190565b602060405180830381865afa15801561145d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114819190613275565b6001600160a01b031663c18f2d318f6040518263ffffffff1660e01b81526004016114ae91815260200190565b602060405180830381865afa1580156114cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ef91906132b6565b9350838d111561152b576040517fb8af220000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84156115415761153e8e8b8f87896129d4565b98505b604080516080810182526001600160a01b03949094168452602084018a9052830191909152606082015261010088015190935060531c60019081161480156115a15750600061159588610100015160541c90565b6001600160a01b031614155b15611791576040517fc55f571c000000000000000000000000000000000000000000000000000000008152600481018c90526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c55f571c90602401602060405180830381865afa158015611627573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061164b919061370b565b90506000604051806101800160405280336001600160a01b031681526020018f6001600160a01b031681526020018e81526020018a6020015181526020018d81526020018481526020018581526020018681526020016116b88b6101000151600160519190911c81161490565b1515815260200160008460028111156116d3576116d361372c565b146116e6576116e18b612b25565b6116ef565b6116ef8b612b42565b81526020018c81526020018b815250905061170f89610100015160541c90565b6001600160a01b031663a51cfd18826040518263ffffffff1660e01b815260040161173a919061375b565b6000604051808303816000875af1158015611759573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526117819190810190613856565b9199509097509550611795915050565b8893505b50508251849150156117ef5760005b83518110156117ed5760008482815181106117c1576117c16136dc565b6020026020010151602001519050806000146117e4576117e18184613262565b92505b506001016117a4565b505b3360009081526001602090815260408083208c8452909152902054811115611843576040517f2fca7ece00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b801561186b573360009081526001602090815260408083208c84529091529020805482900390555b50600160008190555095509550955095915050565b6000816000036118925750600061195b565b828411156118a25750600061195b565b6040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018690526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa158015611924573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061194891906131b3565b905061195786828787876129d4565b9150505b949350505050565b60006119708484846127c0565b90505b9392505050565b6040517f43a266c20000000000000000000000000000000000000000000000000000000081526004810184905260009081906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906343a266c29060240161012060405180830381865afa1580156119fe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a2291906131b3565b9050600083611a9d57611a988787848a6001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a9391906132b6565b61247d565b611b6a565b611b6a86886001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611adf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b0391906132b6565b896001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b41573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b6591906132b6565b6127c0565b905080600003611b7f5760009250505061195b565b6040517f5dd8f6aa000000000000000000000000000000000000000000000000000000008152600481018790526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635dd8f6aa90602401602060405180830381865afa158015611c00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c249190613275565b6001600160a01b031663c18f2d31886040518263ffffffff1660e01b8152600401611c5191815260200190565b602060405180830381865afa158015611c6e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c9291906132b6565b905080861115611ca8576000935050505061195b565b611cb587848884866129d4565b98975050505050505050565b611d196040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b6000600260005403611d87576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103d1565b60026000556040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018690527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa158015611e0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e2f91906131b3565b61010081015190925060491c600190811603611e77576040517f861e9dcd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152600260209081526040808320888452825280832085518452909152812054611ea6908690613262565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635dd8f6aa896040518263ffffffff1660e01b8152600401611ef991815260200190565b602060405180830381865afa158015611f16573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f3a9190613275565b6001600160a01b031663a29a68146040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f9b9190613275565b6001600160a01b031663e8db213089876020015133336001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611fee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120129190613275565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e087901b168152600481019490945260248401929092526001600160a01b0390811660448401521660648201526084016040805180830381865afa158015612083573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120a79190613292565b91509150818311806120b7575081155b156120ee576040517f08dae4ac00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b808614612127576040517fe56ea4e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000336001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b91906132b6565b90508087146121a9576121a4886107b56012600a6133ef565b6121ab565b875b3360009081526001602090815260408083208d8452909152902054909550851115612202576040517f2fca7ece00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50503360008181526002602090815260408083208b845282528083208851845282528083209590955591815260018083528482209982529890915291822080548490039055509490945593915050565b600061232783837f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166343a266c2866040518263ffffffff1660e01b81526004016122a791815260200190565b61012060405180830381865afa1580156122c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122e991906131b3565b866001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a6f573d6000803e3d6000fd5b90505b92915050565b336000908152600160209081526040808320858452909152902054612356908290613262565b336000908152600160209081526040808320958352949052929092209190915550565b600080807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff858709858702925082811083820303915050806000036123d1578382816123c7576123c7613937565b0492505050611973565b838110612414576040517f773cc18c00000000000000000000000000000000000000000000000000000000815260048101829052602481018590526044016103d1565b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b6001600160a01b03841660009081526001602090815260408083208684529091528120548082036124b257600091505061195b565b6040517f5dd8f6aa0000000000000000000000000000000000000000000000000000000081526004810186905260009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690635dd8f6aa90602401602060405180830381865afa158015612535573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125599190613275565b6001600160a01b031663a29a68146040518163ffffffff1660e01b8152600401602060405180830381865afa158015612596573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125ba9190613275565b6001600160a01b031663e8db21308888602001518b8c6001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561260d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126319190613275565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e087901b168152600481019490945260248401929092526001600160a01b0390811660448401521660648201526084016040805180830381865afa1580156126a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126c69190613292565b6001600160a01b038a1660009081526002602090815260408083208c845282528083208b5184529091528120549294509092509061270490846133fb565b905080158015906127155750858214155b156127a15761279e8161272a6012600a6133ef565b6040517fa4d0caf200000000000000000000000000000000000000000000000000000000815260048101869052602481018a9052601260448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a4d0caf290606401610825565b90505b8084116127af5760006127b3565b8084035b9998505050505050505050565b6040517fd17541530000000000000000000000000000000000000000000000000000000081526004810184905260009081906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063d175415390602401600060405180830381865afa158015612843573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261286b9190810190613966565b90506000805b82518110156129165782818151811061288c5761288c6136dc565b60200260200101516001600160a01b031663a32e1e96886040518263ffffffff1660e01b81526004016128c191815260200190565b602060405180830381865afa1580156128de573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061290291906132b6565b61290c9083613262565b9150600101612871565b506000600185146129aa576040517fa4d0caf20000000000000000000000000000000000000000000000000000000081526001600482015260248101869052601260448201526129a5908390670de0b6b3a7640000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a4d0caf290606401610825565b6129ac565b815b9050856012146129c7576129c281601288612b5f565b6129c9565b805b979650505050505050565b60008284036129e4575080612b1c565b6000806040517fc55f571c000000000000000000000000000000000000000000000000000000008152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c55f571c90602401602060405180830381865afa158015612a65573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a89919061370b565b6002811115612a9a57612a9a61372c565b14612aad57612aa886612b25565b612ab6565b612ab686612b42565b905080600003612aca576000915050612b1c565b6000612ad7848787612379565b90506127108203612aeb579150612b1c9050565b612b1781612b0588612aff866127106133fb565b89612379565b612b0f9085613262565b612710612379565b925050505b95945050505050565b60006028826101000151901c61ffff1661271061232a91906133fb565b60006038826101000151901c61ffff1661271061232a91906133fb565b6000828203612b6f575082611973565b82821115612b9d57612b8183836133fb565b612b8c90600a6133ef565b612b9690856139f5565b9050611973565b612ba782846133fb565b612bb290600a6133ef565b612b969085613a32565b6001600160a01b0381168114612bd157600080fd5b50565b60008060408385031215612be757600080fd5b8235612bf281612bbc565b946020939093013593505050565b600080600060608486031215612c1557600080fd5b505081359360208301359350604090920135919050565b6101408101612c998285805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c08301526001600160a01b0360e08201511660e08301526101008082015181840152505050565b826101208301529392505050565b60008083601f840112612cb957600080fd5b50813567ffffffffffffffff811115612cd157600080fd5b602083019150836020828501011115612ce957600080fd5b9250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff81118282101715612d4357612d43612cf0565b60405290565b6040805190810167ffffffffffffffff81118282101715612d4357612d43612cf0565b604051601f8201601f1916810167ffffffffffffffff81118282101715612d9557612d95612cf0565b604052919050565b600067ffffffffffffffff821115612db757612db7612cf0565b50601f01601f191660200190565b6000612dd8612dd384612d9d565b612d6c565b9050828152838383011115612dec57600080fd5b828260208301376000602084830101529392505050565b600082601f830112612e1457600080fd5b61232783833560208501612dc5565b600080600080600080600080888a03610140811215612e4157600080fd5b8935612e4c81612bbc565b98506080601f1982011215612e6057600080fd5b5060208901965060a0890135955060c0890135945060e0890135612e8381612bbc565b935061010089013567ffffffffffffffff80821115612ea157600080fd5b612ead8c838d01612ca7565b90955093506101208b0135915080821115612ec757600080fd5b50612ed48b828c01612e03565b9150509295985092959890939650565b60005b83811015612eff578181015183820152602001612ee7565b50506000910152565b60008151808452612f20816020860160208601612ee4565b601f01601f19169290920160200192915050565b6000610180808301612fa48489805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c08301526001600160a01b0360e08201511660e08301526101008082015181840152505050565b61012084018790526101408401919091528451908190526101a083019060209081870160005b82811015612ffa57815180516001600160a01b031686528401518486015260409094019390830190600101612fca565b505050508281036101608401526129c98185612f08565b60006020828403121561302357600080fd5b5035919050565b600080600080600060a0868803121561304257600080fd5b853561304d81612bbc565b94506020860135935060408601359250606086013567ffffffffffffffff8082111561307857600080fd5b818801915088601f83011261308c57600080fd5b61309b89833560208501612dc5565b935060808801359150808211156130b157600080fd5b506130be88828901612e03565b9150509295509295909350565b600080600080608085870312156130e157600080fd5b5050823594602084013594506040840135936060013592509050565b6000806000806080858703121561311357600080fd5b843561311e81612bbc565b935060208501359250604085013591506060850135801515811461314157600080fd5b939692955090935050565b60008060006060848603121561316157600080fd5b833561316c81612bbc565b95602085013595506040909401359392505050565b6000806040838503121561319457600080fd5b50508035926020909101359150565b80516131ae81612bbc565b919050565b600061012082840312156131c657600080fd5b6131ce612d1f565b825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015261321a60e084016131a3565b60e0820152610100928301519281019290925250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561232a5761232a613233565b60006020828403121561328757600080fd5b815161197381612bbc565b600080604083850312156132a557600080fd5b505080516020909101519092909150565b6000602082840312156132c857600080fd5b5051919050565b600181815b8085111561332857817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561330e5761330e613233565b8085161561331b57918102915b93841c93908002906132d4565b509250929050565b60008261333f5750600161232a565b8161334c5750600061232a565b8160018114613362576002811461336c57613388565b600191505061232a565b60ff84111561337d5761337d613233565b50506001821b61232a565b5060208310610133831016604e8410600b84101617156133ab575081810a61232a565b6133b583836132cf565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156133e7576133e7613233565b029392505050565b60006123278383613330565b8181038181111561232a5761232a613233565b60006080828403121561342057600080fd5b6040516080810181811067ffffffffffffffff8211171561344357613443612cf0565b604052823561345181612bbc565b808252506020830135602082015260408301356040820152606083013560608201528091505092915050565b602081526134976020820183516001600160a01b03169052565b600060208301516134b360408401826001600160a01b03169052565b5060408301516134f060608401826001600160a01b0381511682526020810151602083015260408101516040830152606081015160608301525050565b50606083015160e08301526080830151610100818185015260a08501519150610120613526818601846001600160a01b03169052565b60c086015161014086015260e08601516101608601528186015192506101a091508161018086015261355c6101c0860184612f08565b90860151858203601f1901838701529092506135788382612f08565b9695505050505050565b600082601f83011261359357600080fd5b81516135a1612dd382612d9d565b8181528460208386010111156135b657600080fd5b61195b826020830160208701612ee4565b600067ffffffffffffffff8211156135e1576135e1612cf0565b5060051b60200190565b60008060006060848603121561360057600080fd5b8351925060208085015167ffffffffffffffff8082111561362057600080fd5b61362c88838901613582565b945060409150818701518181111561364357600080fd5b87019050601f8101881361365657600080fd5b8051613664612dd3826135c7565b81815260069190911b8201840190848101908a83111561368357600080fd5b928501925b828410156136cc5784848c0312156136a05760008081fd5b6136a8612d49565b84516136b381612bbc565b8152848701518782015282529284019290850190613688565b8096505050505050509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561371d57600080fd5b81516003811061197357600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b602081526137756020820183516001600160a01b03169052565b6000602083015161379160408401826001600160a01b03169052565b506040830151606083015260608301516080830152608083015160a083015260a083015160c083015260c083015160e083015260e0830151610100613802818501836001600160a01b0381511682526020810151602083015260408101516040830152606081015160608301525050565b8401511515610180840152506101208301516101a08301526101408301516101e06101c08401819052613839610200850183612f08565b9150610160850151601f1985840301828601526135788382612f08565b60008060006060848603121561386b57600080fd5b8351925060208085015167ffffffffffffffff8082111561388b57600080fd5b61389788838901613582565b94506040915081870151818111156138ae57600080fd5b87019050601f810188136138c157600080fd5b80516138cf612dd3826135c7565b81815260069190911b8201840190848101908a8311156138ee57600080fd5b928501925b828410156136cc5784848c03121561390b5760008081fd5b613913612d49565b845161391e81612bbc565b81528487015187820152825292840192908501906138f3565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000602080838503121561397957600080fd5b825167ffffffffffffffff81111561399057600080fd5b8301601f810185136139a157600080fd5b80516139af612dd3826135c7565b81815260059190911b820183019083810190878311156139ce57600080fd5b928401925b828410156129c95783516139e681612bbc565b825292840192908401906139d3565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a2d57613a2d613233565b500290565b600082613a68577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b50049056fea2646970667358221220472cf79391445f8d8a779847ccca68da89347336bdf6d8d6fa3a32f972aa4a6264736f6c63430008100033", "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100ff5760003560e01c8063c294b2f411610097578063d49031c011610066578063d49031c014610285578063d4c3a8d214610298578063e7c8e3e3146102c9578063e8ba563a146102de57600080fd5b8063c294b2f414610211578063c41c2f2414610224578063c66445971461024b578063d3419bf31461025e57600080fd5b80636bb6a5ad116100d35780636bb6a5ad146101c5578063a2df1f95146101d8578063a57c7f59146101eb578063b753d7e9146101fe57600080fd5b8062fdd58e1461010457806325386715146101425780632fa1b39114610163578063557e715514610186575b600080fd5b61012f610112366004612bd4565b600160209081526000928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b610155610150366004612c00565b61030f565b604051610139929190612c2c565b610176610171366004612e23565b61092e565b6040516101399493929190612f34565b6101ad7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610139565b61012f6101d3366004613011565b610f15565b6101766101e636600461302a565b61109e565b61012f6101f93660046130cb565b611880565b61012f61020c366004612c00565b611963565b61012f61021f3660046130fd565b61197a565b6101ad7f000000000000000000000000000000000000000000000000000000000000000081565b610155610259366004612c00565b611cc1565b6101ad7f000000000000000000000000000000000000000000000000000000000000000081565b61012f610293366004612bd4565b612252565b61012f6102a636600461314c565b600360209081526000938452604080852082529284528284209052825290205481565b6102dc6102d7366004613181565b612330565b005b61012f6102ec36600461314c565b600260209081526000938452604080852082529284528284209052825290205481565b6103676040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b60006002600054036103da576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b60026000556040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018690527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa15801561045e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061048291906131b3565b3360009081526003602090815260408083208984528252808320828501518452909152812054919350906104b7908690613262565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635dd8f6aa896040518263ffffffff1660e01b815260040161050a91815260200190565b602060405180830381865afa158015610527573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061054b9190613275565b6001600160a01b031663a29a68146040518163ffffffff1660e01b8152600401602060405180830381865afa158015610588573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ac9190613275565b6001600160a01b0316637a81b56289876020015133336001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105ff573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106239190613275565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e087901b168152600481019490945260248401929092526001600160a01b0390811660448401521660648201526084016040805180830381865afa158015610694573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106b89190613292565b91509150818311806106c8575081155b156106ff576040517fb6ecab1200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b808614610738576040517fe56ea4e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000336001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610778573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061079c91906132b6565b90508087146108705761086b886107b56012600a6133ef565b6040517fa4d0caf2000000000000000000000000000000000000000000000000000000008152600481018b905260248101859052601260448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a4d0caf2906064015b602060405180830381865afa158015610842573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061086691906132b6565b612379565b610872565b875b9450610880338a888461247d565b8511156108b9576040517f2fca7ece00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360008181526003602090815260408083208d845282528083208a83015184528252808320889055928252600181528282208c8352905220546108fd9086906133fb565b3360009081526001602081815260408084209d84529c90529a81209190915598909855509296919550909350505050565b6109866040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b60006060806002600054036109f7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103d1565b60026000556040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018b90527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa158015610a7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a9f91906131b3565b8051909450600003610add576040517f2e96671a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61010084015160481c600190811603610b22576040517fa3bb913300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61010084015160009060521c6001908116148015610b5857506000610b4c86610100015160541c90565b6001600160a01b031614155b15610caa576000604051806101400160405280336001600160a01b031681526020018f6001600160a01b031681526020018e803603810190610b9a919061340e565b815260208082018f905288015160408201526001600160a01b038c16606082015260a080890151608083015261010089015191019060181c61ffff1681526020018a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050908252506020018890529050610c2b86610100015160541c90565b6001600160a01b031663d46cf171826040518263ffffffff1660e01b8152600401610c56919061347d565b6000604051808303816000875af1158015610c75573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610c9d91908101906135eb565b955093509150610ceb9050565b8460a00151905087878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294505050505b825160208d01359015610d805760005b8451811015610d7e576000858281518110610d1857610d186136dc565b602002602001015160200151905080600014610d755782811115610d68576040517f6d51b52600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d7281846133fb565b92505b50600101610cfb565b505b8c60200135600003610d98575060009350610efe9050565b8015610dff573360009081526001602090815260408083208f8452909152902054610dc4908290613262565b60016000336001600160a01b03166001600160a01b0316815260200190815260200160002060008e8152602001908152602001600020819055505b5080600003610e12575060009250610efe565b60408c0135600060608e01358c14610edc576040517fa4d0caf200000000000000000000000000000000000000000000000000000000815260608f01356004820152602481018d9052604481018390526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a4d0caf290606401602060405180830381865afa158015610eb3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ed791906132b6565b610ee7565b610ee782600a6133ef565b9050610ef88e602001358483612379565b95505050505b600160008190555098509850985098945050505050565b6000600260005403610f83576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103d1565b600260009081556040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa158015611009573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061102d91906131b3565b610100810151909150604d1c600190811614611075576040517fe7c9e0be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505033600090815260016020818152604080842094845293905291812080549082905591905590565b6110f66040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b6000606080600260005403611167576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103d1565b60026000556040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa1580156111eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061120f91906131b3565b610100810151909450604a1c600190811603611257576040517fa97cf58f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61128b604051806080016040528060006001600160a01b031681526020016000815260200160008152602001600081525090565b6000806000336001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112ce573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f29190613275565b90506000336001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611334573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061135891906132b6565b90506000336001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561139a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113be91906132b6565b6101008b015190915060511c6001908116146113e5576113e0338f8c8461247d565b6113f0565b6113f08e83836127c0565b94507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635dd8f6aa8f6040518263ffffffff1660e01b815260040161144091815260200190565b602060405180830381865afa15801561145d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114819190613275565b6001600160a01b031663c18f2d318f6040518263ffffffff1660e01b81526004016114ae91815260200190565b602060405180830381865afa1580156114cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ef91906132b6565b9350838d111561152b576040517fb8af220000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84156115415761153e8e8b8f87896129d4565b98505b604080516080810182526001600160a01b03949094168452602084018a9052830191909152606082015261010088015190935060531c60019081161480156115a15750600061159588610100015160541c90565b6001600160a01b031614155b15611791576040517fc55f571c000000000000000000000000000000000000000000000000000000008152600481018c90526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c55f571c90602401602060405180830381865afa158015611627573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061164b919061370b565b90506000604051806101800160405280336001600160a01b031681526020018f6001600160a01b031681526020018e81526020018a6020015181526020018d81526020018481526020018581526020018681526020016116b88b6101000151600160519190911c81161490565b1515815260200160008460028111156116d3576116d361372c565b146116e6576116e18b612b25565b6116ef565b6116ef8b612b42565b81526020018c81526020018b815250905061170f89610100015160541c90565b6001600160a01b031663a51cfd18826040518263ffffffff1660e01b815260040161173a919061375b565b6000604051808303816000875af1158015611759573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526117819190810190613856565b9199509097509550611795915050565b8893505b50508251849150156117ef5760005b83518110156117ed5760008482815181106117c1576117c16136dc565b6020026020010151602001519050806000146117e4576117e18184613262565b92505b506001016117a4565b505b3360009081526001602090815260408083208c8452909152902054811115611843576040517f2fca7ece00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b801561186b573360009081526001602090815260408083208c84529091529020805482900390555b50600160008190555095509550955095915050565b6000816000036118925750600061195b565b828411156118a25750600061195b565b6040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018690526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa158015611924573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061194891906131b3565b905061195786828787876129d4565b9150505b949350505050565b60006119708484846127c0565b90505b9392505050565b6040517f43a266c20000000000000000000000000000000000000000000000000000000081526004810184905260009081906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906343a266c29060240161012060405180830381865afa1580156119fe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a2291906131b3565b9050600083611a9d57611a988787848a6001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a9391906132b6565b61247d565b611b6a565b611b6a86886001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611adf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b0391906132b6565b896001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b41573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b6591906132b6565b6127c0565b905080600003611b7f5760009250505061195b565b6040517f5dd8f6aa000000000000000000000000000000000000000000000000000000008152600481018790526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635dd8f6aa90602401602060405180830381865afa158015611c00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c249190613275565b6001600160a01b031663c18f2d31886040518263ffffffff1660e01b8152600401611c5191815260200190565b602060405180830381865afa158015611c6e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c9291906132b6565b905080861115611ca8576000935050505061195b565b611cb587848884866129d4565b98975050505050505050565b611d196040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b6000600260005403611d87576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103d1565b60026000556040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018690527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa158015611e0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e2f91906131b3565b61010081015190925060491c600190811603611e77576040517f861e9dcd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152600260209081526040808320888452825280832085518452909152812054611ea6908690613262565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635dd8f6aa896040518263ffffffff1660e01b8152600401611ef991815260200190565b602060405180830381865afa158015611f16573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f3a9190613275565b6001600160a01b031663a29a68146040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f9b9190613275565b6001600160a01b031663e8db213089876020015133336001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611fee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120129190613275565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e087901b168152600481019490945260248401929092526001600160a01b0390811660448401521660648201526084016040805180830381865afa158015612083573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120a79190613292565b91509150818311806120b7575081155b156120ee576040517f08dae4ac00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b808614612127576040517fe56ea4e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000336001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b91906132b6565b90508087146121a9576121a4886107b56012600a6133ef565b6121ab565b875b3360009081526001602090815260408083208d8452909152902054909550851115612202576040517f2fca7ece00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50503360008181526002602090815260408083208b845282528083208851845282528083209590955591815260018083528482209982529890915291822080548490039055509490945593915050565b600061232783837f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166343a266c2866040518263ffffffff1660e01b81526004016122a791815260200190565b61012060405180830381865afa1580156122c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122e991906131b3565b866001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a6f573d6000803e3d6000fd5b90505b92915050565b336000908152600160209081526040808320858452909152902054612356908290613262565b336000908152600160209081526040808320958352949052929092209190915550565b600080807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff858709858702925082811083820303915050806000036123d1578382816123c7576123c7613937565b0492505050611973565b838110612414576040517f773cc18c00000000000000000000000000000000000000000000000000000000815260048101829052602481018590526044016103d1565b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b6001600160a01b03841660009081526001602090815260408083208684529091528120548082036124b257600091505061195b565b6040517f5dd8f6aa0000000000000000000000000000000000000000000000000000000081526004810186905260009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690635dd8f6aa90602401602060405180830381865afa158015612535573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125599190613275565b6001600160a01b031663a29a68146040518163ffffffff1660e01b8152600401602060405180830381865afa158015612596573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125ba9190613275565b6001600160a01b031663e8db21308888602001518b8c6001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561260d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126319190613275565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e087901b168152600481019490945260248401929092526001600160a01b0390811660448401521660648201526084016040805180830381865afa1580156126a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126c69190613292565b6001600160a01b038a1660009081526002602090815260408083208c845282528083208b5184529091528120549294509092509061270490846133fb565b905080158015906127155750858214155b156127a15761279e8161272a6012600a6133ef565b6040517fa4d0caf200000000000000000000000000000000000000000000000000000000815260048101869052602481018a9052601260448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a4d0caf290606401610825565b90505b8084116127af5760006127b3565b8084035b9998505050505050505050565b6040517fd17541530000000000000000000000000000000000000000000000000000000081526004810184905260009081906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063d175415390602401600060405180830381865afa158015612843573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261286b9190810190613966565b90506000805b82518110156129165782818151811061288c5761288c6136dc565b60200260200101516001600160a01b031663a32e1e96886040518263ffffffff1660e01b81526004016128c191815260200190565b602060405180830381865afa1580156128de573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061290291906132b6565b61290c9083613262565b9150600101612871565b506000600185146129aa576040517fa4d0caf20000000000000000000000000000000000000000000000000000000081526001600482015260248101869052601260448201526129a5908390670de0b6b3a7640000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a4d0caf290606401610825565b6129ac565b815b9050856012146129c7576129c281601288612b5f565b6129c9565b805b979650505050505050565b60008284036129e4575080612b1c565b6000806040517fc55f571c000000000000000000000000000000000000000000000000000000008152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c55f571c90602401602060405180830381865afa158015612a65573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a89919061370b565b6002811115612a9a57612a9a61372c565b14612aad57612aa886612b25565b612ab6565b612ab686612b42565b905080600003612aca576000915050612b1c565b6000612ad7848787612379565b90506127108203612aeb579150612b1c9050565b612b1781612b0588612aff866127106133fb565b89612379565b612b0f9085613262565b612710612379565b925050505b95945050505050565b60006028826101000151901c61ffff1661271061232a91906133fb565b60006038826101000151901c61ffff1661271061232a91906133fb565b6000828203612b6f575082611973565b82821115612b9d57612b8183836133fb565b612b8c90600a6133ef565b612b9690856139f5565b9050611973565b612ba782846133fb565b612bb290600a6133ef565b612b969085613a32565b6001600160a01b0381168114612bd157600080fd5b50565b60008060408385031215612be757600080fd5b8235612bf281612bbc565b946020939093013593505050565b600080600060608486031215612c1557600080fd5b505081359360208301359350604090920135919050565b6101408101612c998285805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c08301526001600160a01b0360e08201511660e08301526101008082015181840152505050565b826101208301529392505050565b60008083601f840112612cb957600080fd5b50813567ffffffffffffffff811115612cd157600080fd5b602083019150836020828501011115612ce957600080fd5b9250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff81118282101715612d4357612d43612cf0565b60405290565b6040805190810167ffffffffffffffff81118282101715612d4357612d43612cf0565b604051601f8201601f1916810167ffffffffffffffff81118282101715612d9557612d95612cf0565b604052919050565b600067ffffffffffffffff821115612db757612db7612cf0565b50601f01601f191660200190565b6000612dd8612dd384612d9d565b612d6c565b9050828152838383011115612dec57600080fd5b828260208301376000602084830101529392505050565b600082601f830112612e1457600080fd5b61232783833560208501612dc5565b600080600080600080600080888a03610140811215612e4157600080fd5b8935612e4c81612bbc565b98506080601f1982011215612e6057600080fd5b5060208901965060a0890135955060c0890135945060e0890135612e8381612bbc565b935061010089013567ffffffffffffffff80821115612ea157600080fd5b612ead8c838d01612ca7565b90955093506101208b0135915080821115612ec757600080fd5b50612ed48b828c01612e03565b9150509295985092959890939650565b60005b83811015612eff578181015183820152602001612ee7565b50506000910152565b60008151808452612f20816020860160208601612ee4565b601f01601f19169290920160200192915050565b6000610180808301612fa48489805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c08301526001600160a01b0360e08201511660e08301526101008082015181840152505050565b61012084018790526101408401919091528451908190526101a083019060209081870160005b82811015612ffa57815180516001600160a01b031686528401518486015260409094019390830190600101612fca565b505050508281036101608401526129c98185612f08565b60006020828403121561302357600080fd5b5035919050565b600080600080600060a0868803121561304257600080fd5b853561304d81612bbc565b94506020860135935060408601359250606086013567ffffffffffffffff8082111561307857600080fd5b818801915088601f83011261308c57600080fd5b61309b89833560208501612dc5565b935060808801359150808211156130b157600080fd5b506130be88828901612e03565b9150509295509295909350565b600080600080608085870312156130e157600080fd5b5050823594602084013594506040840135936060013592509050565b6000806000806080858703121561311357600080fd5b843561311e81612bbc565b935060208501359250604085013591506060850135801515811461314157600080fd5b939692955090935050565b60008060006060848603121561316157600080fd5b833561316c81612bbc565b95602085013595506040909401359392505050565b6000806040838503121561319457600080fd5b50508035926020909101359150565b80516131ae81612bbc565b919050565b600061012082840312156131c657600080fd5b6131ce612d1f565b825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015261321a60e084016131a3565b60e0820152610100928301519281019290925250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561232a5761232a613233565b60006020828403121561328757600080fd5b815161197381612bbc565b600080604083850312156132a557600080fd5b505080516020909101519092909150565b6000602082840312156132c857600080fd5b5051919050565b600181815b8085111561332857817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561330e5761330e613233565b8085161561331b57918102915b93841c93908002906132d4565b509250929050565b60008261333f5750600161232a565b8161334c5750600061232a565b8160018114613362576002811461336c57613388565b600191505061232a565b60ff84111561337d5761337d613233565b50506001821b61232a565b5060208310610133831016604e8410600b84101617156133ab575081810a61232a565b6133b583836132cf565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156133e7576133e7613233565b029392505050565b60006123278383613330565b8181038181111561232a5761232a613233565b60006080828403121561342057600080fd5b6040516080810181811067ffffffffffffffff8211171561344357613443612cf0565b604052823561345181612bbc565b808252506020830135602082015260408301356040820152606083013560608201528091505092915050565b602081526134976020820183516001600160a01b03169052565b600060208301516134b360408401826001600160a01b03169052565b5060408301516134f060608401826001600160a01b0381511682526020810151602083015260408101516040830152606081015160608301525050565b50606083015160e08301526080830151610100818185015260a08501519150610120613526818601846001600160a01b03169052565b60c086015161014086015260e08601516101608601528186015192506101a091508161018086015261355c6101c0860184612f08565b90860151858203601f1901838701529092506135788382612f08565b9695505050505050565b600082601f83011261359357600080fd5b81516135a1612dd382612d9d565b8181528460208386010111156135b657600080fd5b61195b826020830160208701612ee4565b600067ffffffffffffffff8211156135e1576135e1612cf0565b5060051b60200190565b60008060006060848603121561360057600080fd5b8351925060208085015167ffffffffffffffff8082111561362057600080fd5b61362c88838901613582565b945060409150818701518181111561364357600080fd5b87019050601f8101881361365657600080fd5b8051613664612dd3826135c7565b81815260069190911b8201840190848101908a83111561368357600080fd5b928501925b828410156136cc5784848c0312156136a05760008081fd5b6136a8612d49565b84516136b381612bbc565b8152848701518782015282529284019290850190613688565b8096505050505050509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561371d57600080fd5b81516003811061197357600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b602081526137756020820183516001600160a01b03169052565b6000602083015161379160408401826001600160a01b03169052565b506040830151606083015260608301516080830152608083015160a083015260a083015160c083015260c083015160e083015260e0830151610100613802818501836001600160a01b0381511682526020810151602083015260408101516040830152606081015160608301525050565b8401511515610180840152506101208301516101a08301526101408301516101e06101c08401819052613839610200850183612f08565b9150610160850151601f1985840301828601526135788382612f08565b60008060006060848603121561386b57600080fd5b8351925060208085015167ffffffffffffffff8082111561388b57600080fd5b61389788838901613582565b94506040915081870151818111156138ae57600080fd5b87019050601f810188136138c157600080fd5b80516138cf612dd3826135c7565b81815260069190911b8201840190848101908a8311156138ee57600080fd5b928501925b828410156136cc5784848c03121561390b5760008081fd5b613913612d49565b845161391e81612bbc565b81528487015187820152825292840192908501906138f3565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000602080838503121561397957600080fd5b825167ffffffffffffffff81111561399057600080fd5b8301601f810185136139a157600080fd5b80516139af612dd3826135c7565b81815260059190911b820183019083810190878311156139ce57600080fd5b928401925b828410156129c95783516139e681612bbc565b825292840192908401906139d3565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a2d57613a2d613233565b500290565b600082613a68577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b50049056fea2646970667358221220472cf79391445f8d8a779847ccca68da89347336bdf6d8d6fa3a32f972aa4a6264736f6c63430008100033", "devdoc": { diff --git a/deployments/goerli/solcInputs/7271447540576b6e014cf146f777e938.json b/deployments/goerli/solcInputs/7271447540576b6e014cf146f777e938.json index 1ab7168a2..43b5a811b 100644 --- a/deployments/goerli/solcInputs/7271447540576b6e014cf146f777e938.json +++ b/deployments/goerli/solcInputs/7271447540576b6e014cf146f777e938.json @@ -164,7 +164,7 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './../structs/JBFundAccessConstraints.sol';\nimport './../structs/JBFundingCycleData.sol';\nimport './../structs/JBFundingCycleMetadata.sol';\nimport './../structs/JBGroupedSplits.sol';\nimport './../structs/JBProjectMetadata.sol';\nimport './IJBDirectory.sol';\nimport './IJBFundingCycleStore.sol';\nimport './IJBMigratable.sol';\nimport './IJBPaymentTerminal.sol';\nimport './IJBSplitsStore.sol';\nimport './IJBTokenStore.sol';\n\ninterface IJBController is IERC165 {\n event LaunchProject(uint256 configuration, uint256 projectId, string memo, address caller);\n\n event LaunchFundingCycles(uint256 configuration, uint256 projectId, string memo, address caller);\n\n event ReconfigureFundingCycles(\n uint256 configuration,\n uint256 projectId,\n string memo,\n address caller\n );\n\n event SetFundAccessConstraints(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n JBFundAccessConstraints constraints,\n address caller\n );\n\n event DistributeReservedTokens(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address beneficiary,\n uint256 tokenCount,\n uint256 beneficiaryTokenCount,\n string memo,\n address caller\n );\n\n event DistributeToReservedTokenSplit(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n JBSplit split,\n uint256 tokenCount,\n address caller\n );\n\n event MintTokens(\n address indexed beneficiary,\n uint256 indexed projectId,\n uint256 tokenCount,\n uint256 beneficiaryTokenCount,\n string memo,\n uint256 reservedRate,\n address caller\n );\n\n event BurnTokens(\n address indexed holder,\n uint256 indexed projectId,\n uint256 tokenCount,\n string memo,\n address caller\n );\n\n event Migrate(uint256 indexed projectId, IJBMigratable to, address caller);\n\n event PrepMigration(uint256 indexed projectId, address from, address caller);\n\n function projects() external view returns (IJBProjects);\n\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\n\n function tokenStore() external view returns (IJBTokenStore);\n\n function splitsStore() external view returns (IJBSplitsStore);\n\n function directory() external view returns (IJBDirectory);\n\n function reservedTokenBalanceOf(uint256 _projectId, uint256 _reservedRate)\n external\n view\n returns (uint256);\n\n function distributionLimitOf(\n uint256 _projectId,\n uint256 _configuration,\n IJBPaymentTerminal _terminal,\n address _token\n ) external view returns (uint256 distributionLimit, uint256 distributionLimitCurrency);\n\n function overflowAllowanceOf(\n uint256 _projectId,\n uint256 _configuration,\n IJBPaymentTerminal _terminal,\n address _token\n ) external view returns (uint256 overflowAllowance, uint256 overflowAllowanceCurrency);\n\n function totalOutstandingTokensOf(uint256 _projectId, uint256 _reservedRate)\n external\n view\n returns (uint256);\n\n function getFundingCycleOf(uint256 _projectId, uint256 _configuration)\n external\n view\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\n\n function latestConfiguredFundingCycleOf(uint256 _projectId)\n external\n view\n returns (\n JBFundingCycle memory,\n JBFundingCycleMetadata memory metadata,\n JBBallotState\n );\n\n function currentFundingCycleOf(uint256 _projectId)\n external\n view\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\n\n function queuedFundingCycleOf(uint256 _projectId)\n external\n view\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\n\n function launchProjectFor(\n address _owner,\n JBProjectMetadata calldata _projectMetadata,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] memory _groupedSplits,\n JBFundAccessConstraints[] memory _fundAccessConstraints,\n IJBPaymentTerminal[] memory _terminals,\n string calldata _memo\n ) external returns (uint256 projectId);\n\n function launchFundingCyclesFor(\n uint256 _projectId,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] memory _groupedSplits,\n JBFundAccessConstraints[] memory _fundAccessConstraints,\n IJBPaymentTerminal[] memory _terminals,\n string calldata _memo\n ) external returns (uint256 configuration);\n\n function reconfigureFundingCyclesOf(\n uint256 _projectId,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] memory _groupedSplits,\n JBFundAccessConstraints[] memory _fundAccessConstraints,\n string calldata _memo\n ) external returns (uint256);\n\n function mintTokensOf(\n uint256 _projectId,\n uint256 _tokenCount,\n address _beneficiary,\n string calldata _memo,\n bool _preferClaimedTokens,\n bool _useReservedRate\n ) external returns (uint256 beneficiaryTokenCount);\n\n function burnTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string calldata _memo,\n bool _preferClaimedTokens\n ) external;\n\n function distributeReservedTokensOf(uint256 _projectId, string memory _memo)\n external\n returns (uint256);\n\n function migrate(uint256 _projectId, IJBMigratable _to) external;\n}\n" }, "contracts/JBSingleTokenPaymentTerminalStore3_1.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController3_1.sol';\nimport './interfaces/IJBFundingCycleDataSource.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './structs/JBPayDelegateAllocation.sol';\nimport './structs/JBPayParamsData.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n\n @dev\n This Store expects a project's controller to be an IJBController3_1. This is the only difference between this version and the original.\n*/\ncontract JBSingleTokenPaymentTerminalStore3_1 is\n ReentrancyGuard,\n IJBSingleTokenPaymentTerminalStore\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId);\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n JBPayDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .payParams(_data);\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\n {\n // Keep a reference to the amount that should be added to the project's balance.\n uint256 _balanceDiff = _amount.value;\n\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\n if (delegateAllocations.length != 0) {\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0) {\n // Can't delegate more than was paid.\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\n\n // Decrement the total amount being added to the balance.\n _balanceDiff = _balanceDiff - _delegatedAmount;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Add the correct balance difference to the token balance of the project.\n if (_balanceDiff != 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _balanceDiff;\n }\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId);\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow != 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\n {\n // Get a reference to the ballot state.\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\n\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n _state == JBBallotState.Active\n ? fundingCycle.ballotRedemptionRate()\n : fundingCycle.redemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\n fundingCycle.dataSource()\n ).redeemParams(_data);\n }\n } else {\n memo = _memo;\n }\n }\n\n // Keep a reference to the amount that should be subtracted from the project's balance.\n uint256 _balanceDiff = reclaimAmount;\n\n if (delegateAllocations.length != 0) {\n // Validate all delegated amounts.\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0)\n // Increment the total amount being subtracted from the balance.\n _balanceDiff = _balanceDiff + _delegatedAmount;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (_balanceDiff != 0) {\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n _balanceDiff;\n }\n }\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).fundAccessConstraintsStore().distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).fundAccessConstraintsStore().overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).fundAccessConstraintsStore().distributionLimitOf(\n _projectId,\n _fundingCycle.configuration,\n _terminal,\n _terminal.token()\n );\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n unchecked {\n return\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i; _i < _terminals.length; ) {\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n unchecked {\n ++_i;\n }\n }\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.ETH\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.ETH, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController3_1.sol';\nimport './interfaces/IJBFundingCycleDataSource.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './structs/JBPayDelegateAllocation.sol';\nimport './structs/JBPayParamsData.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n\n @dev\n This Store expects a project's controller to be an IJBController3_1. This is the only difference between this version and the original.\n*/\ncontract JBSingleTokenPaymentTerminalStore3_1 is\n ReentrancyGuard,\n IJBSingleTokenPaymentTerminalStore\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId);\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n JBPayDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .payParams(_data);\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\n {\n // Keep a reference to the amount that should be added to the project's balance.\n uint256 _balanceDiff = _amount.value;\n\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\n if (delegateAllocations.length != 0) {\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0) {\n // Can't delegate more than was paid.\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\n\n // Decrement the total amount being added to the balance.\n _balanceDiff = _balanceDiff - _delegatedAmount;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Add the correct balance difference to the token balance of the project.\n if (_balanceDiff != 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _balanceDiff;\n }\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId);\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow != 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\n {\n // Get a reference to the ballot state.\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\n\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n _state == JBBallotState.Active\n ? fundingCycle.ballotRedemptionRate()\n : fundingCycle.redemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\n fundingCycle.dataSource()\n ).redeemParams(_data);\n }\n } else {\n memo = _memo;\n }\n }\n\n // Keep a reference to the amount that should be subtracted from the project's balance.\n uint256 _balanceDiff = reclaimAmount;\n\n if (delegateAllocations.length != 0) {\n // Validate all delegated amounts.\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0)\n // Increment the total amount being subtracted from the balance.\n _balanceDiff = _balanceDiff + _delegatedAmount;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (_balanceDiff != 0) {\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n _balanceDiff;\n }\n }\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).fundAccessConstraintsStore().distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).fundAccessConstraintsStore().overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).fundAccessConstraintsStore().distributionLimitOf(\n _projectId,\n _fundingCycle.configuration,\n _terminal,\n _terminal.token()\n );\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n unchecked {\n return\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i; _i < _terminals.length; ) {\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n unchecked {\n ++_i;\n }\n }\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.GAS_CURRENCY\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.GAS_CURRENCY, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" }, "@openzeppelin/contracts/security/ReentrancyGuard.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n constructor() {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n // On the first call to nonReentrant, _notEntered will be true\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n\n _;\n\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n}\n" @@ -224,7 +224,7 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IJBPriceFeed {\n function currentPrice(uint256 _targetDecimals) external view returns (uint256);\n}\n" }, "contracts/JBSingleTokenPaymentTerminalStore.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController.sol';\nimport './interfaces/IJBFundingCycleDataSource.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './structs/JBPayDelegateAllocation.sol';\nimport './structs/JBPayParamsData.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBSingleTokenPaymentTerminalStore is ReentrancyGuard, IJBSingleTokenPaymentTerminalStore {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n JBPayDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .payParams(_data);\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\n {\n // Keep a reference to the amount that should be added to the project's balance.\n uint256 _balanceDiff = _amount.value;\n\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\n if (delegateAllocations.length != 0) {\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0) {\n // Can't delegate more than was paid.\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\n\n // Decrement the total amount being added to the balance.\n _balanceDiff = _balanceDiff - _delegatedAmount;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Add the correct balance difference to the token balance of the project.\n if (_balanceDiff != 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _balanceDiff;\n }\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\n _projectId,\n fundingCycle.reservedRate()\n );\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow != 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\n {\n // Get a reference to the ballot state.\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\n\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n _state == JBBallotState.Active\n ? fundingCycle.ballotRedemptionRate()\n : fundingCycle.redemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\n fundingCycle.dataSource()\n ).redeemParams(_data);\n }\n } else {\n memo = _memo;\n }\n }\n\n // Keep a reference to the amount that should be subtracted from the project's balance.\n uint256 _balanceDiff = reclaimAmount;\n\n if (delegateAllocations.length != 0) {\n // Validate all delegated amounts.\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0)\n // Increment the total amount being subtracted from the balance.\n _balanceDiff = _balanceDiff + _delegatedAmount;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (_balanceDiff != 0) {\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n _balanceDiff;\n }\n }\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n unchecked {\n return\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i; _i < _terminals.length; ) {\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n unchecked {\n ++_i;\n }\n }\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.ETH\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.ETH, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController.sol';\nimport './interfaces/IJBFundingCycleDataSource.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './structs/JBPayDelegateAllocation.sol';\nimport './structs/JBPayParamsData.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBSingleTokenPaymentTerminalStore is ReentrancyGuard, IJBSingleTokenPaymentTerminalStore {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n JBPayDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .payParams(_data);\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\n {\n // Keep a reference to the amount that should be added to the project's balance.\n uint256 _balanceDiff = _amount.value;\n\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\n if (delegateAllocations.length != 0) {\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0) {\n // Can't delegate more than was paid.\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\n\n // Decrement the total amount being added to the balance.\n _balanceDiff = _balanceDiff - _delegatedAmount;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Add the correct balance difference to the token balance of the project.\n if (_balanceDiff != 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _balanceDiff;\n }\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\n _projectId,\n fundingCycle.reservedRate()\n );\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow != 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\n {\n // Get a reference to the ballot state.\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\n\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n _state == JBBallotState.Active\n ? fundingCycle.ballotRedemptionRate()\n : fundingCycle.redemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\n fundingCycle.dataSource()\n ).redeemParams(_data);\n }\n } else {\n memo = _memo;\n }\n }\n\n // Keep a reference to the amount that should be subtracted from the project's balance.\n uint256 _balanceDiff = reclaimAmount;\n\n if (delegateAllocations.length != 0) {\n // Validate all delegated amounts.\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0)\n // Increment the total amount being subtracted from the balance.\n _balanceDiff = _balanceDiff + _delegatedAmount;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (_balanceDiff != 0) {\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n _balanceDiff;\n }\n }\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n unchecked {\n return\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i; _i < _terminals.length; ) {\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n unchecked {\n ++_i;\n }\n }\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.GAS_CURRENCY\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.GAS_CURRENCY, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" }, "contracts/interfaces/IJBPayoutRedemptionPaymentTerminal3_1.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './../structs/JBFee.sol';\nimport './IJBAllowanceTerminal3_1.sol';\nimport './IJBDirectory.sol';\nimport './IJBFeeGauge.sol';\nimport './IJBFeeHoldingTerminal.sol';\nimport './IJBPayDelegate.sol';\nimport './IJBPaymentTerminal.sol';\nimport './IJBPayoutTerminal3_1.sol';\nimport './IJBPrices.sol';\nimport './IJBProjects.sol';\nimport './IJBRedemptionDelegate.sol';\nimport './IJBRedemptionTerminal.sol';\nimport './IJBSingleTokenPaymentTerminalStore.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBPayoutRedemptionPaymentTerminal3_1 is\n IJBPaymentTerminal,\n IJBPayoutTerminal3_1,\n IJBAllowanceTerminal3_1,\n IJBRedemptionTerminal,\n IJBFeeHoldingTerminal\n{\n event AddToBalance(\n uint256 indexed projectId,\n uint256 amount,\n uint256 refundedFees,\n string memo,\n bytes metadata,\n address caller\n );\n\n event Migrate(\n uint256 indexed projectId,\n IJBPaymentTerminal indexed to,\n uint256 amount,\n address caller\n );\n\n event DistributePayouts(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address beneficiary,\n uint256 amount,\n uint256 distributedAmount,\n uint256 fee,\n uint256 beneficiaryDistributionAmount,\n bytes metadata,\n address caller\n );\n\n event UseAllowance(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address beneficiary,\n uint256 amount,\n uint256 distributedAmount,\n uint256 netDistributedamount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event HoldFee(\n uint256 indexed projectId,\n uint256 indexed amount,\n uint256 indexed fee,\n uint256 feeDiscount,\n address beneficiary,\n address caller\n );\n\n event ProcessFee(\n uint256 indexed projectId,\n uint256 indexed amount,\n bool indexed wasHeld,\n address beneficiary,\n address caller\n );\n\n event RefundHeldFees(\n uint256 indexed projectId,\n uint256 indexed amount,\n uint256 indexed refundedFees,\n uint256 leftoverAmount,\n address caller\n );\n\n event Pay(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address payer,\n address beneficiary,\n uint256 amount,\n uint256 beneficiaryTokenCount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DelegateDidPay(\n IJBPayDelegate indexed delegate,\n JBDidPayData data,\n uint256 delegatedAmount,\n address caller\n );\n\n event RedeemTokens(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address holder,\n address beneficiary,\n uint256 tokenCount,\n uint256 reclaimedAmount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DelegateDidRedeem(\n IJBRedemptionDelegate indexed delegate,\n JBDidRedeemData data,\n uint256 delegatedAmount,\n address caller\n );\n\n event DistributeToPayoutSplit(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n JBSplit split,\n uint256 amount,\n uint256 netAmount,\n address caller\n );\n\n event SetFee(uint256 fee, address caller);\n\n event SetFeeGauge(IJBFeeGauge indexed feeGauge, address caller);\n\n event SetFeelessAddress(address indexed addrs, bool indexed flag, address caller);\n\n event PayoutReverted(uint256 indexed projectId, JBSplit split, uint256 amount, bytes reason, address caller);\n\n event FeeReverted(\n uint256 indexed projectId,\n uint256 indexed feeProjectId,\n uint256 amount,\n bytes reason,\n address caller\n );\n\n function projects() external view returns (IJBProjects);\n\n function splitsStore() external view returns (IJBSplitsStore);\n\n function directory() external view returns (IJBDirectory);\n\n function prices() external view returns (IJBPrices);\n\n function store() external view returns (IJBSingleTokenPaymentTerminalStore);\n\n function baseWeightCurrency() external view returns (uint256);\n\n function payoutSplitsGroup() external view returns (uint256);\n\n function heldFeesOf(uint256 _projectId) external view returns (JBFee[] memory);\n\n function fee() external view returns (uint256);\n\n function feeGauge() external view returns (IJBFeeGauge);\n\n function isFeelessAddress(address _contract) external view returns (bool);\n\n function migrate(uint256 _projectId, IJBPaymentTerminal _to) external returns (uint256 balance);\n\n function processFees(uint256 _projectId) external;\n\n function setFee(uint256 _fee) external;\n\n function setFeeGauge(IJBFeeGauge _feeGauge) external;\n\n function setFeelessAddress(address _contract, bool _flag) external;\n}\n" @@ -284,10 +284,10 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nlibrary JBSplitsGroups {\n uint256 public constant ETH_PAYOUT = 1;\n uint256 public constant RESERVED_TOKENS = 2;\n}\n" }, "contracts/JBETHPaymentTerminal3_1.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal3_1.sol';\nimport './libraries/JBSplitsGroups.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal3_1: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal3_1 is JBPayoutRedemptionPaymentTerminal3_1 {\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return address(this).balance;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal3_1(\n JBTokens.ETH,\n 18, // 18 decimals.\n JBCurrencies.ETH,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal3_1.sol';\nimport './libraries/JBSplitsGroups.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal3_1: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal3_1 is JBPayoutRedemptionPaymentTerminal3_1 {\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return address(this).balance;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal3_1(\n JBTokens.GAS_TOKEN,\n 18, // 18 decimals.\n JBCurrencies.GAS_CURRENCY,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n}\n" }, "contracts/abstract/JBPayoutRedemptionPaymentTerminal3_1.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/utils/introspection/ERC165Checker.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal3_1.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBPayDelegateAllocation.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal3_1: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal3_1 is\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n IJBPayoutRedemptionPaymentTerminal3_1\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n @dev\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.ETH)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.ETH, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal3_1).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal3_1).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal3_1).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance.\n */\n function _balance() internal view virtual returns (uint256);\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n bytes calldata _metadata\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _metadata);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes calldata _metadata\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _useAllowanceOf(\n _projectId,\n _amount,\n _currency,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n // Do not refund held fees by default.\n addToBalanceOf(_projectId, _amount, _token, false, _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary, _projectId);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n bool _shouldRefundHeldFees,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.ETH) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance.\n _addToBalanceOf(_projectId, _amount, _shouldRefundHeldFees, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual {\n _from; // Prevents unused var compiler and natspec complaints.\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered if a transfer should be undone\n\n @param _to The address to which the transfer went.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _cancelTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\n {\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\n\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _forwardedAmount,\n _beneficiary,\n _memo,\n _metadata\n );\n\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\n\n emit DelegateDidRedeem(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n bytes calldata _metadata\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n }\n\n // Take the fee.\n _fee = _feeEligibleDistributionAmount != 0\n ? _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n )\n : 0;\n\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\n if (_leftoverDistributionAmount != 0) {\n // Subtract the fee from the net leftover amount.\n netLeftoverDistributionAmount =\n _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n\n // Transfer the amount to the project owner.\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes calldata _metadata\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n // The total percentage available to split\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = _split.percent == leftoverPercentage\n ? leftoverAmount\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\n\n // Decrement the leftover percentage.\n leftoverPercentage -= _split.percent;\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount = _distributeToPayoutSplit(\n _split,\n _projectId,\n _group,\n _payoutAmount,\n _feeDiscount\n );\n\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (_netPayoutAmount != 0 && _netPayoutAmount != _payoutAmount)\n feeEligibleDistributionAmount += _payoutAmount;\n\n if (_payoutAmount > 0) {\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _payoutAmount,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Pays out a split for a project's funding cycle configuration.\n \n @param _split The split to distribute payouts to.\n @param _amount The total amount being distributed to the split, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return netPayoutAmount The amount sent to the split after subtracting fees.\n */\n function _distributeToPayoutSplit(\n JBSplit memory _split,\n uint256 _projectId,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 netPayoutAmount) {\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_split.allocator)]\n )\n netPayoutAmount = _amount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\n }\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), netPayoutAmount);\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n uint256 _error;\n bytes memory _reason;\n\n if (\n ERC165Checker.supportsInterface(\n address(_split.allocator),\n type(IJBSplitAllocator).interfaceId\n )\n )\n // If this terminal's token is ETH, send it in msg.value.\n try _split.allocator.allocate{value: token == JBTokens.ETH ? netPayoutAmount : 0}(_data) {\n\n } catch (bytes memory reason) {\n _reason = reason;\n _error = 1;\n }\n else _error = 2;\n\n\n if (_error != 0) {\n // Trigger any inhereted post-transfer cancelation logic.\n _cancelTransferTo(address(_split.allocator), netPayoutAmount);\n\n // Set the net payout amount to 0 to signal the reversion.\n netPayoutAmount = 0;\n\n // Add undistributed amount back to project's balance.\n store.recordAddedBalanceFor(_projectId, _amount);\n\n emit PayoutReverted(_projectId, _split, _amount, _error == 1 ? _reason : abi.encode(\"IERC165 fail\"), msg.sender);\n }\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (\n _terminal == this ||\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\n isFeelessAddress[address(_terminal)]\n )\n netPayoutAmount = _amount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\n }\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), netPayoutAmount);\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n try\n _terminal.addToBalanceOf{value: token == JBTokens.ETH ? netPayoutAmount : 0}(\n _split.projectId,\n netPayoutAmount,\n token,\n '',\n _projectMetadata\n )\n {} catch (bytes memory reason) {\n // Trigger any inhereted post-transfer cancelation logic.\n _cancelTransferTo(address(_terminal), netPayoutAmount);\n\n // Set the net payout amount to 0 to signal the reversion.\n netPayoutAmount = 0;\n\n // Add undistributed amount back to project's balance.\n store.recordAddedBalanceFor(_projectId, _amount);\n\n emit PayoutReverted(_projectId, _split, _amount, reason, msg.sender);\n }\n else\n try\n _terminal.pay{value: token == JBTokens.ETH ? netPayoutAmount : 0}(\n _split.projectId,\n netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n )\n {} catch (bytes memory reason) {\n // Trigger any inhereted post-transfer cancelation logic.\n _cancelTransferTo(address(_terminal), netPayoutAmount);\n\n // Set the net payout amount to 0 to signal the reversion.\n netPayoutAmount = 0;\n\n // Add undistributed amount back to project's balance.\n store.recordAddedBalanceFor(_projectId, _amount);\n\n emit PayoutReverted(_projectId, _split, _amount, reason, msg.sender);\n }\n } else {\n // Keep a reference to the beneficiary.\n address payable _beneficiary = _split.beneficiary != address(0)\n ? _split.beneficiary\n : payable(msg.sender);\n\n // If there's a full discount, this distribution is not eligible for a fee.\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\n netPayoutAmount = _amount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\n else {\n unchecked {\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\n }\n }\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(address(this), _beneficiary, netPayoutAmount);\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary, _projectId); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n @param _from The project ID the fee is being paid from.\n */\n function _processFee(\n uint256 _amount,\n address _beneficiary,\n uint256 _from\n ) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _amount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_from));\n\n // Trigger any inherited pre-transfer logic if funds will be transferred.\n if (address(_terminal) != address(this)) _beforeTransferTo(address(_terminal), _amount);\n\n try\n // Send the fee.\n _terminal.pay{value: _payableValue}(\n _FEE_BENEFICIARY_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n _projectMetadata\n )\n {} catch (bytes memory reason) {\n // Trigger any inhereted post-transfer cancelation logic if the pre-transfer logic was triggered.\n if (address(_terminal) != address(this)) _cancelTransferTo(address(_terminal), _amount);\n\n // Add fee amount back to project's balance.\n store.recordAddedBalanceFor(_from, _amount);\n\n emit FeeReverted(_from, _FEE_BENEFICIARY_PROJECT_ID, _amount, reason, msg.sender);\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\n {\n JBPayDelegateAllocation[] memory _delegateAllocations;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n _forwardedAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n // Get a reference to the number of delegates to allocate to.\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\n\n emit DelegateDidPay(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n unchecked {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\n IJBPaymentTerminal(address(0))\n ) return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge != IJBFeeGauge(address(0)))\n // If the guage reverts, keep the discount at 0.\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n // If the fee discount is greater than the max, we ignore the return value\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\n } catch {\n return 0;\n }\n\n return 0;\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/utils/introspection/ERC165Checker.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal3_1.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBPayDelegateAllocation.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal3_1: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal3_1 is\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n IJBPayoutRedemptionPaymentTerminal3_1\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n @dev\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.GAS_CURRENCY)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.GAS_CURRENCY, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal3_1).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal3_1).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal3_1).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance.\n */\n function _balance() internal view virtual returns (uint256);\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n bytes calldata _metadata\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _metadata);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes calldata _metadata\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _useAllowanceOf(\n _projectId,\n _amount,\n _currency,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n // Do not refund held fees by default.\n addToBalanceOf(_projectId, _amount, _token, false, _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary, _projectId);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n bool _shouldRefundHeldFees,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.GAS_TOKEN) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance.\n _addToBalanceOf(_projectId, _amount, _shouldRefundHeldFees, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual {\n _from; // Prevents unused var compiler and natspec complaints.\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered if a transfer should be undone\n\n @param _to The address to which the transfer went.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _cancelTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\n {\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\n\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _forwardedAmount,\n _beneficiary,\n _memo,\n _metadata\n );\n\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\n\n emit DelegateDidRedeem(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n bytes calldata _metadata\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n }\n\n // Take the fee.\n _fee = _feeEligibleDistributionAmount != 0\n ? _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n )\n : 0;\n\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\n if (_leftoverDistributionAmount != 0) {\n // Subtract the fee from the net leftover amount.\n netLeftoverDistributionAmount =\n _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n\n // Transfer the amount to the project owner.\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes calldata _metadata\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n // The total percentage available to split\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = _split.percent == leftoverPercentage\n ? leftoverAmount\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\n\n // Decrement the leftover percentage.\n leftoverPercentage -= _split.percent;\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount = _distributeToPayoutSplit(\n _split,\n _projectId,\n _group,\n _payoutAmount,\n _feeDiscount\n );\n\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (_netPayoutAmount != 0 && _netPayoutAmount != _payoutAmount)\n feeEligibleDistributionAmount += _payoutAmount;\n\n if (_payoutAmount > 0) {\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _payoutAmount,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Pays out a split for a project's funding cycle configuration.\n \n @param _split The split to distribute payouts to.\n @param _amount The total amount being distributed to the split, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return netPayoutAmount The amount sent to the split after subtracting fees.\n */\n function _distributeToPayoutSplit(\n JBSplit memory _split,\n uint256 _projectId,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 netPayoutAmount) {\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_split.allocator)]\n )\n netPayoutAmount = _amount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\n }\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), netPayoutAmount);\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n uint256 _error;\n bytes memory _reason;\n\n if (\n ERC165Checker.supportsInterface(\n address(_split.allocator),\n type(IJBSplitAllocator).interfaceId\n )\n )\n // If this terminal's token is ETH, send it in msg.value.\n try _split.allocator.allocate{value: token == JBTokens.GAS_TOKEN ? netPayoutAmount : 0}(_data) {\n\n } catch (bytes memory reason) {\n _reason = reason;\n _error = 1;\n }\n else _error = 2;\n\n\n if (_error != 0) {\n // Trigger any inhereted post-transfer cancelation logic.\n _cancelTransferTo(address(_split.allocator), netPayoutAmount);\n\n // Set the net payout amount to 0 to signal the reversion.\n netPayoutAmount = 0;\n\n // Add undistributed amount back to project's balance.\n store.recordAddedBalanceFor(_projectId, _amount);\n\n emit PayoutReverted(_projectId, _split, _amount, _error == 1 ? _reason : abi.encode(\"IERC165 fail\"), msg.sender);\n }\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (\n _terminal == this ||\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\n isFeelessAddress[address(_terminal)]\n )\n netPayoutAmount = _amount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\n }\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), netPayoutAmount);\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n try\n _terminal.addToBalanceOf{value: token == JBTokens.GAS_TOKEN ? netPayoutAmount : 0}(\n _split.projectId,\n netPayoutAmount,\n token,\n '',\n _projectMetadata\n )\n {} catch (bytes memory reason) {\n // Trigger any inhereted post-transfer cancelation logic.\n _cancelTransferTo(address(_terminal), netPayoutAmount);\n\n // Set the net payout amount to 0 to signal the reversion.\n netPayoutAmount = 0;\n\n // Add undistributed amount back to project's balance.\n store.recordAddedBalanceFor(_projectId, _amount);\n\n emit PayoutReverted(_projectId, _split, _amount, reason, msg.sender);\n }\n else\n try\n _terminal.pay{value: token == JBTokens.GAS_TOKEN ? netPayoutAmount : 0}(\n _split.projectId,\n netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n )\n {} catch (bytes memory reason) {\n // Trigger any inhereted post-transfer cancelation logic.\n _cancelTransferTo(address(_terminal), netPayoutAmount);\n\n // Set the net payout amount to 0 to signal the reversion.\n netPayoutAmount = 0;\n\n // Add undistributed amount back to project's balance.\n store.recordAddedBalanceFor(_projectId, _amount);\n\n emit PayoutReverted(_projectId, _split, _amount, reason, msg.sender);\n }\n } else {\n // Keep a reference to the beneficiary.\n address payable _beneficiary = _split.beneficiary != address(0)\n ? _split.beneficiary\n : payable(msg.sender);\n\n // If there's a full discount, this distribution is not eligible for a fee.\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\n netPayoutAmount = _amount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\n else {\n unchecked {\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\n }\n }\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(address(this), _beneficiary, netPayoutAmount);\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary, _projectId); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n @param _from The project ID the fee is being paid from.\n */\n function _processFee(\n uint256 _amount,\n address _beneficiary,\n uint256 _from\n ) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_from));\n\n // Trigger any inherited pre-transfer logic if funds will be transferred.\n if (address(_terminal) != address(this)) _beforeTransferTo(address(_terminal), _amount);\n\n try\n // Send the fee.\n _terminal.pay{value: _payableValue}(\n _FEE_BENEFICIARY_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n _projectMetadata\n )\n {} catch (bytes memory reason) {\n // Trigger any inhereted post-transfer cancelation logic if the pre-transfer logic was triggered.\n if (address(_terminal) != address(this)) _cancelTransferTo(address(_terminal), _amount);\n\n // Add fee amount back to project's balance.\n store.recordAddedBalanceFor(_from, _amount);\n\n emit FeeReverted(_from, _FEE_BENEFICIARY_PROJECT_ID, _amount, reason, msg.sender);\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\n {\n JBPayDelegateAllocation[] memory _delegateAllocations;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n _forwardedAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n // Get a reference to the number of delegates to allocate to.\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\n\n emit DelegateDidPay(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n unchecked {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\n IJBPaymentTerminal(address(0))\n ) return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge != IJBFeeGauge(address(0)))\n // If the guage reverts, keep the discount at 0.\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n // If the fee discount is greater than the max, we ignore the return value\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\n } catch {\n return 0;\n }\n\n return 0;\n }\n}\n" }, "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165Checker.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Library used to query support of an interface declared via {IERC165}.\n *\n * Note that these functions return the actual result of the query: they do not\n * `revert` if an interface is not supported. It is up to the caller to decide\n * what to do in these cases.\n */\nlibrary ERC165Checker {\n // As per the EIP-165 spec, no interface should ever match 0xffffffff\n bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;\n\n /**\n * @dev Returns true if `account` supports the {IERC165} interface,\n */\n function supportsERC165(address account) internal view returns (bool) {\n // Any contract that implements ERC165 must explicitly indicate support of\n // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid\n return\n _supportsERC165Interface(account, type(IERC165).interfaceId) &&\n !_supportsERC165Interface(account, _INTERFACE_ID_INVALID);\n }\n\n /**\n * @dev Returns true if `account` supports the interface defined by\n * `interfaceId`. Support for {IERC165} itself is queried automatically.\n *\n * See {IERC165-supportsInterface}.\n */\n function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {\n // query support of both ERC165 as per the spec and support of _interfaceId\n return supportsERC165(account) && _supportsERC165Interface(account, interfaceId);\n }\n\n /**\n * @dev Returns a boolean array where each value corresponds to the\n * interfaces passed in and whether they're supported or not. This allows\n * you to batch check interfaces for a contract where your expectation\n * is that some interfaces may not be supported.\n *\n * See {IERC165-supportsInterface}.\n *\n * _Available since v3.4._\n */\n function getSupportedInterfaces(address account, bytes4[] memory interfaceIds)\n internal\n view\n returns (bool[] memory)\n {\n // an array of booleans corresponding to interfaceIds and whether they're supported or not\n bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);\n\n // query support of ERC165 itself\n if (supportsERC165(account)) {\n // query support of each interface in interfaceIds\n for (uint256 i = 0; i < interfaceIds.length; i++) {\n interfaceIdsSupported[i] = _supportsERC165Interface(account, interfaceIds[i]);\n }\n }\n\n return interfaceIdsSupported;\n }\n\n /**\n * @dev Returns true if `account` supports all the interfaces defined in\n * `interfaceIds`. Support for {IERC165} itself is queried automatically.\n *\n * Batch-querying can lead to gas savings by skipping repeated checks for\n * {IERC165} support.\n *\n * See {IERC165-supportsInterface}.\n */\n function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {\n // query support of ERC165 itself\n if (!supportsERC165(account)) {\n return false;\n }\n\n // query support of each interface in _interfaceIds\n for (uint256 i = 0; i < interfaceIds.length; i++) {\n if (!_supportsERC165Interface(account, interfaceIds[i])) {\n return false;\n }\n }\n\n // all interfaces supported\n return true;\n }\n\n /**\n * @notice Query if a contract implements an interface, does not check ERC165 support\n * @param account The address of the contract to query for support of an interface\n * @param interfaceId The interface identifier, as specified in ERC-165\n * @return true if the contract at account indicates support of the interface with\n * identifier interfaceId, false otherwise\n * @dev Assumes that account contains a contract that supports ERC165, otherwise\n * the behavior of this method is undefined. This precondition can be checked\n * with {supportsERC165}.\n * Interface identification is specified in ERC-165.\n */\n function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) {\n bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);\n (bool success, bytes memory result) = account.staticcall{gas: 30000}(encodedParams);\n if (result.length < 32) return false;\n return success && abi.decode(result, (bool));\n }\n}\n" @@ -304,29 +304,29 @@ "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n function safeTransfer(\n IERC20 token,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(\n IERC20 token,\n address from,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n uint256 newAllowance = token.allowance(address(this), spender) + value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n uint256 newAllowance = oldAllowance - value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) {\n // Return data is optional\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" }, - "contracts/JBETHERC20SplitsPayer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBSplitsPayer.sol';\nimport './interfaces/IJBSplitsStore.sol';\nimport './libraries/JBConstants.sol';\nimport './JBETHERC20ProjectPayer.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\n\n @dev\n Adheres to -\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBETHERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBETHERC20SplitsPayer is JBETHERC20ProjectPayer, ReentrancyGuard, IJBSplitsPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The ID of project for which the default splits are stored. \n */\n uint256 public override defaultSplitsProjectId;\n\n /**\n @notice\n The domain within which the default splits are stored. \n */\n uint256 public override defaultSplitsDomain;\n\n /**\n @notice\n The group within which the default splits are stored. \n */\n uint256 public override defaultSplitsGroup;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBETHERC20ProjectPayer, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n )\n JBETHERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _preferAddToBalance,\n _splitsStore.directory(),\n _owner\n )\n {\n defaultSplitsProjectId = _defaultSplitsProjectId;\n defaultSplitsDomain = _defaultSplitsDomain;\n defaultSplitsGroup = _defaultSplitsGroup;\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default split group using the stored default properties.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override nonReentrant {\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n JBTokens.ETH,\n address(this).balance,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // If there is no leftover amount, nothing left to pay.\n if (_leftoverAmount == 0) return;\n\n // If there's a default project ID, try to pay it.\n if (defaultProjectId != 0)\n if (defaultPreferAddToBalance)\n // Pay the project by adding to its balance if prefered.\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.ETH,\n _leftoverAmount,\n 18, // decimals.\n defaultMemo,\n defaultMetadata\n );\n // Otherwise, issue a payment to the project.\n else\n _pay(\n defaultProjectId,\n JBTokens.ETH,\n _leftoverAmount,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n 0, // min returned tokens.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else\n Address.sendValue(\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(tx.origin),\n _leftoverAmount\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the splits in the splits store that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n @param _groupedSplits The split groups to set.\n */\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n JBGroupedSplits[] memory _groupedSplits\n ) external virtual override onlyOwner {\n // Set the splits in the store.\n splitsStore.set(_projectId, _domain, _groupedSplits);\n\n // Set the splits reference.\n setDefaultSplitsReference(_projectId, _domain, _group);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the location of the splits that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n */\n function setDefaultSplitsReference(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) public virtual override onlyOwner {\n // Set the default splits project ID if it's changing.\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\n\n // Set the default splits domain if it's changing.\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\n\n // Set the default splits group if it's changing.\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\n\n emit SetDefaultSplitsReference(_projectId, _domain, _group, msg.sender);\n }\n\n /** \n @notice \n Make a payment to the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Pay any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to pay it.\n if (_projectId != 0) {\n _pay(\n _projectId,\n _token,\n _leftoverAmount,\n _decimals,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? payable(_beneficiary) : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit Pay(\n _projectId,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event. \n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Distribute any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to add to its balance.\n if (_projectId != 0)\n // Add to the project's balance.\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\n\n // Otherwise, send a payment to the beneficiary.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit AddToBalance(\n _projectId,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splitsProjectId The ID of the project to which the splits belong.\n @param _splitsDomain The splits domain to which the group belongs.\n @param _splitsGroup The splits group to pay.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payToSplits(\n uint256 _splitsProjectId,\n uint256 _splitsDomain,\n uint256 _splitsGroup,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Pay the splits.\n leftoverAmount = _payTo(\n splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup),\n _token,\n _amount,\n _decimals,\n _defaultBeneficiary\n );\n emit DistributeToSplitGroup(_splitsProjectId, _splitsDomain, _splitsGroup, msg.sender);\n }\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splits The splits.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payTo(\n JBSplit[] memory _splits,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Set the leftover amount to the initial balance.\n leftoverAmount = _amount;\n\n // Settle between all splits.\n for (uint256 i; i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[i];\n\n // The amount to send towards the split.\n uint256 _splitAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n if (_splitAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n _token,\n _splitAmount,\n _decimals,\n defaultProjectId,\n 0,\n _split\n );\n\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\n if (_token != JBTokens.ETH)\n IERC20(_token).safeApprove(address(_split.allocator), _splitAmount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _splitAmount : 0;\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n if (_split.preferAddToBalance)\n _addToBalanceOf(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n 0,\n _split.preferClaimed,\n defaultMemo,\n defaultMetadata\n );\n } else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : payable(_defaultBeneficiary),\n _splitAmount\n );\n // Or, transfer the ERC20.\n else {\n IERC20(_token).safeTransfer(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n _splitAmount\n );\n }\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _splitAmount;\n }\n\n emit DistributeToSplit(_split, _splitAmount, _defaultBeneficiary, msg.sender);\n\n unchecked {\n ++i;\n }\n }\n }\n}\n" + "contracts/JBGasTokenERC20SplitsPayer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBSplitsPayer.sol';\nimport './interfaces/IJBSplitsStore.sol';\nimport './libraries/JBConstants.sol';\nimport './JBGasTokenERC20ProjectPayer.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\n\n @dev\n Adheres to -\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBGasTokenERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBGasTokenERC20SplitsPayer is JBGasTokenERC20ProjectPayer, ReentrancyGuard, IJBSplitsPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The ID of project for which the default splits are stored. \n */\n uint256 public override defaultSplitsProjectId;\n\n /**\n @notice\n The domain within which the default splits are stored. \n */\n uint256 public override defaultSplitsDomain;\n\n /**\n @notice\n The group within which the default splits are stored. \n */\n uint256 public override defaultSplitsGroup;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBGasTokenERC20ProjectPayer, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n )\n JBGasTokenERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _preferAddToBalance,\n _splitsStore.directory(),\n _owner\n )\n {\n defaultSplitsProjectId = _defaultSplitsProjectId;\n defaultSplitsDomain = _defaultSplitsDomain;\n defaultSplitsGroup = _defaultSplitsGroup;\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default split group using the stored default properties.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override nonReentrant {\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // If there is no leftover amount, nothing left to pay.\n if (_leftoverAmount == 0) return;\n\n // If there's a default project ID, try to pay it.\n if (defaultProjectId != 0)\n if (defaultPreferAddToBalance)\n // Pay the project by adding to its balance if prefered.\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n _leftoverAmount,\n 18, // decimals.\n defaultMemo,\n defaultMetadata\n );\n // Otherwise, issue a payment to the project.\n else\n _pay(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n _leftoverAmount,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n 0, // min returned tokens.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else\n Address.sendValue(\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(tx.origin),\n _leftoverAmount\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the splits in the splits store that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n @param _groupedSplits The split groups to set.\n */\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n JBGroupedSplits[] memory _groupedSplits\n ) external virtual override onlyOwner {\n // Set the splits in the store.\n splitsStore.set(_projectId, _domain, _groupedSplits);\n\n // Set the splits reference.\n setDefaultSplitsReference(_projectId, _domain, _group);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the location of the splits that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n */\n function setDefaultSplitsReference(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) public virtual override onlyOwner {\n // Set the default splits project ID if it's changing.\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\n\n // Set the default splits domain if it's changing.\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\n\n // Set the default splits group if it's changing.\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\n\n emit SetDefaultSplitsReference(_projectId, _domain, _group, msg.sender);\n }\n\n /** \n @notice \n Make a payment to the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Pay any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to pay it.\n if (_projectId != 0) {\n _pay(\n _projectId,\n _token,\n _leftoverAmount,\n _decimals,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? payable(_beneficiary) : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit Pay(\n _projectId,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event. \n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Distribute any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to add to its balance.\n if (_projectId != 0)\n // Add to the project's balance.\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\n\n // Otherwise, send a payment to the beneficiary.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit AddToBalance(\n _projectId,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splitsProjectId The ID of the project to which the splits belong.\n @param _splitsDomain The splits domain to which the group belongs.\n @param _splitsGroup The splits group to pay.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payToSplits(\n uint256 _splitsProjectId,\n uint256 _splitsDomain,\n uint256 _splitsGroup,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Pay the splits.\n leftoverAmount = _payTo(\n splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup),\n _token,\n _amount,\n _decimals,\n _defaultBeneficiary\n );\n emit DistributeToSplitGroup(_splitsProjectId, _splitsDomain, _splitsGroup, msg.sender);\n }\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splits The splits.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payTo(\n JBSplit[] memory _splits,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Set the leftover amount to the initial balance.\n leftoverAmount = _amount;\n\n // Settle between all splits.\n for (uint256 i; i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[i];\n\n // The amount to send towards the split.\n uint256 _splitAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n if (_splitAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n _token,\n _splitAmount,\n _decimals,\n defaultProjectId,\n 0,\n _split\n );\n\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN)\n IERC20(_token).safeApprove(address(_split.allocator), _splitAmount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _splitAmount : 0;\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n if (_split.preferAddToBalance)\n _addToBalanceOf(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n 0,\n _split.preferClaimed,\n defaultMemo,\n defaultMetadata\n );\n } else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : payable(_defaultBeneficiary),\n _splitAmount\n );\n // Or, transfer the ERC20.\n else {\n IERC20(_token).safeTransfer(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n _splitAmount\n );\n }\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _splitAmount;\n }\n\n emit DistributeToSplit(_split, _splitAmount, _defaultBeneficiary, msg.sender);\n\n unchecked {\n ++i;\n }\n }\n }\n}\n" }, "contracts/interfaces/IJBSplitsPayer.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './../structs/JBSplit.sol';\nimport './../structs/JBGroupedSplits.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBSplitsPayer is IERC165 {\n event SetDefaultSplitsReference(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n address caller\n );\n event Pay(\n uint256 indexed projectId,\n address beneficiary,\n address token,\n uint256 amount,\n uint256 decimals,\n uint256 leftoverAmount,\n uint256 minReturnedTokens,\n bool preferClaimedTokens,\n string memo,\n bytes metadata,\n address caller\n );\n\n event AddToBalance(\n uint256 indexed projectId,\n address beneficiary,\n address token,\n uint256 amount,\n uint256 decimals,\n uint256 leftoverAmount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DistributeToSplitGroup(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n address caller\n );\n\n event DistributeToSplit(\n JBSplit split,\n uint256 amount,\n address defaultBeneficiary,\n address caller\n );\n\n function defaultSplitsProjectId() external view returns (uint256);\n\n function defaultSplitsDomain() external view returns (uint256);\n\n function defaultSplitsGroup() external view returns (uint256);\n\n function splitsStore() external view returns (IJBSplitsStore);\n\n function setDefaultSplitsReference(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) external;\n\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n JBGroupedSplits[] memory _splitsGroup\n ) external;\n}\n" }, - "contracts/JBETHERC20ProjectPayer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport './interfaces/IJBProjectPayer.sol';\nimport './libraries/JBTokens.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ERC165: Introspection on interface adherance. \n*/\ncontract JBETHERC20ProjectPayer is Ownable, ERC165, IJBProjectPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // -------------------------- custom errors -------------------------- //\n //*********************************************************************//\n error INCORRECT_DECIMAL_AMOUNT();\n error NO_MSG_VALUE_ALLOWED();\n error TERMINAL_NOT_FOUND();\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice \n A contract storing directories of terminals and controllers for each project.\n */\n IJBDirectory public immutable override directory;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The ID of the project that should be used to forward this contract's received payments.\n */\n uint256 public override defaultProjectId;\n\n /** \n @notice \n The beneficiary that should be used in the payment made when this contract receives payments.\n */\n address payable public override defaultBeneficiary;\n\n /** \n @notice \n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\n */\n bool public override defaultPreferClaimedTokens;\n\n /** \n @notice \n The memo that should be used in the payment made when this contract receives payments.\n */\n string public override defaultMemo;\n\n /** \n @notice \n The metadata that should be used in the payment made when this contract receives payments.\n */\n bytes public override defaultMetadata;\n\n /**\n @notice \n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n bool public override defaultPreferAddToBalance;\n\n //*********************************************************************//\n // ------------------------- public views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) {\n defaultProjectId = _defaultProjectId;\n defaultBeneficiary = _defaultBeneficiary;\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\n defaultMemo = _defaultMemo;\n defaultMetadata = _defaultMetadata;\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n directory = _directory;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default project ID using the stored default properties.\n\n @dev\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override {\n if (defaultPreferAddToBalance)\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.ETH,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n defaultProjectId,\n JBTokens.ETH,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultBeneficiary == address(0) ? tx.origin : defaultBeneficiary,\n 0, // Can't determine expectation of returned tokens ahead of time.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\n\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _beneficiary The address that'll receive the project's tokens. \n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _memo The memo that'll be used. \n @param _metadata The metadata that'll be sent. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external virtual override onlyOwner {\n // Set the default project ID if it has changed.\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\n\n // Set the default beneficiary if it has changed.\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\n\n // Set the default claimed token preference if it has changed.\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\n defaultPreferClaimedTokens = _preferClaimedTokens;\n\n // Set the default memo if it has changed.\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\n defaultMemo = _memo;\n\n // Set the default metadata if it has changed.\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\n defaultMetadata = _metadata;\n\n // Set the add to balance preference if it has changed.\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n\n emit SetDefaultValues(\n _projectId,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata,\n _defaultPreferAddToBalance,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _pay(\n _projectId,\n _token,\n _amount,\n _decimals,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. \n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source and delegate, if provided.\n */\n function _pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.ETH) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\n\n // Send funds to the terminal.\n // If the token is ETH, send it in msg.value.\n _terminal.pay{value: _payableValue}(\n _projectId,\n _amount, // ignored if the token is JBTokens.ETH.\n _token,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.ETH) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\n\n // Add to balance so tokens don't get issued.\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\n }\n}\n" + "contracts/JBGasTokenERC20ProjectPayer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport './interfaces/IJBProjectPayer.sol';\nimport './libraries/JBTokens.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ERC165: Introspection on interface adherance. \n*/\ncontract JBGasTokenERC20ProjectPayer is Ownable, ERC165, IJBProjectPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // -------------------------- custom errors -------------------------- //\n //*********************************************************************//\n error INCORRECT_DECIMAL_AMOUNT();\n error NO_MSG_VALUE_ALLOWED();\n error TERMINAL_NOT_FOUND();\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice \n A contract storing directories of terminals and controllers for each project.\n */\n IJBDirectory public immutable override directory;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The ID of the project that should be used to forward this contract's received payments.\n */\n uint256 public override defaultProjectId;\n\n /** \n @notice \n The beneficiary that should be used in the payment made when this contract receives payments.\n */\n address payable public override defaultBeneficiary;\n\n /** \n @notice \n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\n */\n bool public override defaultPreferClaimedTokens;\n\n /** \n @notice \n The memo that should be used in the payment made when this contract receives payments.\n */\n string public override defaultMemo;\n\n /** \n @notice \n The metadata that should be used in the payment made when this contract receives payments.\n */\n bytes public override defaultMetadata;\n\n /**\n @notice \n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n bool public override defaultPreferAddToBalance;\n\n //*********************************************************************//\n // ------------------------- public views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) {\n defaultProjectId = _defaultProjectId;\n defaultBeneficiary = _defaultBeneficiary;\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\n defaultMemo = _defaultMemo;\n defaultMetadata = _defaultMetadata;\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n directory = _directory;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default project ID using the stored default properties.\n\n @dev\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override {\n if (defaultPreferAddToBalance)\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultBeneficiary == address(0) ? tx.origin : defaultBeneficiary,\n 0, // Can't determine expectation of returned tokens ahead of time.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\n\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _beneficiary The address that'll receive the project's tokens. \n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _memo The memo that'll be used. \n @param _metadata The metadata that'll be sent. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external virtual override onlyOwner {\n // Set the default project ID if it has changed.\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\n\n // Set the default beneficiary if it has changed.\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\n\n // Set the default claimed token preference if it has changed.\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\n defaultPreferClaimedTokens = _preferClaimedTokens;\n\n // Set the default memo if it has changed.\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\n defaultMemo = _memo;\n\n // Set the default metadata if it has changed.\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\n defaultMetadata = _metadata;\n\n // Set the add to balance preference if it has changed.\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n\n emit SetDefaultValues(\n _projectId,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata,\n _defaultPreferAddToBalance,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _pay(\n _projectId,\n _token,\n _amount,\n _decimals,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. \n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source and delegate, if provided.\n */\n function _pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send funds to the terminal.\n // If the token is ETH, send it in msg.value.\n _terminal.pay{value: _payableValue}(\n _projectId,\n _amount, // ignored if the token is JBTokens.GAS_TOKEN.\n _token,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Add to balance so tokens don't get issued.\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\n }\n}\n" }, "contracts/interfaces/IJBProjectPayer.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './IJBDirectory.sol';\n\ninterface IJBProjectPayer is IERC165 {\n event SetDefaultValues(\n uint256 indexed projectId,\n address indexed beneficiary,\n bool preferClaimedTokens,\n string memo,\n bytes metadata,\n bool preferAddToBalance,\n address caller\n );\n\n function directory() external view returns (IJBDirectory);\n\n function defaultProjectId() external view returns (uint256);\n\n function defaultBeneficiary() external view returns (address payable);\n\n function defaultPreferClaimedTokens() external view returns (bool);\n\n function defaultMemo() external view returns (string memory);\n\n function defaultMetadata() external view returns (bytes memory);\n\n function defaultPreferAddToBalance() external view returns (bool);\n\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external;\n\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) external payable;\n\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) external payable;\n\n receive() external payable;\n}\n" }, - "contracts/JBETHERC20SplitsPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './interfaces/IJBETHERC20SplitsPayerDeployer.sol';\nimport './structs/JBSplit.sol';\nimport './structs/JBGroupedSplits.sol';\nimport './JBETHERC20SplitsPayer.sol';\n\n/** \n @notice \n Deploys splits payer contracts.\n\n @dev\n Adheres to -\n IJBETHERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBETHERC20SplitsPayerDeployer is IJBETHERC20SplitsPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @dev\n This contract must have Operator permissions over the SET_SPLITS permission of the specified `_defaultSplitsProjectId`.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplits The splits to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBSplitsPayer splitsPayer) {\n // Use this contract's address as the domain.\n uint256 _domain = uint256(uint160(address(this)));\n\n // Create the random hash using data unique to this instance that'll be used as the storage domain.\n uint256 _group = uint256(keccak256(abi.encodePacked(msg.sender, block.number)));\n\n // Set the splits in the store.\n JBGroupedSplits[] memory _groupedSplits;\n _groupedSplits = new JBGroupedSplits[](1);\n _groupedSplits[0] = JBGroupedSplits(_group, _defaultSplits);\n _splitsStore.set(_defaultSplitsProjectId, _domain, _groupedSplits);\n\n return\n deploySplitsPayer(\n _defaultSplitsProjectId,\n _domain,\n _group,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n }\n\n //*********************************************************************//\n // ---------------------- public transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) public override returns (IJBSplitsPayer splitsPayer) {\n // Deploy the splits payer.\n splitsPayer = new JBETHERC20SplitsPayer(\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeploySplitsPayer(\n splitsPayer,\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner,\n msg.sender\n );\n }\n}\n" + "contracts/JBGasTokenERC20SplitsPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './interfaces/IJBGasTokenERC20SplitsPayerDeployer.sol';\nimport './structs/JBSplit.sol';\nimport './structs/JBGroupedSplits.sol';\nimport './JBGasTokenERC20SplitsPayer.sol';\n\n/** \n @notice \n Deploys splits payer contracts.\n\n @dev\n Adheres to -\n IJBGasTokenERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBGasTokenERC20SplitsPayerDeployer is IJBGasTokenERC20SplitsPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @dev\n This contract must have Operator permissions over the SET_SPLITS permission of the specified `_defaultSplitsProjectId`.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplits The splits to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBSplitsPayer splitsPayer) {\n // Use this contract's address as the domain.\n uint256 _domain = uint256(uint160(address(this)));\n\n // Create the random hash using data unique to this instance that'll be used as the storage domain.\n uint256 _group = uint256(keccak256(abi.encodePacked(msg.sender, block.number)));\n\n // Set the splits in the store.\n JBGroupedSplits[] memory _groupedSplits;\n _groupedSplits = new JBGroupedSplits[](1);\n _groupedSplits[0] = JBGroupedSplits(_group, _defaultSplits);\n _splitsStore.set(_defaultSplitsProjectId, _domain, _groupedSplits);\n\n return\n deploySplitsPayer(\n _defaultSplitsProjectId,\n _domain,\n _group,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n }\n\n //*********************************************************************//\n // ---------------------- public transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) public override returns (IJBSplitsPayer splitsPayer) {\n // Deploy the splits payer.\n splitsPayer = new JBGasTokenERC20SplitsPayer(\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeploySplitsPayer(\n splitsPayer,\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner,\n msg.sender\n );\n }\n}\n" }, - "contracts/interfaces/IJBETHERC20SplitsPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBSplitsPayer.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBETHERC20SplitsPayerDeployer {\n event DeploySplitsPayer(\n IJBSplitsPayer indexed splitsPayer,\n uint256 defaultSplitsProjectId,\n uint256 defaultSplitsDomain,\n uint256 defaultSplitsGroup,\n IJBSplitsStore splitsStore,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n address owner,\n address caller\n );\n\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string calldata _defaultMemo,\n bytes calldata _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n}\n" + "contracts/interfaces/IJBGasTokenERC20SplitsPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBSplitsPayer.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBGasTokenERC20SplitsPayerDeployer {\n event DeploySplitsPayer(\n IJBSplitsPayer indexed splitsPayer,\n uint256 defaultSplitsProjectId,\n uint256 defaultSplitsDomain,\n uint256 defaultSplitsGroup,\n IJBSplitsStore splitsStore,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n address owner,\n address caller\n );\n\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string calldata _defaultMemo,\n bytes calldata _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n}\n" }, - "contracts/JBETHERC20ProjectPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './interfaces/IJBETHERC20ProjectPayerDeployer.sol';\nimport './JBETHERC20ProjectPayer.sol';\n\n/** \n @notice \n Deploys project payer contracts.\n\n @dev\n Adheres to -\n IJBETHERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBETHERC20ProjectPayerDeployer is IJBETHERC20ProjectPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new project payer contract.\n\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the project payer contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the project payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the project payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the project payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the project payer.\n\n @return projectPayer The project payer contract.\n */\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external override returns (IJBProjectPayer projectPayer) {\n // Deploy the project payer.\n projectPayer = new JBETHERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner\n );\n\n emit DeployProjectPayer(\n projectPayer,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner,\n msg.sender\n );\n }\n}\n" + "contracts/JBGasTokenERC20ProjectPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './interfaces/IJBGasTokenERC20ProjectPayerDeployer.sol';\nimport './JBGasTokenERC20ProjectPayer.sol';\n\n/** \n @notice \n Deploys project payer contracts.\n\n @dev\n Adheres to -\n IJBGasTokenERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBGasTokenERC20ProjectPayerDeployer is IJBGasTokenERC20ProjectPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new project payer contract.\n\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the project payer contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the project payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the project payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the project payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the project payer.\n\n @return projectPayer The project payer contract.\n */\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external override returns (IJBProjectPayer projectPayer) {\n // Deploy the project payer.\n projectPayer = new JBGasTokenERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner\n );\n\n emit DeployProjectPayer(\n projectPayer,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner,\n msg.sender\n );\n }\n}\n" }, - "contracts/interfaces/IJBETHERC20ProjectPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBDirectory.sol';\nimport './IJBProjectPayer.sol';\n\ninterface IJBETHERC20ProjectPayerDeployer {\n event DeployProjectPayer(\n IJBProjectPayer indexed projectPayer,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n IJBDirectory directory,\n address owner,\n address caller\n );\n\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external returns (IJBProjectPayer projectPayer);\n}\n" + "contracts/interfaces/IJBGasTokenERC20ProjectPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBDirectory.sol';\nimport './IJBProjectPayer.sol';\n\ninterface IJBGasTokenERC20ProjectPayerDeployer {\n event DeployProjectPayer(\n IJBProjectPayer indexed projectPayer,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n IJBDirectory directory,\n address owner,\n address caller\n );\n\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external returns (IJBProjectPayer projectPayer);\n}\n" }, "contracts/JBDirectory.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport './abstract/JBOperatable.sol';\nimport './interfaces/IJBDirectory.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './libraries/JBOperations.sol';\n\n/**\n @notice\n Keeps a reference of which terminal contracts each project is currently accepting funds through, and which controller contract is managing each project's tokens and funding cycles.\n\n @dev\n Adheres to -\n IJBDirectory: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\ncontract JBDirectory is JBOperatable, Ownable, IJBDirectory {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error DUPLICATE_TERMINALS();\n error INVALID_PROJECT_ID_IN_DIRECTORY();\n error SET_CONTROLLER_NOT_ALLOWED();\n error SET_TERMINALS_NOT_ALLOWED();\n error TOKEN_NOT_ACCEPTED();\n\n //*********************************************************************//\n // --------------------- private stored properties ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n For each project ID, the terminals that are currently managing its funds.\n\n _projectId The ID of the project to get terminals of.\n */\n mapping(uint256 => IJBPaymentTerminal[]) private _terminalsOf;\n\n /**\n @notice\n The project's primary terminal for a token.\n\n _projectId The ID of the project to get the primary terminal of.\n _token The token to get the project's primary terminal of.\n */\n mapping(uint256 => mapping(address => IJBPaymentTerminal)) private _primaryTerminalOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n For each project ID, the controller that manages how terminals interact with tokens and funding cycles.\n\n _projectId The ID of the project to get the controller of.\n */\n mapping(uint256 => address) public override controllerOf;\n\n /**\n @notice\n Addresses that can set a project's first controller on their behalf. These addresses/contracts have been vetted and verified by this contract's owner.\n\n _address The address that is either allowed or not.\n */\n mapping(address => bool) public override isAllowedToSetFirstController;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n For each project ID, the terminals that are currently managing its funds.\n\n @param _projectId The ID of the project to get terminals of.\n\n @return An array of terminal addresses.\n */\n function terminalsOf(uint256 _projectId)\n external\n view\n override\n returns (IJBPaymentTerminal[] memory)\n {\n return _terminalsOf[_projectId];\n }\n\n /**\n @notice\n The primary terminal that is managing funds for a project for a specified token.\n\n @dev\n The zero address is returned if a terminal isn't found for the specified token.\n\n @param _projectId The ID of the project to get a terminal for.\n @param _token The token the terminal accepts.\n\n @return The primary terminal for the project for the specified token.\n */\n function primaryTerminalOf(uint256 _projectId, address _token)\n external\n view\n override\n returns (IJBPaymentTerminal)\n {\n // Keep a reference to the primary terminal for the provided project ID and token.\n IJBPaymentTerminal _primaryTerminal = _primaryTerminalOf[_projectId][_token];\n\n // If a primary terminal for the token was specifically set and it's one of the project's terminals, return it.\n if (\n _primaryTerminal != IJBPaymentTerminal(address(0)) &&\n isTerminalOf(_projectId, _primaryTerminal)\n ) return _primaryTerminal;\n\n // Keep a reference to the number of terminals the project has.\n uint256 _numberOfTerminals = _terminalsOf[_projectId].length;\n\n // Return the first terminal which accepts the specified token.\n for (uint256 _i; _i < _numberOfTerminals; ) {\n // Keep a reference to the terminal being iterated on.\n IJBPaymentTerminal _terminal = _terminalsOf[_projectId][_i];\n\n // If the terminal accepts the specified token, return it.\n if (_terminal.acceptsToken(_token, _projectId)) return _terminal;\n\n unchecked {\n ++_i;\n }\n }\n\n // Not found.\n return IJBPaymentTerminal(address(0));\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Whether or not a specified terminal is a terminal of the specified project.\n\n @param _projectId The ID of the project to check within.\n @param _terminal The address of the terminal to check for.\n\n @return A flag indicating whether or not the specified terminal is a terminal of the specified project.\n */\n function isTerminalOf(uint256 _projectId, IJBPaymentTerminal _terminal)\n public\n view\n override\n returns (bool)\n {\n // Keep a reference to the number of terminals the project has.\n uint256 _numberOfTerminals = _terminalsOf[_projectId].length;\n\n // Loop through and return true if the terminal is contained.\n for (uint256 _i; _i < _numberOfTerminals; ) {\n // If the terminal being iterated on matches the provided terminal, return true.\n if (_terminalsOf[_projectId][_i] == _terminal) return true;\n\n unchecked {\n ++_i;\n }\n }\n\n // Otherwise, return false.\n return false;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _owner The address that will own the contract.\n */\n constructor(\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBFundingCycleStore _fundingCycleStore,\n address _owner\n ) JBOperatable(_operatorStore) {\n projects = _projects;\n fundingCycleStore = _fundingCycleStore;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Update the controller that manages how terminals interact with the ecosystem.\n\n @dev\n A controller can be set if:\n - the message sender is the project owner or an operator having the correct authorization.\n - the message sender is the project's current controller.\n - or, an allowedlisted address is setting a controller for a project that doesn't already have a controller.\n\n @param _projectId The ID of the project to set a new controller for.\n @param _controller The new controller to set.\n */\n function setControllerOf(uint256 _projectId, address _controller)\n external\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.SET_CONTROLLER,\n (msg.sender == address(controllerOf[_projectId]) ||\n (isAllowedToSetFirstController[msg.sender] && controllerOf[_projectId] == address(0)))\n )\n {\n // The project must exist.\n if (projects.count() < _projectId) revert INVALID_PROJECT_ID_IN_DIRECTORY();\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Setting controller is allowed if called from the current controller, or if the project doesn't have a current controller, or if the project's funding cycle allows setting the controller. Revert otherwise.\n if (\n msg.sender != address(controllerOf[_projectId]) &&\n controllerOf[_projectId] != address(0) &&\n !_fundingCycle.global().allowSetController\n ) revert SET_CONTROLLER_NOT_ALLOWED();\n\n // Set the new controller.\n controllerOf[_projectId] = _controller;\n\n emit SetController(_projectId, _controller, msg.sender);\n }\n\n /** \n @notice \n Set a project's terminals.\n\n @dev\n Only a project owner, an operator, or its controller can set its terminals.\n\n @param _projectId The ID of the project having terminals set.\n @param _terminals The terminal to set.\n */\n function setTerminalsOf(uint256 _projectId, IJBPaymentTerminal[] calldata _terminals)\n external\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.SET_TERMINALS,\n msg.sender == address(controllerOf[_projectId])\n )\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Setting terminals must be allowed if not called from the current controller.\n if (\n msg.sender != address(controllerOf[_projectId]) && !_fundingCycle.global().allowSetTerminals\n ) revert SET_TERMINALS_NOT_ALLOWED();\n\n // Set the stored terminals for the project.\n _terminalsOf[_projectId] = _terminals;\n\n // Make sure duplicates were not added.\n if (_terminals.length > 1) {\n for (uint256 _i; _i < _terminals.length; ) {\n for (uint256 _j = _i + 1; _j < _terminals.length; ) {\n if (_terminals[_i] == _terminals[_j]) revert DUPLICATE_TERMINALS();\n\n unchecked {\n ++_j;\n }\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n emit SetTerminals(_projectId, _terminals, msg.sender);\n }\n\n /**\n @notice\n Project's can set which terminal should be their primary for a particular token.\n This is useful in case a project has several terminals connected for a particular token.\n\n @dev\n The terminal will be set as the primary terminal where ecosystem contracts should route tokens.\n\n @dev\n If setting a newly added terminal and the funding cycle doesn't allow new terminals, the caller must be the current controller.\n\n @param _projectId The ID of the project for which a primary token is being set.\n @param _token The token to set the primary terminal of.\n @param _terminal The terminal to make primary.\n */\n function setPrimaryTerminalOf(\n uint256 _projectId,\n address _token,\n IJBPaymentTerminal _terminal\n )\n external\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.SET_PRIMARY_TERMINAL)\n {\n // Can't set the primary terminal for a token if it doesn't accept the token.\n if (!_terminal.acceptsToken(_token, _projectId)) revert TOKEN_NOT_ACCEPTED();\n\n // Add the terminal to the project if it hasn't been already.\n _addTerminalIfNeeded(_projectId, _terminal);\n\n // Store the terminal as the primary for the particular token.\n _primaryTerminalOf[_projectId][_token] = _terminal;\n\n emit SetPrimaryTerminal(_projectId, _token, _terminal, msg.sender);\n }\n\n /** \n @notice\t\n Set a contract to the list of trusted addresses that can set a first controller for any project.\t\n\n @dev\n The owner can add addresses which are allowed to change projects' first controllers. \n These addresses are known and vetted controllers as well as contracts designed to launch new projects. \n A project can set its own controller without it being on the allow list.\n\n @dev\n If you would like an address/contract allowlisted, please reach out to the contract owner.\n\n @param _address The address to allow or revoke allowance from.\n @param _flag Whether allowance is being added or revoked.\n */\n function setIsAllowedToSetFirstController(address _address, bool _flag)\n external\n override\n onlyOwner\n {\n // Set the flag in the allowlist.\n isAllowedToSetFirstController[_address] = _flag;\n\n emit SetIsAllowedToSetFirstController(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Add a terminal to a project's list of terminals if it hasn't been already.\n\n @param _projectId The ID of the project having a terminal added.\n @param _terminal The terminal to add.\n */\n function _addTerminalIfNeeded(uint256 _projectId, IJBPaymentTerminal _terminal) private {\n // Check that the terminal has not already been added.\n if (isTerminalOf(_projectId, _terminal)) return;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Setting terminals must be allowed if not called from the current controller.\n if (\n msg.sender != address(controllerOf[_projectId]) && !_fundingCycle.global().allowSetTerminals\n ) revert SET_TERMINALS_NOT_ALLOWED();\n\n // Add the new terminal.\n _terminalsOf[_projectId].push(_terminal);\n\n emit AddTerminal(_projectId, _terminal, msg.sender);\n }\n}\n" @@ -350,7 +350,7 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './interfaces/IJBOperatorStore.sol';\n\n/** \n @notice\n Stores operator permissions for all addresses. Addresses can give permissions to any other address to take specific indexed actions on their behalf.\n\n @dev\n Adheres to -\n IJBOperatorStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBOperatorStore is IJBOperatorStore {\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error PERMISSION_INDEX_OUT_OF_BOUNDS();\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice\n The permissions that an operator has been given to operate on a specific domain.\n \n @dev\n An account can give an operator permissions that only pertain to a specific domain namespace.\n There is no domain with a value of 0 – accounts can use the 0 domain to give an operator\n permissions to all domains on their behalf.\n\n @dev\n Permissions are stored in a packed `uint256`. Each 256 bits represents the on/off state of a permission. Applications can specify the significance of each index.\n\n _operator The address of the operator.\n _account The address of the account being operated.\n _domain The domain within which the permissions apply. Applications can use the domain namespace as they wish.\n */\n mapping(address => mapping(address => mapping(uint256 => uint256))) public override permissionsOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Whether or not an operator has the permission to take a certain action pertaining to the specified domain.\n\n @param _operator The operator to check.\n @param _account The account that has given out permissions to the operator.\n @param _domain The domain that the operator has been given permissions to operate.\n @param _permissionIndex The permission index to check for.\n\n @return A flag indicating whether the operator has the specified permission.\n */\n function hasPermission(\n address _operator,\n address _account,\n uint256 _domain,\n uint256 _permissionIndex\n ) external view override returns (bool) {\n if (_permissionIndex > 255) revert PERMISSION_INDEX_OUT_OF_BOUNDS();\n\n return (((permissionsOf[_operator][_account][_domain] >> _permissionIndex) & 1) == 1);\n }\n\n /** \n @notice \n Whether or not an operator has the permission to take certain actions pertaining to the specified domain.\n\n @param _operator The operator to check.\n @param _account The account that has given out permissions to the operator.\n @param _domain The domain that the operator has been given permissions to operate.\n @param _permissionIndexes An array of permission indexes to check for.\n\n @return A flag indicating whether the operator has all specified permissions.\n */\n function hasPermissions(\n address _operator,\n address _account,\n uint256 _domain,\n uint256[] calldata _permissionIndexes\n ) external view override returns (bool) {\n for (uint256 _i; _i < _permissionIndexes.length; ) {\n uint256 _permissionIndex = _permissionIndexes[_i];\n\n if (_permissionIndex > 255) revert PERMISSION_INDEX_OUT_OF_BOUNDS();\n\n if (((permissionsOf[_operator][_account][_domain] >> _permissionIndex) & 1) == 0)\n return false;\n\n unchecked {\n ++_i;\n }\n }\n return true;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Sets permissions for an operators.\n\n @dev\n Only an address can set its own operators.\n\n @param _operatorData The data that specifies the params for the operator being set.\n */\n function setOperator(JBOperatorData calldata _operatorData) external override {\n // Pack the indexes into a uint256.\n uint256 _packed = _packedPermissions(_operatorData.permissionIndexes);\n\n // Store the new value.\n permissionsOf[_operatorData.operator][msg.sender][_operatorData.domain] = _packed;\n\n emit SetOperator(\n _operatorData.operator,\n msg.sender,\n _operatorData.domain,\n _operatorData.permissionIndexes,\n _packed\n );\n }\n\n /**\n @notice\n Sets permissions for many operators.\n\n @dev\n Only an address can set its own operators.\n\n @param _operatorData The data that specify the params for each operator being set.\n */\n function setOperators(JBOperatorData[] calldata _operatorData) external override {\n for (uint256 _i; _i < _operatorData.length; ) {\n // Pack the indexes into a uint256.\n uint256 _packed = _packedPermissions(_operatorData[_i].permissionIndexes);\n\n // Store the new value.\n permissionsOf[_operatorData[_i].operator][msg.sender][_operatorData[_i].domain] = _packed;\n\n emit SetOperator(\n _operatorData[_i].operator,\n msg.sender,\n _operatorData[_i].domain,\n _operatorData[_i].permissionIndexes,\n _packed\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Converts an array of permission indexes to a packed `uint256`.\n\n @param _indexes The indexes of the permissions to pack.\n\n @return packed The packed value.\n */\n function _packedPermissions(uint256[] calldata _indexes) private pure returns (uint256 packed) {\n for (uint256 _i; _i < _indexes.length; ) {\n uint256 _index = _indexes[_i];\n\n if (_index > 255) revert PERMISSION_INDEX_OUT_OF_BOUNDS();\n\n // Turn the bit at the index on.\n packed |= 1 << _index;\n\n unchecked {\n ++_i;\n }\n }\n }\n}\n" }, "contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBPayDelegateAllocation.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal is\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n IJBPayoutRedemptionPaymentTerminal\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n @dev\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.ETH)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.ETH, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance.\n */\n function _balance() internal view virtual returns (uint256);\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.ETH) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual {\n _from; // Prevents unused var compiler and natspec complaints.\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\n {\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\n\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _forwardedAmount,\n _beneficiary,\n _memo,\n _metadata\n );\n\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\n\n emit DelegateDidRedeem(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n }\n\n // Take the fee.\n _fee = _feeEligibleDistributionAmount != 0\n ? _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n )\n : 0;\n\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\n if (_leftoverDistributionAmount != 0) {\n // Subtract the fee from the net leftover amount.\n netLeftoverDistributionAmount =\n _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n\n // Transfer the amount to the project owner.\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n // The total percentage available to split\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = _split.percent == leftoverPercentage\n ? leftoverAmount\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\n\n // Decrement the leftover percentage.\n leftoverPercentage -= _split.percent;\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount;\n\n if (_payoutAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\n isFeelessAddress[address(_split.allocator)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n _netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n // If this terminal's token is ETH, send it in msg.value.\n _split.allocator.allocate{value: token == JBTokens.ETH ? _netPayoutAmount : 0}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // Save gas if this contract is being used as the terminal.\n if (_terminal == this) {\n // This distribution does not incur a fee.\n _netPayoutAmount = _payoutAmount;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\n else\n _pay(\n _netPayoutAmount,\n address(this),\n _split.projectId,\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n } else {\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_terminal)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _netPayoutAmount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _terminal.addToBalanceOf{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n '',\n _projectMetadata\n );\n else\n _terminal.pay{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n }\n } else {\n // Keep a reference to the beneficiary.\n address payable _beneficiary = _split.beneficiary != address(0)\n ? _split.beneficiary\n : payable(msg.sender);\n\n // If there's a full discount, this distribution is not eligible for a fee.\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(address(this), _beneficiary, _netPayoutAmount);\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n */\n function _processFee(uint256 _amount, address _beneficiary) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\n\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\n if (_terminal == this)\n _pay(\n _amount,\n address(this),\n _FEE_BENEFICIARY_PROJECT_ID,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the local pay call.\n else {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _amount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _amount : 0;\n\n // Send the payment.\n _terminal.pay{value: _payableValue}(\n _FEE_BENEFICIARY_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the external pay call of the correct terminal.\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\n {\n JBPayDelegateAllocation[] memory _delegateAllocations;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n _forwardedAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n // Get a reference to the number of delegates to allocate to.\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\n\n emit DelegateDidPay(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n unchecked {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\n IJBPaymentTerminal(address(0))\n ) return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge != IJBFeeGauge(address(0)))\n // If the guage reverts, keep the discount at 0.\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n // If the fee discount is greater than the max, we ignore the return value\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\n } catch {\n return 0;\n }\n\n return 0;\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBPayDelegateAllocation.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal is\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n IJBPayoutRedemptionPaymentTerminal\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n @dev\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.GAS_CURRENCY)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.GAS_CURRENCY, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance.\n */\n function _balance() internal view virtual returns (uint256);\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.GAS_TOKEN) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual {\n _from; // Prevents unused var compiler and natspec complaints.\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\n {\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\n\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _forwardedAmount,\n _beneficiary,\n _memo,\n _metadata\n );\n\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\n\n emit DelegateDidRedeem(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n }\n\n // Take the fee.\n _fee = _feeEligibleDistributionAmount != 0\n ? _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n )\n : 0;\n\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\n if (_leftoverDistributionAmount != 0) {\n // Subtract the fee from the net leftover amount.\n netLeftoverDistributionAmount =\n _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n\n // Transfer the amount to the project owner.\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n // The total percentage available to split\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = _split.percent == leftoverPercentage\n ? leftoverAmount\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\n\n // Decrement the leftover percentage.\n leftoverPercentage -= _split.percent;\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount;\n\n if (_payoutAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\n isFeelessAddress[address(_split.allocator)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n _netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n // If this terminal's token is ETH, send it in msg.value.\n _split.allocator.allocate{value: token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // Save gas if this contract is being used as the terminal.\n if (_terminal == this) {\n // This distribution does not incur a fee.\n _netPayoutAmount = _payoutAmount;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\n else\n _pay(\n _netPayoutAmount,\n address(this),\n _split.projectId,\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n } else {\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_terminal)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _terminal.addToBalanceOf{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n '',\n _projectMetadata\n );\n else\n _terminal.pay{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n }\n } else {\n // Keep a reference to the beneficiary.\n address payable _beneficiary = _split.beneficiary != address(0)\n ? _split.beneficiary\n : payable(msg.sender);\n\n // If there's a full discount, this distribution is not eligible for a fee.\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(address(this), _beneficiary, _netPayoutAmount);\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n */\n function _processFee(uint256 _amount, address _beneficiary) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\n\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\n if (_terminal == this)\n _pay(\n _amount,\n address(this),\n _FEE_BENEFICIARY_PROJECT_ID,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the local pay call.\n else {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _amount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send the payment.\n _terminal.pay{value: _payableValue}(\n _FEE_BENEFICIARY_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the external pay call of the correct terminal.\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\n {\n JBPayDelegateAllocation[] memory _delegateAllocations;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n _forwardedAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n // Get a reference to the number of delegates to allocate to.\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\n\n emit DelegateDidPay(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n unchecked {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\n IJBPaymentTerminal(address(0))\n ) return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge != IJBFeeGauge(address(0)))\n // If the guage reverts, keep the discount at 0.\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n // If the fee discount is greater than the max, we ignore the return value\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\n } catch {\n return 0;\n }\n\n return 0;\n }\n}\n" }, "contracts/interfaces/IJBPayoutRedemptionPaymentTerminal.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './../structs/JBFee.sol';\nimport './IJBAllowanceTerminal.sol';\nimport './IJBDirectory.sol';\nimport './IJBFeeGauge.sol';\nimport './IJBPayDelegate.sol';\nimport './IJBPaymentTerminal.sol';\nimport './IJBPayoutTerminal.sol';\nimport './IJBPrices.sol';\nimport './IJBProjects.sol';\nimport './IJBRedemptionDelegate.sol';\nimport './IJBRedemptionTerminal.sol';\nimport './IJBSingleTokenPaymentTerminalStore.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBPayoutRedemptionPaymentTerminal is\n IJBPaymentTerminal,\n IJBPayoutTerminal,\n IJBAllowanceTerminal,\n IJBRedemptionTerminal\n{\n event AddToBalance(\n uint256 indexed projectId,\n uint256 amount,\n uint256 refundedFees,\n string memo,\n bytes metadata,\n address caller\n );\n\n event Migrate(\n uint256 indexed projectId,\n IJBPaymentTerminal indexed to,\n uint256 amount,\n address caller\n );\n\n event DistributePayouts(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address beneficiary,\n uint256 amount,\n uint256 distributedAmount,\n uint256 fee,\n uint256 beneficiaryDistributionAmount,\n string memo,\n address caller\n );\n\n event UseAllowance(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address beneficiary,\n uint256 amount,\n uint256 distributedAmount,\n uint256 netDistributedamount,\n string memo,\n address caller\n );\n\n event HoldFee(\n uint256 indexed projectId,\n uint256 indexed amount,\n uint256 indexed fee,\n uint256 feeDiscount,\n address beneficiary,\n address caller\n );\n\n event ProcessFee(\n uint256 indexed projectId,\n uint256 indexed amount,\n bool indexed wasHeld,\n address beneficiary,\n address caller\n );\n\n event RefundHeldFees(\n uint256 indexed projectId,\n uint256 indexed amount,\n uint256 indexed refundedFees,\n uint256 leftoverAmount,\n address caller\n );\n\n event Pay(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address payer,\n address beneficiary,\n uint256 amount,\n uint256 beneficiaryTokenCount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DelegateDidPay(\n IJBPayDelegate indexed delegate,\n JBDidPayData data,\n uint256 delegatedAmount,\n address caller\n );\n\n event RedeemTokens(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address holder,\n address beneficiary,\n uint256 tokenCount,\n uint256 reclaimedAmount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DelegateDidRedeem(\n IJBRedemptionDelegate indexed delegate,\n JBDidRedeemData data,\n uint256 delegatedAmount,\n address caller\n );\n\n event DistributeToPayoutSplit(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n JBSplit split,\n uint256 amount,\n address caller\n );\n\n event SetFee(uint256 fee, address caller);\n\n event SetFeeGauge(IJBFeeGauge indexed feeGauge, address caller);\n\n event SetFeelessAddress(address indexed addrs, bool indexed flag, address caller);\n\n function projects() external view returns (IJBProjects);\n\n function splitsStore() external view returns (IJBSplitsStore);\n\n function directory() external view returns (IJBDirectory);\n\n function prices() external view returns (IJBPrices);\n\n function store() external view returns (IJBSingleTokenPaymentTerminalStore);\n\n function baseWeightCurrency() external view returns (uint256);\n\n function payoutSplitsGroup() external view returns (uint256);\n\n function heldFeesOf(uint256 _projectId) external view returns (JBFee[] memory);\n\n function fee() external view returns (uint256);\n\n function feeGauge() external view returns (IJBFeeGauge);\n\n function isFeelessAddress(address _contract) external view returns (bool);\n\n function migrate(uint256 _projectId, IJBPaymentTerminal _to) external returns (uint256 balance);\n\n function processFees(uint256 _projectId) external;\n\n function setFee(uint256 _fee) external;\n\n function setFeeGauge(IJBFeeGauge _feeGauge) external;\n\n function setFeelessAddress(address _contract, bool _flag) external;\n}\n" @@ -362,7 +362,7 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IJBPayoutTerminal {\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) external returns (uint256 netLeftoverDistributionAmount);\n}\n" }, "contracts/JBETHPaymentTerminal.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\nimport './libraries/JBSplitsGroups.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return address(this).balance;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n JBTokens.ETH,\n 18, // 18 decimals.\n JBCurrencies.ETH,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\nimport './libraries/JBSplitsGroups.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return address(this).balance;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n JBTokens.GAS_TOKEN,\n 18, // 18 decimals.\n JBCurrencies.GAS_CURRENCY,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n}\n" }, "contracts/JBERC20PaymentTerminal.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\n\n/** \n @notice \n Manages the inflows and outflows of an ERC-20 token.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\ncontract JBERC20PaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return IERC20(token).balanceOf(address(this));\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n IERC20Metadata _token,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n address(_token),\n _token.decimals(),\n _currency,\n _baseWeightCurrency,\n _payoutSplitsGroup,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from == address(this)\n ? IERC20(token).safeTransfer(_to, _amount)\n : IERC20(token).safeTransferFrom(_from, _to, _amount);\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal override {\n IERC20(token).safeApprove(_to, _amount);\n }\n}\n" diff --git a/deployments/goerli/solcInputs/7f5ae5369c2a685c882e67f75315b841.json b/deployments/goerli/solcInputs/7f5ae5369c2a685c882e67f75315b841.json index 8819afbdf..331538fd8 100644 --- a/deployments/goerli/solcInputs/7f5ae5369c2a685c882e67f75315b841.json +++ b/deployments/goerli/solcInputs/7f5ae5369c2a685c882e67f75315b841.json @@ -146,13 +146,13 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport './abstract/JBOperatable.sol';\nimport './interfaces/IJBDirectory.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './libraries/JBOperations.sol';\n\n/**\n @notice\n Keeps a reference of which terminal contracts each project is currently accepting funds through, and which controller contract is managing each project's tokens and funding cycles.\n\n @dev\n Adheres to -\n IJBDirectory: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\ncontract JBDirectory is JBOperatable, Ownable, IJBDirectory {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error DUPLICATE_TERMINALS();\n error INVALID_PROJECT_ID_IN_DIRECTORY();\n error SET_CONTROLLER_NOT_ALLOWED();\n error SET_TERMINALS_NOT_ALLOWED();\n error TOKEN_NOT_ACCEPTED();\n\n //*********************************************************************//\n // --------------------- private stored properties ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n For each project ID, the terminals that are currently managing its funds.\n\n _projectId The ID of the project to get terminals of.\n */\n mapping(uint256 => IJBPaymentTerminal[]) private _terminalsOf;\n\n /**\n @notice\n The project's primary terminal for a token.\n\n _projectId The ID of the project to get the primary terminal of.\n _token The token to get the project's primary terminal of.\n */\n mapping(uint256 => mapping(address => IJBPaymentTerminal)) private _primaryTerminalOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n For each project ID, the controller that manages how terminals interact with tokens and funding cycles.\n\n _projectId The ID of the project to get the controller of.\n */\n mapping(uint256 => address) public override controllerOf;\n\n /**\n @notice\n Addresses that can set a project's first controller on their behalf. These addresses/contracts have been vetted and verified by this contract's owner.\n\n _address The address that is either allowed or not.\n */\n mapping(address => bool) public override isAllowedToSetFirstController;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n For each project ID, the terminals that are currently managing its funds.\n\n @param _projectId The ID of the project to get terminals of.\n\n @return An array of terminal addresses.\n */\n function terminalsOf(uint256 _projectId)\n external\n view\n override\n returns (IJBPaymentTerminal[] memory)\n {\n return _terminalsOf[_projectId];\n }\n\n /**\n @notice\n The primary terminal that is managing funds for a project for a specified token.\n\n @dev\n The zero address is returned if a terminal isn't found for the specified token.\n\n @param _projectId The ID of the project to get a terminal for.\n @param _token The token the terminal accepts.\n\n @return The primary terminal for the project for the specified token.\n */\n function primaryTerminalOf(uint256 _projectId, address _token)\n external\n view\n override\n returns (IJBPaymentTerminal)\n {\n // Keep a reference to the primary terminal for the provided project ID and token.\n IJBPaymentTerminal _primaryTerminal = _primaryTerminalOf[_projectId][_token];\n\n // If a primary terminal for the token was specifically set and it's one of the project's terminals, return it.\n if (\n _primaryTerminal != IJBPaymentTerminal(address(0)) &&\n isTerminalOf(_projectId, _primaryTerminal)\n ) return _primaryTerminal;\n\n // Keep a reference to the number of terminals the project has.\n uint256 _numberOfTerminals = _terminalsOf[_projectId].length;\n\n // Return the first terminal which accepts the specified token.\n for (uint256 _i; _i < _numberOfTerminals; ) {\n // Keep a reference to the terminal being iterated on.\n IJBPaymentTerminal _terminal = _terminalsOf[_projectId][_i];\n\n // If the terminal accepts the specified token, return it.\n if (_terminal.acceptsToken(_token, _projectId)) return _terminal;\n\n unchecked {\n ++_i;\n }\n }\n\n // Not found.\n return IJBPaymentTerminal(address(0));\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Whether or not a specified terminal is a terminal of the specified project.\n\n @param _projectId The ID of the project to check within.\n @param _terminal The address of the terminal to check for.\n\n @return A flag indicating whether or not the specified terminal is a terminal of the specified project.\n */\n function isTerminalOf(uint256 _projectId, IJBPaymentTerminal _terminal)\n public\n view\n override\n returns (bool)\n {\n // Keep a reference to the number of terminals the project has.\n uint256 _numberOfTerminals = _terminalsOf[_projectId].length;\n\n // Loop through and return true if the terminal is contained.\n for (uint256 _i; _i < _numberOfTerminals; ) {\n // If the terminal being iterated on matches the provided terminal, return true.\n if (_terminalsOf[_projectId][_i] == _terminal) return true;\n\n unchecked {\n ++_i;\n }\n }\n\n // Otherwise, return false.\n return false;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _owner The address that will own the contract.\n */\n constructor(\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBFundingCycleStore _fundingCycleStore,\n address _owner\n ) JBOperatable(_operatorStore) {\n projects = _projects;\n fundingCycleStore = _fundingCycleStore;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Update the controller that manages how terminals interact with the ecosystem.\n\n @dev\n A controller can be set if:\n - the message sender is the project owner or an operator having the correct authorization.\n - the message sender is the project's current controller.\n - or, an allowedlisted address is setting a controller for a project that doesn't already have a controller.\n\n @param _projectId The ID of the project to set a new controller for.\n @param _controller The new controller to set.\n */\n function setControllerOf(uint256 _projectId, address _controller)\n external\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.SET_CONTROLLER,\n (msg.sender == address(controllerOf[_projectId]) ||\n (isAllowedToSetFirstController[msg.sender] && controllerOf[_projectId] == address(0)))\n )\n {\n // The project must exist.\n if (projects.count() < _projectId) revert INVALID_PROJECT_ID_IN_DIRECTORY();\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Setting controller is allowed if called from the current controller, or if the project doesn't have a current controller, or if the project's funding cycle allows setting the controller. Revert otherwise.\n if (\n msg.sender != address(controllerOf[_projectId]) &&\n controllerOf[_projectId] != address(0) &&\n !_fundingCycle.global().allowSetController\n ) revert SET_CONTROLLER_NOT_ALLOWED();\n\n // Set the new controller.\n controllerOf[_projectId] = _controller;\n\n emit SetController(_projectId, _controller, msg.sender);\n }\n\n /** \n @notice \n Set a project's terminals.\n\n @dev\n Only a project owner, an operator, or its controller can set its terminals.\n\n @param _projectId The ID of the project having terminals set.\n @param _terminals The terminal to set.\n */\n function setTerminalsOf(uint256 _projectId, IJBPaymentTerminal[] calldata _terminals)\n external\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.SET_TERMINALS,\n msg.sender == address(controllerOf[_projectId])\n )\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Setting terminals must be allowed if not called from the current controller.\n if (\n msg.sender != address(controllerOf[_projectId]) && !_fundingCycle.global().allowSetTerminals\n ) revert SET_TERMINALS_NOT_ALLOWED();\n\n // Set the stored terminals for the project.\n _terminalsOf[_projectId] = _terminals;\n\n // Make sure duplicates were not added.\n if (_terminals.length > 1) {\n for (uint256 _i; _i < _terminals.length; ) {\n for (uint256 _j = _i + 1; _j < _terminals.length; ) {\n if (_terminals[_i] == _terminals[_j]) revert DUPLICATE_TERMINALS();\n\n unchecked {\n ++_j;\n }\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n emit SetTerminals(_projectId, _terminals, msg.sender);\n }\n\n /**\n @notice\n Project's can set which terminal should be their primary for a particular token.\n This is useful in case a project has several terminals connected for a particular token.\n\n @dev\n The terminal will be set as the primary terminal where ecosystem contracts should route tokens.\n\n @dev\n If setting a newly added terminal and the funding cycle doesn't allow new terminals, the caller must be the current controller.\n\n @param _projectId The ID of the project for which a primary token is being set.\n @param _token The token to set the primary terminal of.\n @param _terminal The terminal to make primary.\n */\n function setPrimaryTerminalOf(\n uint256 _projectId,\n address _token,\n IJBPaymentTerminal _terminal\n )\n external\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.SET_PRIMARY_TERMINAL)\n {\n // Can't set the primary terminal for a token if it doesn't accept the token.\n if (!_terminal.acceptsToken(_token, _projectId)) revert TOKEN_NOT_ACCEPTED();\n\n // Add the terminal to the project if it hasn't been already.\n _addTerminalIfNeeded(_projectId, _terminal);\n\n // Store the terminal as the primary for the particular token.\n _primaryTerminalOf[_projectId][_token] = _terminal;\n\n emit SetPrimaryTerminal(_projectId, _token, _terminal, msg.sender);\n }\n\n /** \n @notice\t\n Set a contract to the list of trusted addresses that can set a first controller for any project.\t\n\n @dev\n The owner can add addresses which are allowed to change projects' first controllers. \n These addresses are known and vetted controllers as well as contracts designed to launch new projects. \n A project can set its own controller without it being on the allow list.\n\n @dev\n If you would like an address/contract allowlisted, please reach out to the contract owner.\n\n @param _address The address to allow or revoke allowance from.\n @param _flag Whether allowance is being added or revoked.\n */\n function setIsAllowedToSetFirstController(address _address, bool _flag)\n external\n override\n onlyOwner\n {\n // Set the flag in the allowlist.\n isAllowedToSetFirstController[_address] = _flag;\n\n emit SetIsAllowedToSetFirstController(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Add a terminal to a project's list of terminals if it hasn't been already.\n\n @param _projectId The ID of the project having a terminal added.\n @param _terminal The terminal to add.\n */\n function _addTerminalIfNeeded(uint256 _projectId, IJBPaymentTerminal _terminal) private {\n // Check that the terminal has not already been added.\n if (isTerminalOf(_projectId, _terminal)) return;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Setting terminals must be allowed if not called from the current controller.\n if (\n msg.sender != address(controllerOf[_projectId]) && !_fundingCycle.global().allowSetTerminals\n ) revert SET_TERMINALS_NOT_ALLOWED();\n\n // Add the new terminal.\n _terminalsOf[_projectId].push(_terminal);\n\n emit AddTerminal(_projectId, _terminal, msg.sender);\n }\n}\n" }, "contracts/JBETHPaymentTerminal.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\nimport './libraries/JBSplitsGroups.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return address(this).balance;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n JBTokens.ETH,\n 18, // 18 decimals.\n JBCurrencies.ETH,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\nimport './libraries/JBSplitsGroups.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return address(this).balance;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n JBTokens.GAS_TOKEN,\n 18, // 18 decimals.\n JBCurrencies.GAS_CURRENCY,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n}\n" }, "contracts/JBERC20PaymentTerminal.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\n\n/** \n @notice \n Manages the inflows and outflows of an ERC-20 token.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\ncontract JBERC20PaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return IERC20(token).balanceOf(address(this));\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n IERC20Metadata _token,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n address(_token),\n _token.decimals(),\n _currency,\n _baseWeightCurrency,\n _payoutSplitsGroup,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from == address(this)\n ? IERC20(token).safeTransfer(_to, _amount)\n : IERC20(token).safeTransferFrom(_from, _to, _amount);\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal override {\n IERC20(token).safeApprove(_to, _amount);\n }\n}\n" }, "contracts/JBSingleTokenPaymentTerminalStore.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController.sol';\nimport './interfaces/IJBFundingCycleDataSource.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './structs/JBPayDelegateAllocation.sol';\nimport './structs/JBPayParamsData.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBSingleTokenPaymentTerminalStore is ReentrancyGuard, IJBSingleTokenPaymentTerminalStore {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n JBPayDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .payParams(_data);\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\n {\n // Keep a reference to the amount that should be added to the project's balance.\n uint256 _balanceDiff = _amount.value;\n\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\n if (delegateAllocations.length != 0) {\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0) {\n // Can't delegate more than was paid.\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\n\n // Decrement the total amount being added to the balance.\n _balanceDiff = _balanceDiff - _delegatedAmount;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Add the correct balance difference to the token balance of the project.\n if (_balanceDiff != 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _balanceDiff;\n }\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\n _projectId,\n fundingCycle.reservedRate()\n );\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow != 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\n {\n // Get a reference to the ballot state.\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\n\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n _state == JBBallotState.Active\n ? fundingCycle.ballotRedemptionRate()\n : fundingCycle.redemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\n fundingCycle.dataSource()\n ).redeemParams(_data);\n }\n } else {\n memo = _memo;\n }\n }\n\n // Keep a reference to the amount that should be subtracted from the project's balance.\n uint256 _balanceDiff = reclaimAmount;\n\n if (delegateAllocations.length != 0) {\n // Validate all delegated amounts.\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0)\n // Increment the total amount being subtracted from the balance.\n _balanceDiff = _balanceDiff + _delegatedAmount;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (_balanceDiff != 0) {\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n _balanceDiff;\n }\n }\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n unchecked {\n return\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i; _i < _terminals.length; ) {\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n unchecked {\n ++_i;\n }\n }\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.ETH\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.ETH, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController.sol';\nimport './interfaces/IJBFundingCycleDataSource.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './structs/JBPayDelegateAllocation.sol';\nimport './structs/JBPayParamsData.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBSingleTokenPaymentTerminalStore is ReentrancyGuard, IJBSingleTokenPaymentTerminalStore {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n JBPayDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .payParams(_data);\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\n {\n // Keep a reference to the amount that should be added to the project's balance.\n uint256 _balanceDiff = _amount.value;\n\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\n if (delegateAllocations.length != 0) {\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0) {\n // Can't delegate more than was paid.\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\n\n // Decrement the total amount being added to the balance.\n _balanceDiff = _balanceDiff - _delegatedAmount;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Add the correct balance difference to the token balance of the project.\n if (_balanceDiff != 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _balanceDiff;\n }\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\n _projectId,\n fundingCycle.reservedRate()\n );\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow != 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\n {\n // Get a reference to the ballot state.\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\n\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n _state == JBBallotState.Active\n ? fundingCycle.ballotRedemptionRate()\n : fundingCycle.redemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\n fundingCycle.dataSource()\n ).redeemParams(_data);\n }\n } else {\n memo = _memo;\n }\n }\n\n // Keep a reference to the amount that should be subtracted from the project's balance.\n uint256 _balanceDiff = reclaimAmount;\n\n if (delegateAllocations.length != 0) {\n // Validate all delegated amounts.\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0)\n // Increment the total amount being subtracted from the balance.\n _balanceDiff = _balanceDiff + _delegatedAmount;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (_balanceDiff != 0) {\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n _balanceDiff;\n }\n }\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n unchecked {\n return\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i; _i < _terminals.length; ) {\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n unchecked {\n ++_i;\n }\n }\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.GAS_CURRENCY\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.GAS_CURRENCY, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" }, "contracts/JBFundingCycleStore.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './abstract/JBControllerUtility.sol';\nimport './libraries/JBConstants.sol';\n\n/** \n @notice \n Manages funding cycle configurations and scheduling.\n\n @dev\n Adheres to -\n IJBFundingCycleStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBControllerUtility: Includes convenience functionality for checking if the message sender is the current controller of the project whose data is being manipulated.\n*/\ncontract JBFundingCycleStore is JBControllerUtility, IJBFundingCycleStore {\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_BALLOT();\n error INVALID_DISCOUNT_RATE();\n error INVALID_DURATION();\n error INVALID_TIMEFRAME();\n error INVALID_WEIGHT();\n error NO_SAME_BLOCK_RECONFIGURATION();\n\n //*********************************************************************//\n // --------------------- private stored properties ------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Stores the user defined properties of each funding cycle, packed into one storage slot.\n\n _projectId The ID of the project to get properties of.\n _configuration The funding cycle configuration to get properties of.\n */\n mapping(uint256 => mapping(uint256 => uint256)) private _packedUserPropertiesOf;\n\n /** \n @notice\n Stores the properties added by the mechanism to manage and schedule each funding cycle, packed into one storage slot.\n \n _projectId The ID of the project to get instrinsic properties of.\n _configuration The funding cycle configuration to get properties of.\n */\n mapping(uint256 => mapping(uint256 => uint256)) private _packedIntrinsicPropertiesOf;\n\n /** \n @notice\n Stores the metadata for each funding cycle configuration, packed into one storage slot.\n\n _projectId The ID of the project to get metadata of.\n _configuration The funding cycle configuration to get metadata of.\n */\n mapping(uint256 => mapping(uint256 => uint256)) private _metadataOf;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The latest funding cycle configuration for each project.\n\n _projectId The ID of the project to get the latest funding cycle configuration of.\n */\n mapping(uint256 => uint256) public override latestConfigurationOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice \n Get the funding cycle with the given configuration for the specified project.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n @param _configuration The configuration of the funding cycle to get.\n\n @return fundingCycle The funding cycle.\n */\n function get(uint256 _projectId, uint256 _configuration)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle)\n {\n return _getStructFor(_projectId, _configuration);\n }\n\n /**\n @notice \n The latest funding cycle to be configured for the specified project, and its current ballot state.\n\n @param _projectId The ID of the project to get the latest configured funding cycle of.\n\n @return fundingCycle The project's queued funding cycle.\n @return ballotState The state of the ballot for the reconfiguration.\n */\n function latestConfiguredOf(uint256 _projectId)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle, JBBallotState ballotState)\n {\n // Get a reference to the latest funding cycle configuration.\n uint256 _fundingCycleConfiguration = latestConfigurationOf[_projectId];\n\n // Resolve the funding cycle for the latest configuration.\n fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n // Resolve the ballot state.\n ballotState = _ballotStateOf(\n _projectId,\n fundingCycle.configuration,\n fundingCycle.start,\n fundingCycle.basedOn\n );\n }\n\n /**\n @notice \n The funding cycle that's next up for the specified project.\n\n @dev\n If a queued funding cycle of the project is not found, returns an empty funding cycle with all properties set to 0.\n\n @param _projectId The ID of the project to get the queued funding cycle of.\n\n @return fundingCycle The project's queued funding cycle.\n */\n function queuedOf(uint256 _projectId)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle)\n {\n // If the project does not have a funding cycle, return an empty struct.\n if (latestConfigurationOf[_projectId] == 0) return _getStructFor(0, 0);\n\n // Get a reference to the configuration of the standby funding cycle.\n uint256 _standbyFundingCycleConfiguration = _standbyOf(_projectId);\n\n // If it exists, return its funding cycle if it is approved.\n if (_standbyFundingCycleConfiguration > 0) {\n fundingCycle = _getStructFor(_projectId, _standbyFundingCycleConfiguration);\n\n if (_isApproved(_projectId, fundingCycle)) return fundingCycle;\n\n // Resolve the funding cycle for the latest configured funding cycle.\n fundingCycle = _getStructFor(_projectId, fundingCycle.basedOn);\n } else {\n // Resolve the funding cycle for the latest configured funding cycle.\n fundingCycle = _getStructFor(_projectId, latestConfigurationOf[_projectId]);\n\n // If the latest funding cycle starts in the future, it must start in the distant future\n // since its not in standby. In this case base the queued cycles on the base cycle.\n if (fundingCycle.start > block.timestamp)\n fundingCycle = _getStructFor(_projectId, fundingCycle.basedOn);\n }\n\n // There's no queued if the current has a duration of 0.\n if (fundingCycle.duration == 0) return _getStructFor(0, 0);\n\n // Check to see if this funding cycle's ballot is approved.\n // If so, return a funding cycle based on it.\n if (_isApproved(_projectId, fundingCycle)) return _mockFundingCycleBasedOn(fundingCycle, false);\n\n // Get the funding cycle of its base funding cycle, which carries the last approved configuration.\n fundingCycle = _getStructFor(_projectId, fundingCycle.basedOn);\n\n // There's no queued if the base, which must still be the current, has a duration of 0.\n if (fundingCycle.duration == 0) return _getStructFor(0, 0);\n\n // Return a mock of the next up funding cycle.\n return _mockFundingCycleBasedOn(fundingCycle, false);\n }\n\n /**\n @notice \n The funding cycle that is currently active for the specified project.\n\n @dev\n If a current funding cycle of the project is not found, returns an empty funding cycle with all properties set to 0.\n\n @param _projectId The ID of the project to get the current funding cycle of.\n\n @return fundingCycle The project's current funding cycle.\n */\n function currentOf(uint256 _projectId)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle)\n {\n // If the project does not have a funding cycle, return an empty struct.\n if (latestConfigurationOf[_projectId] == 0) return _getStructFor(0, 0);\n\n // Get a reference to the configuration of the eligible funding cycle.\n uint256 _fundingCycleConfiguration = _eligibleOf(_projectId);\n\n // Keep a reference to the eligible funding cycle.\n JBFundingCycle memory _fundingCycle;\n\n // If an eligible funding cycle exists...\n if (_fundingCycleConfiguration > 0) {\n // Resolve the funding cycle for the eligible configuration.\n _fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n // Check to see if this funding cycle's ballot is approved.\n // If so, return it.\n if (_isApproved(_projectId, _fundingCycle)) return _fundingCycle;\n\n // If it hasn't been approved, set the funding cycle configuration to be the configuration of the funding cycle that it's based on,\n // which carries the last approved configuration.\n _fundingCycleConfiguration = _fundingCycle.basedOn;\n } else {\n // No upcoming funding cycle found that is eligible to become active,\n // so use the last configuration.\n _fundingCycleConfiguration = latestConfigurationOf[_projectId];\n\n // Get the funding cycle for the latest ID.\n _fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n // If it's not approved or if it hasn't yet started, get a reference to the funding cycle that the latest is based on, which has the latest approved configuration.\n if (!_isApproved(_projectId, _fundingCycle) || block.timestamp < _fundingCycle.start)\n _fundingCycleConfiguration = _fundingCycle.basedOn;\n }\n\n // If there is not funding cycle to base the current one on, there can't be a current one.\n if (_fundingCycleConfiguration == 0) return _getStructFor(0, 0);\n\n // The funding cycle to base a current one on.\n _fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n // If the base has no duration, it's still the current one.\n if (_fundingCycle.duration == 0) return _fundingCycle;\n\n // Return a mock of the current funding cycle.\n return _mockFundingCycleBasedOn(_fundingCycle, true);\n }\n\n /** \n @notice \n The current ballot state of the project.\n\n @param _projectId The ID of the project to check the ballot state of.\n\n @return The project's current ballot's state.\n */\n function currentBallotStateOf(uint256 _projectId) external view override returns (JBBallotState) {\n // Get a reference to the latest funding cycle configuration.\n uint256 _fundingCycleConfiguration = latestConfigurationOf[_projectId];\n\n // Resolve the funding cycle for the latest configuration.\n JBFundingCycle memory _fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n return\n _ballotStateOf(\n _projectId,\n _fundingCycle.configuration,\n _fundingCycle.start,\n _fundingCycle.basedOn\n );\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _directory A contract storing directories of terminals and controllers for each project.\n */\n // solhint-disable-next-line no-empty-blocks\n constructor(IJBDirectory _directory) JBControllerUtility(_directory) {}\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice \n Configures the next eligible funding cycle for the specified project.\n\n @dev\n Only a project's current controller can configure its funding cycles.\n\n @param _projectId The ID of the project being configured.\n @param _data The funding cycle configuration data.\n @param _metadata Arbitrary extra data to associate with this funding cycle configuration that's not used within.\n @param _mustStartAtOrAfter The time before which the initialized funding cycle cannot start.\n\n @return The funding cycle that the configuration will take effect during.\n */\n function configureFor(\n uint256 _projectId,\n JBFundingCycleData calldata _data,\n uint256 _metadata,\n uint256 _mustStartAtOrAfter\n ) external override onlyController(_projectId) returns (JBFundingCycle memory) {\n // Duration must fit in a uint32.\n if (_data.duration > type(uint32).max) revert INVALID_DURATION();\n\n // Discount rate must be less than or equal to 100%.\n if (_data.discountRate > JBConstants.MAX_DISCOUNT_RATE) revert INVALID_DISCOUNT_RATE();\n\n // Weight must fit into a uint88.\n if (_data.weight > type(uint88).max) revert INVALID_WEIGHT();\n\n // If the start date is in the past, set it to be the current timestamp.\n if (_mustStartAtOrAfter < block.timestamp) _mustStartAtOrAfter = block.timestamp;\n\n // Make sure the min start date fits in a uint56, and that the start date of an upcoming cycle also starts within the max.\n if (_mustStartAtOrAfter + _data.duration > type(uint56).max) revert INVALID_TIMEFRAME();\n\n // Ballot should be a valid contract, supporting the correct interface\n if (_data.ballot != IJBFundingCycleBallot(address(0))) {\n address _ballot = address(_data.ballot);\n\n // No contract at the address ?\n if (_ballot.code.length == 0) revert INVALID_BALLOT();\n\n // Make sure the ballot supports the expected interface.\n try _data.ballot.supportsInterface(type(IJBFundingCycleBallot).interfaceId) returns (\n bool _supports\n ) {\n if (!_supports) revert INVALID_BALLOT(); // Contract exists at the address but with the wrong interface\n } catch {\n revert INVALID_BALLOT(); // No ERC165 support\n }\n }\n\n // The configuration timestamp is now.\n uint256 _configuration = block.timestamp;\n\n // Set up a reconfiguration by configuring intrinsic properties.\n _configureIntrinsicPropertiesFor(_projectId, _configuration, _data.weight, _mustStartAtOrAfter);\n\n // Efficiently stores a funding cycles provided user defined properties.\n // If all user config properties are zero, no need to store anything as the default value will have the same outcome.\n if (\n _data.ballot != IJBFundingCycleBallot(address(0)) ||\n _data.duration > 0 ||\n _data.discountRate > 0\n ) {\n // ballot in bits 0-159 bytes.\n uint256 packed = uint160(address(_data.ballot));\n\n // duration in bits 160-191 bytes.\n packed |= _data.duration << 160;\n\n // discountRate in bits 192-223 bytes.\n packed |= _data.discountRate << 192;\n\n // Set in storage.\n _packedUserPropertiesOf[_projectId][_configuration] = packed;\n }\n\n // Set the metadata if needed.\n if (_metadata > 0) _metadataOf[_projectId][_configuration] = _metadata;\n\n emit Configure(_configuration, _projectId, _data, _metadata, _mustStartAtOrAfter, msg.sender);\n\n // Return the funding cycle for the new configuration.\n return _getStructFor(_projectId, _configuration);\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice \n Updates the configurable funding cycle for this project if it exists, otherwise creates one.\n\n @param _projectId The ID of the project to find a configurable funding cycle for.\n @param _configuration The time at which the funding cycle was configured.\n @param _weight The weight to store in the configured funding cycle.\n @param _mustStartAtOrAfter The time before which the initialized funding cycle can't start.\n */\n function _configureIntrinsicPropertiesFor(\n uint256 _projectId,\n uint256 _configuration,\n uint256 _weight,\n uint256 _mustStartAtOrAfter\n ) private {\n // If there's not yet a funding cycle for the project, initialize one.\n if (latestConfigurationOf[_projectId] == 0)\n // Use an empty funding cycle as the base.\n return\n _initFor(_projectId, _getStructFor(0, 0), _configuration, _mustStartAtOrAfter, _weight);\n\n // Get the active funding cycle's configuration.\n uint256 _currentConfiguration = _eligibleOf(_projectId);\n\n // If an eligible funding cycle does not exist, get a reference to the latest funding cycle configuration for the project.\n if (_currentConfiguration == 0)\n // Get the latest funding cycle's configuration.\n _currentConfiguration = latestConfigurationOf[_projectId];\n\n // Get a reference to the funding cycle.\n JBFundingCycle memory _baseFundingCycle = _getStructFor(_projectId, _currentConfiguration);\n\n if (!_isApproved(_projectId, _baseFundingCycle) || block.timestamp < _baseFundingCycle.start)\n // If it hasn't been approved or hasn't yet started, set the ID to be the funding cycle it's based on,\n // which carries the latest approved configuration.\n _baseFundingCycle = _getStructFor(_projectId, _baseFundingCycle.basedOn);\n\n // The configuration can't be the same as the base configuration.\n if (_baseFundingCycle.configuration == _configuration) revert NO_SAME_BLOCK_RECONFIGURATION();\n\n // The time after the ballot of the provided funding cycle has expired.\n // If the provided funding cycle has no ballot, return the current timestamp.\n uint256 _timestampAfterBallot = _baseFundingCycle.ballot == IJBFundingCycleBallot(address(0))\n ? 0\n : _configuration + _baseFundingCycle.ballot.duration();\n\n _initFor(\n _projectId,\n _baseFundingCycle,\n _configuration,\n // Can only start after the ballot.\n _timestampAfterBallot > _mustStartAtOrAfter ? _timestampAfterBallot : _mustStartAtOrAfter,\n _weight\n );\n }\n\n /**\n @notice \n Initializes a funding cycle with the specified properties.\n\n @param _projectId The ID of the project to which the funding cycle being initialized belongs.\n @param _baseFundingCycle The funding cycle to base the initialized one on.\n @param _configuration The configuration of the funding cycle being initialized.\n @param _mustStartAtOrAfter The time before which the initialized funding cycle cannot start.\n @param _weight The weight to give the newly initialized funding cycle.\n */\n function _initFor(\n uint256 _projectId,\n JBFundingCycle memory _baseFundingCycle,\n uint256 _configuration,\n uint256 _mustStartAtOrAfter,\n uint256 _weight\n ) private {\n // If there is no base, initialize a first cycle.\n if (_baseFundingCycle.number == 0) {\n // The first number is 1.\n uint256 _number = 1;\n\n // Set fresh intrinsic properties.\n _packAndStoreIntrinsicPropertiesOf(\n _configuration,\n _projectId,\n _number,\n _weight,\n _baseFundingCycle.configuration,\n _mustStartAtOrAfter\n );\n } else {\n // Derive the correct next start time from the base.\n uint256 _start = _deriveStartFrom(_baseFundingCycle, _mustStartAtOrAfter);\n\n // A weight of 1 is treated as a weight of 0.\n // This is to allow a weight of 0 (default) to represent inheriting the discounted weight of the previous funding cycle.\n _weight = _weight > 0\n ? (_weight == 1 ? 0 : _weight)\n : _deriveWeightFrom(_baseFundingCycle, _start);\n\n // Derive the correct number.\n uint256 _number = _deriveNumberFrom(_baseFundingCycle, _start);\n\n // Update the intrinsic properties.\n _packAndStoreIntrinsicPropertiesOf(\n _configuration,\n _projectId,\n _number,\n _weight,\n _baseFundingCycle.configuration,\n _start\n );\n }\n\n // Set the project's latest funding cycle configuration.\n latestConfigurationOf[_projectId] = _configuration;\n\n emit Init(_configuration, _projectId, _baseFundingCycle.configuration);\n }\n\n /**\n @notice \n Efficiently stores a funding cycle's provided intrinsic properties.\n\n @param _configuration The configuration of the funding cycle to pack and store.\n @param _projectId The ID of the project to which the funding cycle belongs.\n @param _number The number of the funding cycle.\n @param _weight The weight of the funding cycle.\n @param _basedOn The configuration of the base funding cycle.\n @param _start The start time of this funding cycle.\n */\n function _packAndStoreIntrinsicPropertiesOf(\n uint256 _configuration,\n uint256 _projectId,\n uint256 _number,\n uint256 _weight,\n uint256 _basedOn,\n uint256 _start\n ) private {\n // weight in bits 0-87.\n uint256 packed = _weight;\n\n // basedOn in bits 88-143.\n packed |= _basedOn << 88;\n\n // start in bits 144-199.\n packed |= _start << 144;\n\n // number in bits 200-255.\n packed |= _number << 200;\n\n // Store the packed value.\n _packedIntrinsicPropertiesOf[_projectId][_configuration] = packed;\n }\n\n /**\n @notice \n The project's stored funding cycle that hasn't yet started and should be used next, if one exists.\n\n @dev\n A value of 0 is returned if no funding cycle was found.\n\n @dev\n Assumes the project has a latest configuration.\n \n @param _projectId The ID of a project to look through for a standby cycle.\n\n @return configuration The configuration of the standby funding cycle if one exists, or 0 if one doesn't exist.\n */\n function _standbyOf(uint256 _projectId) private view returns (uint256 configuration) {\n // Get a reference to the project's latest funding cycle.\n configuration = latestConfigurationOf[_projectId];\n\n // Get the necessary properties for the latest funding cycle.\n JBFundingCycle memory _fundingCycle = _getStructFor(_projectId, configuration);\n\n // There is no upcoming funding cycle if the latest funding cycle has already started.\n if (block.timestamp >= _fundingCycle.start) return 0;\n\n // If this is the first funding cycle, it is queued.\n if (_fundingCycle.number == 1) return configuration;\n\n // Get the necessary properties for the base funding cycle.\n JBFundingCycle memory _baseFundingCycle = _getStructFor(_projectId, _fundingCycle.basedOn);\n\n // If the latest configuration doesn't start until after another base cycle, return 0.\n if (\n _baseFundingCycle.duration > 0 &&\n block.timestamp < _fundingCycle.start - _baseFundingCycle.duration\n ) return 0;\n }\n\n /**\n @notice \n The project's stored funding cycle that has started and hasn't yet expired.\n \n @dev\n A value of 0 is returned if no funding cycle was found.\n\n @dev\n Assumes the project has a latest configuration.\n\n @param _projectId The ID of the project to look through.\n\n @return configuration The configuration of an eligible funding cycle if one exists, or 0 if one doesn't exist.\n */\n function _eligibleOf(uint256 _projectId) private view returns (uint256 configuration) {\n // Get a reference to the project's latest funding cycle.\n configuration = latestConfigurationOf[_projectId];\n\n // Get the latest funding cycle.\n JBFundingCycle memory _fundingCycle = _getStructFor(_projectId, configuration);\n\n // If the latest is expired, return an empty funding cycle.\n // A duration of 0 cannot be expired.\n if (\n _fundingCycle.duration > 0 && block.timestamp >= _fundingCycle.start + _fundingCycle.duration\n ) return 0;\n\n // Return the funding cycle's configuration if it has started.\n if (block.timestamp >= _fundingCycle.start) return _fundingCycle.configuration;\n\n // Get a reference to the cycle's base configuration.\n JBFundingCycle memory _baseFundingCycle = _getStructFor(_projectId, _fundingCycle.basedOn);\n\n // If the base cycle isn't eligible, the project has no eligible cycle.\n // A duration of 0 is always eligible.\n if (\n _baseFundingCycle.duration > 0 &&\n block.timestamp >= _baseFundingCycle.start + _baseFundingCycle.duration\n ) return 0;\n\n // Return the configuration that the latest funding cycle is based on.\n configuration = _fundingCycle.basedOn;\n }\n\n /** \n @notice \n A view of the funding cycle that would be created based on the provided one if the project doesn't make a reconfiguration.\n\n @dev\n Returns an empty funding cycle if there can't be a mock funding cycle based on the provided one.\n\n @dev\n Assumes a funding cycle with a duration of 0 will never be asked to be the base of a mock.\n\n @param _baseFundingCycle The funding cycle that the resulting funding cycle should follow.\n @param _allowMidCycle A flag indicating if the mocked funding cycle is allowed to already be mid cycle.\n\n @return A mock of what the next funding cycle will be.\n */\n function _mockFundingCycleBasedOn(JBFundingCycle memory _baseFundingCycle, bool _allowMidCycle)\n private\n view\n returns (JBFundingCycle memory)\n {\n // Get the distance of the current time to the start of the next possible funding cycle.\n // If the returned mock cycle must not yet have started, the start time of the mock must be in the future.\n uint256 _mustStartAtOrAfter = !_allowMidCycle\n ? block.timestamp + 1\n : block.timestamp - _baseFundingCycle.duration + 1;\n\n // Derive what the start time should be.\n uint256 _start = _deriveStartFrom(_baseFundingCycle, _mustStartAtOrAfter);\n\n // Derive what the number should be.\n uint256 _number = _deriveNumberFrom(_baseFundingCycle, _start);\n\n return\n JBFundingCycle(\n _number,\n _baseFundingCycle.configuration,\n _baseFundingCycle.basedOn,\n _start,\n _baseFundingCycle.duration,\n _deriveWeightFrom(_baseFundingCycle, _start),\n _baseFundingCycle.discountRate,\n _baseFundingCycle.ballot,\n _baseFundingCycle.metadata\n );\n }\n\n /** \n @notice \n The date that is the nearest multiple of the specified funding cycle's duration from its end.\n\n @param _baseFundingCycle The funding cycle to base the calculation on.\n @param _mustStartAtOrAfter A date that the derived start must be on or come after.\n\n @return start The next start time.\n */\n function _deriveStartFrom(JBFundingCycle memory _baseFundingCycle, uint256 _mustStartAtOrAfter)\n private\n pure\n returns (uint256 start)\n {\n // A subsequent cycle to one with a duration of 0 should start as soon as possible.\n if (_baseFundingCycle.duration == 0) return _mustStartAtOrAfter;\n\n // The time when the funding cycle immediately after the specified funding cycle starts.\n uint256 _nextImmediateStart = _baseFundingCycle.start + _baseFundingCycle.duration;\n\n // If the next immediate start is now or in the future, return it.\n if (_nextImmediateStart >= _mustStartAtOrAfter) return _nextImmediateStart;\n\n // The amount of seconds since the `_mustStartAtOrAfter` time which results in a start time that might satisfy the specified constraints.\n uint256 _timeFromImmediateStartMultiple = (_mustStartAtOrAfter - _nextImmediateStart) %\n _baseFundingCycle.duration;\n\n // A reference to the first possible start timestamp.\n start = _mustStartAtOrAfter - _timeFromImmediateStartMultiple;\n\n // Add increments of duration as necessary to satisfy the threshold.\n while (_mustStartAtOrAfter > start) start = start + _baseFundingCycle.duration;\n }\n\n /** \n @notice \n The accumulated weight change since the specified funding cycle.\n\n @param _baseFundingCycle The funding cycle to base the calculation on.\n @param _start The start time of the funding cycle to derive a number for.\n\n @return weight The derived weight, as a fixed point number with 18 decimals.\n */\n function _deriveWeightFrom(JBFundingCycle memory _baseFundingCycle, uint256 _start)\n private\n pure\n returns (uint256 weight)\n {\n // A subsequent cycle to one with a duration of 0 should have the next possible weight.\n if (_baseFundingCycle.duration == 0)\n return\n PRBMath.mulDiv(\n _baseFundingCycle.weight,\n JBConstants.MAX_DISCOUNT_RATE - _baseFundingCycle.discountRate,\n JBConstants.MAX_DISCOUNT_RATE\n );\n\n // The weight should be based off the base funding cycle's weight.\n weight = _baseFundingCycle.weight;\n\n // If the discount is 0, the weight doesn't change.\n if (_baseFundingCycle.discountRate == 0) return weight;\n\n // The difference between the start of the base funding cycle and the proposed start.\n uint256 _startDistance = _start - _baseFundingCycle.start;\n\n // Apply the base funding cycle's discount rate for each cycle that has passed.\n uint256 _discountMultiple;\n unchecked {\n _discountMultiple = _startDistance / _baseFundingCycle.duration; // Non-null duration is excluded above\n }\n\n for (uint256 _i; _i < _discountMultiple; ) {\n // The number of times to apply the discount rate.\n // Base the new weight on the specified funding cycle's weight.\n weight = PRBMath.mulDiv(\n weight,\n JBConstants.MAX_DISCOUNT_RATE - _baseFundingCycle.discountRate,\n JBConstants.MAX_DISCOUNT_RATE\n );\n\n // The calculation doesn't need to continue if the weight is 0.\n if (weight == 0) break;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /** \n @notice \n The number of the next funding cycle given the specified funding cycle.\n\n @param _baseFundingCycle The funding cycle to base the calculation on.\n @param _start The start time of the funding cycle to derive a number for.\n\n @return The funding cycle number.\n */\n function _deriveNumberFrom(JBFundingCycle memory _baseFundingCycle, uint256 _start)\n private\n pure\n returns (uint256)\n {\n // A subsequent cycle to one with a duration of 0 should be the next number.\n if (_baseFundingCycle.duration == 0) return _baseFundingCycle.number + 1;\n\n // The difference between the start of the base funding cycle and the proposed start.\n uint256 _startDistance = _start - _baseFundingCycle.start;\n\n // Find the number of base cycles that fit in the start distance.\n return _baseFundingCycle.number + (_startDistance / _baseFundingCycle.duration);\n }\n\n /** \n @notice \n Checks to see if the provided funding cycle is approved according to the correct ballot.\n\n @param _projectId The ID of the project to which the funding cycle belongs. \n @param _fundingCycle The funding cycle to get an approval flag for.\n\n @return The approval flag.\n */\n function _isApproved(uint256 _projectId, JBFundingCycle memory _fundingCycle)\n private\n view\n returns (bool)\n {\n return\n _ballotStateOf(\n _projectId,\n _fundingCycle.configuration,\n _fundingCycle.start,\n _fundingCycle.basedOn\n ) == JBBallotState.Approved;\n }\n\n /**\n @notice \n A project's latest funding cycle configuration approval status.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n @param _configuration The funding cycle configuration to get the ballot state of.\n @param _start The start time of the funding cycle configuration to get the ballot state of.\n @param _ballotFundingCycleConfiguration The configuration of the funding cycle which is configured with the ballot that should be used.\n\n @return The ballot state of the project.\n */\n function _ballotStateOf(\n uint256 _projectId,\n uint256 _configuration,\n uint256 _start,\n uint256 _ballotFundingCycleConfiguration\n ) private view returns (JBBallotState) {\n // If there is no ballot funding cycle, implicitly approve.\n if (_ballotFundingCycleConfiguration == 0) return JBBallotState.Approved;\n\n // Get the ballot funding cycle.\n JBFundingCycle memory _ballotFundingCycle = _getStructFor(\n _projectId,\n _ballotFundingCycleConfiguration\n );\n\n // If there is no ballot, the ID is auto approved.\n if (_ballotFundingCycle.ballot == IJBFundingCycleBallot(address(0)))\n return JBBallotState.Approved;\n\n // Return the ballot's state\n return _ballotFundingCycle.ballot.stateOf(_projectId, _configuration, _start);\n }\n\n /**\n @notice \n Unpack a funding cycle's packed stored values into an easy-to-work-with funding cycle struct.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n @param _configuration The funding cycle configuration to get the full struct for.\n\n @return fundingCycle A funding cycle struct.\n */\n function _getStructFor(uint256 _projectId, uint256 _configuration)\n private\n view\n returns (JBFundingCycle memory fundingCycle)\n {\n // Return an empty funding cycle if the configuration specified is 0.\n if (_configuration == 0) return fundingCycle;\n\n fundingCycle.configuration = _configuration;\n\n uint256 _packedIntrinsicProperties = _packedIntrinsicPropertiesOf[_projectId][_configuration];\n\n // weight in bits 0-87 bits.\n fundingCycle.weight = uint256(uint88(_packedIntrinsicProperties));\n // basedOn in bits 88-143 bits.\n fundingCycle.basedOn = uint256(uint56(_packedIntrinsicProperties >> 88));\n // start in bits 144-199 bits.\n fundingCycle.start = uint256(uint56(_packedIntrinsicProperties >> 144));\n // number in bits 200-255 bits.\n fundingCycle.number = uint256(uint56(_packedIntrinsicProperties >> 200));\n\n uint256 _packedUserProperties = _packedUserPropertiesOf[_projectId][_configuration];\n\n // ballot in bits 0-159 bits.\n fundingCycle.ballot = IJBFundingCycleBallot(address(uint160(_packedUserProperties)));\n // duration in bits 160-191 bits.\n fundingCycle.duration = uint256(uint32(_packedUserProperties >> 160));\n // discountRate in bits 192-223 bits.\n fundingCycle.discountRate = uint256(uint32(_packedUserProperties >> 192));\n\n fundingCycle.metadata = _metadataOf[_projectId][_configuration];\n }\n}\n" @@ -194,7 +194,7 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './../interfaces/IJBSplitAllocator.sol';\n\n/** \n @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.\n @member preferAddToBalance A flag indicating if a distribution to a project should prefer triggering it's addToBalance function instead of its pay function.\n @member percent The percent of the whole group that this split occupies. This number is out of `JBConstants.SPLITS_TOTAL_PERCENT`.\n @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.\n @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.\n @member lockedUntil Specifies if the split should be unchangeable until the specified time, with the exception of extending the locked period.\n @member allocator If an allocator is specified, funds will be sent to the allocator contract along with all properties of this split.\n*/\nstruct JBSplit {\n bool preferClaimed;\n bool preferAddToBalance;\n uint256 percent;\n uint256 projectId;\n address payable beneficiary;\n uint256 lockedUntil;\n IJBSplitAllocator allocator;\n}\n" }, "contracts/system_tests/helpers/AccessJBLib.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.6;\n\nimport '../../libraries/JBCurrencies.sol';\nimport '../../libraries/JBConstants.sol';\nimport '../../libraries/JBTokens.sol';\n\ncontract AccessJBLib {\n function ETH() external pure returns (uint256) {\n return JBCurrencies.ETH;\n }\n\n function USD() external pure returns (uint256) {\n return JBCurrencies.USD;\n }\n\n function ETHToken() external pure returns (address) {\n return JBTokens.ETH;\n }\n\n function MAX_FEE() external pure returns (uint256) {\n return JBConstants.MAX_FEE;\n }\n\n function MAX_RESERVED_RATE() external pure returns (uint256) {\n return JBConstants.MAX_RESERVED_RATE;\n }\n\n function MAX_REDEMPTION_RATE() external pure returns (uint256) {\n return JBConstants.MAX_REDEMPTION_RATE;\n }\n\n function MAX_DISCOUNT_RATE() external pure returns (uint256) {\n return JBConstants.MAX_DISCOUNT_RATE;\n }\n\n function SPLITS_TOTAL_PERCENT() external pure returns (uint256) {\n return JBConstants.SPLITS_TOTAL_PERCENT;\n }\n\n function MAX_FEE_DISCOUNT() external pure returns (uint256) {\n return JBConstants.MAX_FEE_DISCOUNT;\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.6;\n\nimport '../../libraries/JBCurrencies.sol';\nimport '../../libraries/JBConstants.sol';\nimport '../../libraries/JBTokens.sol';\n\ncontract AccessJBLib {\n function ETH() external pure returns (uint256) {\n return JBCurrencies.GAS_CURRENCY;\n }\n\n function USD() external pure returns (uint256) {\n return JBCurrencies.USD;\n }\n\n function ETHToken() external pure returns (address) {\n return JBTokens.GAS_TOKEN;\n }\n\n function MAX_FEE() external pure returns (uint256) {\n return JBConstants.MAX_FEE;\n }\n\n function MAX_RESERVED_RATE() external pure returns (uint256) {\n return JBConstants.MAX_RESERVED_RATE;\n }\n\n function MAX_REDEMPTION_RATE() external pure returns (uint256) {\n return JBConstants.MAX_REDEMPTION_RATE;\n }\n\n function MAX_DISCOUNT_RATE() external pure returns (uint256) {\n return JBConstants.MAX_DISCOUNT_RATE;\n }\n\n function SPLITS_TOTAL_PERCENT() external pure returns (uint256) {\n return JBConstants.SPLITS_TOTAL_PERCENT;\n }\n\n function MAX_FEE_DISCOUNT() external pure returns (uint256) {\n return JBConstants.MAX_FEE_DISCOUNT;\n }\n}\n" }, "@paulrberg/contracts/math/PRBMath.sol": { "content": "// SPDX-License-Identifier: Unlicense\npragma solidity >=0.8.4;\n\nimport \"prb-math/contracts/PRBMath.sol\";\n" @@ -227,7 +227,7 @@ "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" }, "contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBPayDelegateAllocation.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal is\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n IJBPayoutRedemptionPaymentTerminal\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n @dev\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.ETH)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.ETH, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance.\n */\n function _balance() internal view virtual returns (uint256);\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.ETH) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual {\n _from; // Prevents unused var compiler and natspec complaints.\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\n {\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\n\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _forwardedAmount,\n _beneficiary,\n _memo,\n _metadata\n );\n\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\n\n emit DelegateDidRedeem(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n }\n\n // Take the fee.\n _fee = _feeEligibleDistributionAmount != 0\n ? _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n )\n : 0;\n\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\n if (_leftoverDistributionAmount != 0) {\n // Subtract the fee from the net leftover amount.\n netLeftoverDistributionAmount =\n _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n\n // Transfer the amount to the project owner.\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n // The total percentage available to split\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = _split.percent == leftoverPercentage\n ? leftoverAmount\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\n\n // Decrement the leftover percentage.\n leftoverPercentage -= _split.percent;\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount;\n\n if (_payoutAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\n isFeelessAddress[address(_split.allocator)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n _netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n // If this terminal's token is ETH, send it in msg.value.\n _split.allocator.allocate{value: token == JBTokens.ETH ? _netPayoutAmount : 0}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // Save gas if this contract is being used as the terminal.\n if (_terminal == this) {\n // This distribution does not incur a fee.\n _netPayoutAmount = _payoutAmount;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\n else\n _pay(\n _netPayoutAmount,\n address(this),\n _split.projectId,\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n } else {\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_terminal)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _netPayoutAmount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _terminal.addToBalanceOf{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n '',\n _projectMetadata\n );\n else\n _terminal.pay{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n }\n } else {\n // Keep a reference to the beneficiary.\n address payable _beneficiary = _split.beneficiary != address(0)\n ? _split.beneficiary\n : payable(msg.sender);\n\n // If there's a full discount, this distribution is not eligible for a fee.\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(address(this), _beneficiary, _netPayoutAmount);\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n */\n function _processFee(uint256 _amount, address _beneficiary) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\n\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\n if (_terminal == this)\n _pay(\n _amount,\n address(this),\n _FEE_BENEFICIARY_PROJECT_ID,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the local pay call.\n else {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _amount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _amount : 0;\n\n // Send the payment.\n _terminal.pay{value: _payableValue}(\n _FEE_BENEFICIARY_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the external pay call of the correct terminal.\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\n {\n JBPayDelegateAllocation[] memory _delegateAllocations;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n _forwardedAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n // Get a reference to the number of delegates to allocate to.\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\n\n emit DelegateDidPay(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n unchecked {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\n IJBPaymentTerminal(address(0))\n ) return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge != IJBFeeGauge(address(0)))\n // If the guage reverts, keep the discount at 0.\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n // If the fee discount is greater than the max, we ignore the return value\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\n } catch {\n return 0;\n }\n\n return 0;\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBPayDelegateAllocation.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal is\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n IJBPayoutRedemptionPaymentTerminal\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n @dev\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.GAS_CURRENCY)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.GAS_CURRENCY, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance.\n */\n function _balance() internal view virtual returns (uint256);\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.GAS_TOKEN) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual {\n _from; // Prevents unused var compiler and natspec complaints.\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\n {\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\n\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _forwardedAmount,\n _beneficiary,\n _memo,\n _metadata\n );\n\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\n\n emit DelegateDidRedeem(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n }\n\n // Take the fee.\n _fee = _feeEligibleDistributionAmount != 0\n ? _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n )\n : 0;\n\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\n if (_leftoverDistributionAmount != 0) {\n // Subtract the fee from the net leftover amount.\n netLeftoverDistributionAmount =\n _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n\n // Transfer the amount to the project owner.\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n // The total percentage available to split\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = _split.percent == leftoverPercentage\n ? leftoverAmount\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\n\n // Decrement the leftover percentage.\n leftoverPercentage -= _split.percent;\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount;\n\n if (_payoutAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\n isFeelessAddress[address(_split.allocator)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n _netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n // If this terminal's token is ETH, send it in msg.value.\n _split.allocator.allocate{value: token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // Save gas if this contract is being used as the terminal.\n if (_terminal == this) {\n // This distribution does not incur a fee.\n _netPayoutAmount = _payoutAmount;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\n else\n _pay(\n _netPayoutAmount,\n address(this),\n _split.projectId,\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n } else {\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_terminal)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _terminal.addToBalanceOf{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n '',\n _projectMetadata\n );\n else\n _terminal.pay{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n }\n } else {\n // Keep a reference to the beneficiary.\n address payable _beneficiary = _split.beneficiary != address(0)\n ? _split.beneficiary\n : payable(msg.sender);\n\n // If there's a full discount, this distribution is not eligible for a fee.\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(address(this), _beneficiary, _netPayoutAmount);\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n */\n function _processFee(uint256 _amount, address _beneficiary) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\n\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\n if (_terminal == this)\n _pay(\n _amount,\n address(this),\n _FEE_BENEFICIARY_PROJECT_ID,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the local pay call.\n else {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _amount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send the payment.\n _terminal.pay{value: _payableValue}(\n _FEE_BENEFICIARY_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the external pay call of the correct terminal.\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\n {\n JBPayDelegateAllocation[] memory _delegateAllocations;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n _forwardedAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n // Get a reference to the number of delegates to allocate to.\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\n\n emit DelegateDidPay(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n unchecked {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\n IJBPaymentTerminal(address(0))\n ) return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge != IJBFeeGauge(address(0)))\n // If the guage reverts, keep the discount at 0.\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n // If the fee discount is greater than the max, we ignore the return value\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\n } catch {\n return 0;\n }\n\n return 0;\n }\n}\n" }, "contracts/interfaces/IJBPayoutRedemptionPaymentTerminal.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './../structs/JBFee.sol';\nimport './IJBAllowanceTerminal.sol';\nimport './IJBDirectory.sol';\nimport './IJBFeeGauge.sol';\nimport './IJBPayDelegate.sol';\nimport './IJBPaymentTerminal.sol';\nimport './IJBPayoutTerminal.sol';\nimport './IJBPrices.sol';\nimport './IJBProjects.sol';\nimport './IJBRedemptionDelegate.sol';\nimport './IJBRedemptionTerminal.sol';\nimport './IJBSingleTokenPaymentTerminalStore.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBPayoutRedemptionPaymentTerminal is\n IJBPaymentTerminal,\n IJBPayoutTerminal,\n IJBAllowanceTerminal,\n IJBRedemptionTerminal\n{\n event AddToBalance(\n uint256 indexed projectId,\n uint256 amount,\n uint256 refundedFees,\n string memo,\n bytes metadata,\n address caller\n );\n\n event Migrate(\n uint256 indexed projectId,\n IJBPaymentTerminal indexed to,\n uint256 amount,\n address caller\n );\n\n event DistributePayouts(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address beneficiary,\n uint256 amount,\n uint256 distributedAmount,\n uint256 fee,\n uint256 beneficiaryDistributionAmount,\n string memo,\n address caller\n );\n\n event UseAllowance(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address beneficiary,\n uint256 amount,\n uint256 distributedAmount,\n uint256 netDistributedamount,\n string memo,\n address caller\n );\n\n event HoldFee(\n uint256 indexed projectId,\n uint256 indexed amount,\n uint256 indexed fee,\n uint256 feeDiscount,\n address beneficiary,\n address caller\n );\n\n event ProcessFee(\n uint256 indexed projectId,\n uint256 indexed amount,\n bool indexed wasHeld,\n address beneficiary,\n address caller\n );\n\n event RefundHeldFees(\n uint256 indexed projectId,\n uint256 indexed amount,\n uint256 indexed refundedFees,\n uint256 leftoverAmount,\n address caller\n );\n\n event Pay(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address payer,\n address beneficiary,\n uint256 amount,\n uint256 beneficiaryTokenCount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DelegateDidPay(\n IJBPayDelegate indexed delegate,\n JBDidPayData data,\n uint256 delegatedAmount,\n address caller\n );\n\n event RedeemTokens(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address holder,\n address beneficiary,\n uint256 tokenCount,\n uint256 reclaimedAmount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DelegateDidRedeem(\n IJBRedemptionDelegate indexed delegate,\n JBDidRedeemData data,\n uint256 delegatedAmount,\n address caller\n );\n\n event DistributeToPayoutSplit(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n JBSplit split,\n uint256 amount,\n address caller\n );\n\n event SetFee(uint256 fee, address caller);\n\n event SetFeeGauge(IJBFeeGauge indexed feeGauge, address caller);\n\n event SetFeelessAddress(address indexed addrs, bool indexed flag, address caller);\n\n function projects() external view returns (IJBProjects);\n\n function splitsStore() external view returns (IJBSplitsStore);\n\n function directory() external view returns (IJBDirectory);\n\n function prices() external view returns (IJBPrices);\n\n function store() external view returns (IJBSingleTokenPaymentTerminalStore);\n\n function baseWeightCurrency() external view returns (uint256);\n\n function payoutSplitsGroup() external view returns (uint256);\n\n function heldFeesOf(uint256 _projectId) external view returns (JBFee[] memory);\n\n function fee() external view returns (uint256);\n\n function feeGauge() external view returns (IJBFeeGauge);\n\n function isFeelessAddress(address _contract) external view returns (bool);\n\n function migrate(uint256 _projectId, IJBPaymentTerminal _to) external returns (uint256 balance);\n\n function processFees(uint256 _projectId) external;\n\n function setFee(uint256 _fee) external;\n\n function setFeeGauge(IJBFeeGauge _feeGauge) external;\n\n function setFeelessAddress(address _contract, bool _flag) external;\n}\n" @@ -337,20 +337,20 @@ "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface AggregatorV3Interface {\n\n function decimals()\n external\n view\n returns (\n uint8\n );\n\n function description()\n external\n view\n returns (\n string memory\n );\n\n function version()\n external\n view\n returns (\n uint256\n );\n\n // getRoundData and latestRoundData should both raise \"No data present\"\n // if they do not have data to report, instead of returning unset values\n // which could be misinterpreted as actual reported values.\n function getRoundData(\n uint80 _roundId\n )\n external\n view\n returns (\n uint80 roundId,\n int256 answer,\n uint256 startedAt,\n uint256 updatedAt,\n uint80 answeredInRound\n );\n\n function latestRoundData()\n external\n view\n returns (\n uint80 roundId,\n int256 answer,\n uint256 startedAt,\n uint256 updatedAt,\n uint80 answeredInRound\n );\n\n}\n" }, - "contracts/JBETHERC20SplitsPayer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBSplitsPayer.sol';\nimport './interfaces/IJBSplitsStore.sol';\nimport './libraries/JBConstants.sol';\nimport './JBETHERC20ProjectPayer.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\n\n @dev\n Adheres to -\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBETHERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBETHERC20SplitsPayer is JBETHERC20ProjectPayer, ReentrancyGuard, IJBSplitsPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The ID of project for which the default splits are stored. \n */\n uint256 public override defaultSplitsProjectId;\n\n /**\n @notice\n The domain within which the default splits are stored. \n */\n uint256 public override defaultSplitsDomain;\n\n /**\n @notice\n The group within which the default splits are stored. \n */\n uint256 public override defaultSplitsGroup;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBETHERC20ProjectPayer, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n )\n JBETHERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _preferAddToBalance,\n _splitsStore.directory(),\n _owner\n )\n {\n defaultSplitsProjectId = _defaultSplitsProjectId;\n defaultSplitsDomain = _defaultSplitsDomain;\n defaultSplitsGroup = _defaultSplitsGroup;\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default split group using the stored default properties.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override nonReentrant {\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n JBTokens.ETH,\n address(this).balance,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // If there is no leftover amount, nothing left to pay.\n if (_leftoverAmount == 0) return;\n\n // If there's a default project ID, try to pay it.\n if (defaultProjectId != 0)\n if (defaultPreferAddToBalance)\n // Pay the project by adding to its balance if prefered.\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.ETH,\n _leftoverAmount,\n 18, // decimals.\n defaultMemo,\n defaultMetadata\n );\n // Otherwise, issue a payment to the project.\n else\n _pay(\n defaultProjectId,\n JBTokens.ETH,\n _leftoverAmount,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n 0, // min returned tokens.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else\n Address.sendValue(\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(tx.origin),\n _leftoverAmount\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the splits in the splits store that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n @param _groupedSplits The split groups to set.\n */\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n JBGroupedSplits[] memory _groupedSplits\n ) external virtual override onlyOwner {\n // Set the splits in the store.\n splitsStore.set(_projectId, _domain, _groupedSplits);\n\n // Set the splits reference.\n setDefaultSplitsReference(_projectId, _domain, _group);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the location of the splits that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n */\n function setDefaultSplitsReference(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) public virtual override onlyOwner {\n // Set the default splits project ID if it's changing.\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\n\n // Set the default splits domain if it's changing.\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\n\n // Set the default splits group if it's changing.\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\n\n emit SetDefaultSplitsReference(_projectId, _domain, _group, msg.sender);\n }\n\n /** \n @notice \n Make a payment to the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Pay any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to pay it.\n if (_projectId != 0) {\n _pay(\n _projectId,\n _token,\n _leftoverAmount,\n _decimals,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? payable(_beneficiary) : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit Pay(\n _projectId,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event. \n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Distribute any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to add to its balance.\n if (_projectId != 0)\n // Add to the project's balance.\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\n\n // Otherwise, send a payment to the beneficiary.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit AddToBalance(\n _projectId,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splitsProjectId The ID of the project to which the splits belong.\n @param _splitsDomain The splits domain to which the group belongs.\n @param _splitsGroup The splits group to pay.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payToSplits(\n uint256 _splitsProjectId,\n uint256 _splitsDomain,\n uint256 _splitsGroup,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Pay the splits.\n leftoverAmount = _payTo(\n splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup),\n _token,\n _amount,\n _decimals,\n _defaultBeneficiary\n );\n emit DistributeToSplitGroup(_splitsProjectId, _splitsDomain, _splitsGroup, msg.sender);\n }\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splits The splits.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payTo(\n JBSplit[] memory _splits,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Set the leftover amount to the initial balance.\n leftoverAmount = _amount;\n\n // Settle between all splits.\n for (uint256 i; i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[i];\n\n // The amount to send towards the split.\n uint256 _splitAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n if (_splitAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n _token,\n _splitAmount,\n _decimals,\n defaultProjectId,\n 0,\n _split\n );\n\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\n if (_token != JBTokens.ETH)\n IERC20(_token).safeApprove(address(_split.allocator), _splitAmount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _splitAmount : 0;\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n if (_split.preferAddToBalance)\n _addToBalanceOf(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n 0,\n _split.preferClaimed,\n defaultMemo,\n defaultMetadata\n );\n } else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : payable(_defaultBeneficiary),\n _splitAmount\n );\n // Or, transfer the ERC20.\n else {\n IERC20(_token).safeTransfer(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n _splitAmount\n );\n }\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _splitAmount;\n }\n\n emit DistributeToSplit(_split, _splitAmount, _defaultBeneficiary, msg.sender);\n\n unchecked {\n ++i;\n }\n }\n }\n}\n" + "contracts/JBGasTokenERC20SplitsPayer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBSplitsPayer.sol';\nimport './interfaces/IJBSplitsStore.sol';\nimport './libraries/JBConstants.sol';\nimport './JBGasTokenERC20ProjectPayer.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\n\n @dev\n Adheres to -\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBGasTokenERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBGasTokenERC20SplitsPayer is JBGasTokenERC20ProjectPayer, ReentrancyGuard, IJBSplitsPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The ID of project for which the default splits are stored. \n */\n uint256 public override defaultSplitsProjectId;\n\n /**\n @notice\n The domain within which the default splits are stored. \n */\n uint256 public override defaultSplitsDomain;\n\n /**\n @notice\n The group within which the default splits are stored. \n */\n uint256 public override defaultSplitsGroup;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBGasTokenERC20ProjectPayer, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n )\n JBGasTokenERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _preferAddToBalance,\n _splitsStore.directory(),\n _owner\n )\n {\n defaultSplitsProjectId = _defaultSplitsProjectId;\n defaultSplitsDomain = _defaultSplitsDomain;\n defaultSplitsGroup = _defaultSplitsGroup;\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default split group using the stored default properties.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override nonReentrant {\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // If there is no leftover amount, nothing left to pay.\n if (_leftoverAmount == 0) return;\n\n // If there's a default project ID, try to pay it.\n if (defaultProjectId != 0)\n if (defaultPreferAddToBalance)\n // Pay the project by adding to its balance if prefered.\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n _leftoverAmount,\n 18, // decimals.\n defaultMemo,\n defaultMetadata\n );\n // Otherwise, issue a payment to the project.\n else\n _pay(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n _leftoverAmount,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n 0, // min returned tokens.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else\n Address.sendValue(\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(tx.origin),\n _leftoverAmount\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the splits in the splits store that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n @param _groupedSplits The split groups to set.\n */\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n JBGroupedSplits[] memory _groupedSplits\n ) external virtual override onlyOwner {\n // Set the splits in the store.\n splitsStore.set(_projectId, _domain, _groupedSplits);\n\n // Set the splits reference.\n setDefaultSplitsReference(_projectId, _domain, _group);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the location of the splits that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n */\n function setDefaultSplitsReference(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) public virtual override onlyOwner {\n // Set the default splits project ID if it's changing.\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\n\n // Set the default splits domain if it's changing.\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\n\n // Set the default splits group if it's changing.\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\n\n emit SetDefaultSplitsReference(_projectId, _domain, _group, msg.sender);\n }\n\n /** \n @notice \n Make a payment to the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Pay any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to pay it.\n if (_projectId != 0) {\n _pay(\n _projectId,\n _token,\n _leftoverAmount,\n _decimals,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? payable(_beneficiary) : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit Pay(\n _projectId,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event. \n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Distribute any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to add to its balance.\n if (_projectId != 0)\n // Add to the project's balance.\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\n\n // Otherwise, send a payment to the beneficiary.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit AddToBalance(\n _projectId,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splitsProjectId The ID of the project to which the splits belong.\n @param _splitsDomain The splits domain to which the group belongs.\n @param _splitsGroup The splits group to pay.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payToSplits(\n uint256 _splitsProjectId,\n uint256 _splitsDomain,\n uint256 _splitsGroup,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Pay the splits.\n leftoverAmount = _payTo(\n splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup),\n _token,\n _amount,\n _decimals,\n _defaultBeneficiary\n );\n emit DistributeToSplitGroup(_splitsProjectId, _splitsDomain, _splitsGroup, msg.sender);\n }\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splits The splits.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payTo(\n JBSplit[] memory _splits,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Set the leftover amount to the initial balance.\n leftoverAmount = _amount;\n\n // Settle between all splits.\n for (uint256 i; i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[i];\n\n // The amount to send towards the split.\n uint256 _splitAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n if (_splitAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n _token,\n _splitAmount,\n _decimals,\n defaultProjectId,\n 0,\n _split\n );\n\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN)\n IERC20(_token).safeApprove(address(_split.allocator), _splitAmount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _splitAmount : 0;\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n if (_split.preferAddToBalance)\n _addToBalanceOf(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n 0,\n _split.preferClaimed,\n defaultMemo,\n defaultMetadata\n );\n } else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : payable(_defaultBeneficiary),\n _splitAmount\n );\n // Or, transfer the ERC20.\n else {\n IERC20(_token).safeTransfer(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n _splitAmount\n );\n }\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _splitAmount;\n }\n\n emit DistributeToSplit(_split, _splitAmount, _defaultBeneficiary, msg.sender);\n\n unchecked {\n ++i;\n }\n }\n }\n}\n" }, "contracts/interfaces/IJBSplitsPayer.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './../structs/JBSplit.sol';\nimport './../structs/JBGroupedSplits.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBSplitsPayer is IERC165 {\n event SetDefaultSplitsReference(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n address caller\n );\n event Pay(\n uint256 indexed projectId,\n address beneficiary,\n address token,\n uint256 amount,\n uint256 decimals,\n uint256 leftoverAmount,\n uint256 minReturnedTokens,\n bool preferClaimedTokens,\n string memo,\n bytes metadata,\n address caller\n );\n\n event AddToBalance(\n uint256 indexed projectId,\n address beneficiary,\n address token,\n uint256 amount,\n uint256 decimals,\n uint256 leftoverAmount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DistributeToSplitGroup(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n address caller\n );\n\n event DistributeToSplit(\n JBSplit split,\n uint256 amount,\n address defaultBeneficiary,\n address caller\n );\n\n function defaultSplitsProjectId() external view returns (uint256);\n\n function defaultSplitsDomain() external view returns (uint256);\n\n function defaultSplitsGroup() external view returns (uint256);\n\n function splitsStore() external view returns (IJBSplitsStore);\n\n function setDefaultSplitsReference(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) external;\n\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n JBGroupedSplits[] memory _splitsGroup\n ) external;\n}\n" }, - "contracts/JBETHERC20ProjectPayer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport './interfaces/IJBProjectPayer.sol';\nimport './libraries/JBTokens.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ERC165: Introspection on interface adherance. \n*/\ncontract JBETHERC20ProjectPayer is Ownable, ERC165, IJBProjectPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // -------------------------- custom errors -------------------------- //\n //*********************************************************************//\n error INCORRECT_DECIMAL_AMOUNT();\n error NO_MSG_VALUE_ALLOWED();\n error TERMINAL_NOT_FOUND();\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice \n A contract storing directories of terminals and controllers for each project.\n */\n IJBDirectory public immutable override directory;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The ID of the project that should be used to forward this contract's received payments.\n */\n uint256 public override defaultProjectId;\n\n /** \n @notice \n The beneficiary that should be used in the payment made when this contract receives payments.\n */\n address payable public override defaultBeneficiary;\n\n /** \n @notice \n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\n */\n bool public override defaultPreferClaimedTokens;\n\n /** \n @notice \n The memo that should be used in the payment made when this contract receives payments.\n */\n string public override defaultMemo;\n\n /** \n @notice \n The metadata that should be used in the payment made when this contract receives payments.\n */\n bytes public override defaultMetadata;\n\n /**\n @notice \n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n bool public override defaultPreferAddToBalance;\n\n //*********************************************************************//\n // ------------------------- public views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) {\n defaultProjectId = _defaultProjectId;\n defaultBeneficiary = _defaultBeneficiary;\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\n defaultMemo = _defaultMemo;\n defaultMetadata = _defaultMetadata;\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n directory = _directory;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default project ID using the stored default properties.\n\n @dev\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override {\n if (defaultPreferAddToBalance)\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.ETH,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n defaultProjectId,\n JBTokens.ETH,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultBeneficiary == address(0) ? tx.origin : defaultBeneficiary,\n 0, // Can't determine expectation of returned tokens ahead of time.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\n\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _beneficiary The address that'll receive the project's tokens. \n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _memo The memo that'll be used. \n @param _metadata The metadata that'll be sent. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external virtual override onlyOwner {\n // Set the default project ID if it has changed.\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\n\n // Set the default beneficiary if it has changed.\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\n\n // Set the default claimed token preference if it has changed.\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\n defaultPreferClaimedTokens = _preferClaimedTokens;\n\n // Set the default memo if it has changed.\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\n defaultMemo = _memo;\n\n // Set the default metadata if it has changed.\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\n defaultMetadata = _metadata;\n\n // Set the add to balance preference if it has changed.\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n\n emit SetDefaultValues(\n _projectId,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata,\n _defaultPreferAddToBalance,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _pay(\n _projectId,\n _token,\n _amount,\n _decimals,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. \n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source and delegate, if provided.\n */\n function _pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.ETH) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\n\n // Send funds to the terminal.\n // If the token is ETH, send it in msg.value.\n _terminal.pay{value: _payableValue}(\n _projectId,\n _amount, // ignored if the token is JBTokens.ETH.\n _token,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.ETH) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\n\n // Add to balance so tokens don't get issued.\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\n }\n}\n" + "contracts/JBGasTokenERC20ProjectPayer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport './interfaces/IJBProjectPayer.sol';\nimport './libraries/JBTokens.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ERC165: Introspection on interface adherance. \n*/\ncontract JBGasTokenERC20ProjectPayer is Ownable, ERC165, IJBProjectPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // -------------------------- custom errors -------------------------- //\n //*********************************************************************//\n error INCORRECT_DECIMAL_AMOUNT();\n error NO_MSG_VALUE_ALLOWED();\n error TERMINAL_NOT_FOUND();\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice \n A contract storing directories of terminals and controllers for each project.\n */\n IJBDirectory public immutable override directory;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The ID of the project that should be used to forward this contract's received payments.\n */\n uint256 public override defaultProjectId;\n\n /** \n @notice \n The beneficiary that should be used in the payment made when this contract receives payments.\n */\n address payable public override defaultBeneficiary;\n\n /** \n @notice \n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\n */\n bool public override defaultPreferClaimedTokens;\n\n /** \n @notice \n The memo that should be used in the payment made when this contract receives payments.\n */\n string public override defaultMemo;\n\n /** \n @notice \n The metadata that should be used in the payment made when this contract receives payments.\n */\n bytes public override defaultMetadata;\n\n /**\n @notice \n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n bool public override defaultPreferAddToBalance;\n\n //*********************************************************************//\n // ------------------------- public views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) {\n defaultProjectId = _defaultProjectId;\n defaultBeneficiary = _defaultBeneficiary;\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\n defaultMemo = _defaultMemo;\n defaultMetadata = _defaultMetadata;\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n directory = _directory;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default project ID using the stored default properties.\n\n @dev\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override {\n if (defaultPreferAddToBalance)\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultBeneficiary == address(0) ? tx.origin : defaultBeneficiary,\n 0, // Can't determine expectation of returned tokens ahead of time.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\n\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _beneficiary The address that'll receive the project's tokens. \n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _memo The memo that'll be used. \n @param _metadata The metadata that'll be sent. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external virtual override onlyOwner {\n // Set the default project ID if it has changed.\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\n\n // Set the default beneficiary if it has changed.\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\n\n // Set the default claimed token preference if it has changed.\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\n defaultPreferClaimedTokens = _preferClaimedTokens;\n\n // Set the default memo if it has changed.\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\n defaultMemo = _memo;\n\n // Set the default metadata if it has changed.\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\n defaultMetadata = _metadata;\n\n // Set the add to balance preference if it has changed.\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n\n emit SetDefaultValues(\n _projectId,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata,\n _defaultPreferAddToBalance,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _pay(\n _projectId,\n _token,\n _amount,\n _decimals,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. \n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source and delegate, if provided.\n */\n function _pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send funds to the terminal.\n // If the token is ETH, send it in msg.value.\n _terminal.pay{value: _payableValue}(\n _projectId,\n _amount, // ignored if the token is JBTokens.GAS_TOKEN.\n _token,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Add to balance so tokens don't get issued.\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\n }\n}\n" }, "contracts/interfaces/IJBProjectPayer.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './IJBDirectory.sol';\n\ninterface IJBProjectPayer is IERC165 {\n event SetDefaultValues(\n uint256 indexed projectId,\n address indexed beneficiary,\n bool preferClaimedTokens,\n string memo,\n bytes metadata,\n bool preferAddToBalance,\n address caller\n );\n\n function directory() external view returns (IJBDirectory);\n\n function defaultProjectId() external view returns (uint256);\n\n function defaultBeneficiary() external view returns (address payable);\n\n function defaultPreferClaimedTokens() external view returns (bool);\n\n function defaultMemo() external view returns (string memory);\n\n function defaultMetadata() external view returns (bytes memory);\n\n function defaultPreferAddToBalance() external view returns (bool);\n\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external;\n\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) external payable;\n\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) external payable;\n\n receive() external payable;\n}\n" }, "contracts/system_tests/TestEIP165.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.6;\n\nimport './helpers/TestBaseWorkflow.sol';\nimport '../JBReconfigurationBufferBallot.sol';\nimport '../JBETHERC20SplitsPayer.sol';\n\ncontract TestEIP165 is TestBaseWorkflow {\n bytes4 constant notSupportedInterface = 0xffffffff;\n\n uint256 constant projectId = 2;\n uint256 constant splitsProjectID = 3;\n address payable constant splitsBeneficiary = payable(address(420));\n uint256 constant splitsDomain = 1;\n uint256 constant splitsGroup = 1;\n bool constant splitsPreferClaimedTokens = false;\n string constant splitsMemo = '';\n bytes constant splitsMetadata = '';\n bool constant splitsPreferAddToBalance = true;\n address constant splitsOwner = address(420);\n\n function testJBController() public {\n JBController controller = jbController();\n\n // Should support these interfaces\n assertTrue(controller.supportsInterface(type(IERC165).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBController).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBMigratable).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!controller.supportsInterface(notSupportedInterface));\n }\n\n function testJBERC20PaymentTerminal() public {\n JBERC20PaymentTerminal terminal = new JBERC20PaymentTerminal(\n jbToken(),\n jbLibraries().USD(), // currency\n jbLibraries().ETH(), // base weight currency\n 1, // JBSplitsGroupe\n jbOperatorStore(),\n jbProjects(),\n jbDirectory(),\n jbSplitsStore(),\n jbPrices(),\n jbPaymentTerminalStore(),\n multisig()\n );\n\n // Should support these interfaces\n assertTrue(terminal.supportsInterface(type(IERC165).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBRedemptionTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBSingleTokenPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!terminal.supportsInterface(notSupportedInterface));\n }\n\n function testJBETHPaymentTerminal() public {\n JBETHPaymentTerminal terminal = jbETHPaymentTerminal();\n\n // Should support these interfaces\n assertTrue(terminal.supportsInterface(type(IERC165).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBRedemptionTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBSingleTokenPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!terminal.supportsInterface(notSupportedInterface));\n }\n\n function testJBProjects() public {\n JBProjects projects = jbProjects();\n\n // Should support these interfaces\n assertTrue(projects.supportsInterface(type(IERC165).interfaceId));\n assertTrue(projects.supportsInterface(type(IERC721).interfaceId));\n assertTrue(projects.supportsInterface(type(IERC721Metadata).interfaceId));\n assertTrue(projects.supportsInterface(type(IJBProjects).interfaceId));\n assertTrue(projects.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!projects.supportsInterface(notSupportedInterface));\n }\n\n function testJBReconfigurationBufferBallot() public {\n JBReconfigurationBufferBallot ballot = new JBReconfigurationBufferBallot(3000);\n\n // Should support these interfaces\n assertTrue(ballot.supportsInterface(type(IERC165).interfaceId));\n // TODO: Add interface\n //assertTrue(ballot.supportsInterface(type(IJBReconfigurationBufferBallot).interfaceId));\n assertTrue(ballot.supportsInterface(type(IJBFundingCycleBallot).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!ballot.supportsInterface(notSupportedInterface));\n }\n\n function testJBETHERC20SplitsPayer() public {\n JBETHERC20SplitsPayer splitsPayer = new JBETHERC20SplitsPayer(\n splitsProjectID,\n splitsDomain,\n splitsGroup,\n jbSplitsStore(),\n projectId,\n splitsBeneficiary,\n splitsPreferClaimedTokens,\n splitsMemo,\n splitsMetadata,\n splitsPreferAddToBalance,\n splitsOwner\n );\n\n // Should support these interfaces\n assertTrue(splitsPayer.supportsInterface(type(IERC165).interfaceId));\n assertTrue(splitsPayer.supportsInterface(type(IJBSplitsPayer).interfaceId));\n assertTrue(splitsPayer.supportsInterface(type(IJBProjectPayer).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!splitsPayer.supportsInterface(notSupportedInterface));\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.6;\n\nimport './helpers/TestBaseWorkflow.sol';\nimport '../JBReconfigurationBufferBallot.sol';\nimport '../JBGasTokenERC20SplitsPayer.sol';\n\ncontract TestEIP165 is TestBaseWorkflow {\n bytes4 constant notSupportedInterface = 0xffffffff;\n\n uint256 constant projectId = 2;\n uint256 constant splitsProjectID = 3;\n address payable constant splitsBeneficiary = payable(address(420));\n uint256 constant splitsDomain = 1;\n uint256 constant splitsGroup = 1;\n bool constant splitsPreferClaimedTokens = false;\n string constant splitsMemo = '';\n bytes constant splitsMetadata = '';\n bool constant splitsPreferAddToBalance = true;\n address constant splitsOwner = address(420);\n\n function testJBController() public {\n JBController controller = jbController();\n\n // Should support these interfaces\n assertTrue(controller.supportsInterface(type(IERC165).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBController).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBMigratable).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!controller.supportsInterface(notSupportedInterface));\n }\n\n function testJBERC20PaymentTerminal() public {\n JBERC20PaymentTerminal terminal = new JBERC20PaymentTerminal(\n jbToken(),\n jbLibraries().USD(), // currency\n jbLibraries().ETH(), // base weight currency\n 1, // JBSplitsGroupe\n jbOperatorStore(),\n jbProjects(),\n jbDirectory(),\n jbSplitsStore(),\n jbPrices(),\n jbPaymentTerminalStore(),\n multisig()\n );\n\n // Should support these interfaces\n assertTrue(terminal.supportsInterface(type(IERC165).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBRedemptionTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBSingleTokenPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!terminal.supportsInterface(notSupportedInterface));\n }\n\n function testJBETHPaymentTerminal() public {\n JBETHPaymentTerminal terminal = jbETHPaymentTerminal();\n\n // Should support these interfaces\n assertTrue(terminal.supportsInterface(type(IERC165).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBRedemptionTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBSingleTokenPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!terminal.supportsInterface(notSupportedInterface));\n }\n\n function testJBProjects() public {\n JBProjects projects = jbProjects();\n\n // Should support these interfaces\n assertTrue(projects.supportsInterface(type(IERC165).interfaceId));\n assertTrue(projects.supportsInterface(type(IERC721).interfaceId));\n assertTrue(projects.supportsInterface(type(IERC721Metadata).interfaceId));\n assertTrue(projects.supportsInterface(type(IJBProjects).interfaceId));\n assertTrue(projects.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!projects.supportsInterface(notSupportedInterface));\n }\n\n function testJBReconfigurationBufferBallot() public {\n JBReconfigurationBufferBallot ballot = new JBReconfigurationBufferBallot(3000);\n\n // Should support these interfaces\n assertTrue(ballot.supportsInterface(type(IERC165).interfaceId));\n // TODO: Add interface\n //assertTrue(ballot.supportsInterface(type(IJBReconfigurationBufferBallot).interfaceId));\n assertTrue(ballot.supportsInterface(type(IJBFundingCycleBallot).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!ballot.supportsInterface(notSupportedInterface));\n }\n\n function testJBGasTokenERC20SplitsPayer() public {\n JBGasTokenERC20SplitsPayer splitsPayer = new JBGasTokenERC20SplitsPayer(\n splitsProjectID,\n splitsDomain,\n splitsGroup,\n jbSplitsStore(),\n projectId,\n splitsBeneficiary,\n splitsPreferClaimedTokens,\n splitsMemo,\n splitsMetadata,\n splitsPreferAddToBalance,\n splitsOwner\n );\n\n // Should support these interfaces\n assertTrue(splitsPayer.supportsInterface(type(IERC165).interfaceId));\n assertTrue(splitsPayer.supportsInterface(type(IJBSplitsPayer).interfaceId));\n assertTrue(splitsPayer.supportsInterface(type(IJBProjectPayer).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!splitsPayer.supportsInterface(notSupportedInterface));\n }\n}\n" }, "contracts/JBReconfigurationBufferBallot.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport './interfaces/IJBFundingCycleBallot.sol';\nimport './structs/JBFundingCycle.sol';\n\n/** \n @notice \n Manages approving funding cycle reconfigurations automatically after a buffer period.\n\n @dev\n Adheres to -\n IJBFundingCycleBallot: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ERC165: Introspection on interface adherance. \n*/\ncontract JBReconfigurationBufferBallot is ERC165, IJBFundingCycleBallot {\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice \n The number of seconds that must pass for a funding cycle reconfiguration to become either `Approved` or `Failed`.\n */\n uint256 public immutable override duration;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice \n The approval state of a particular funding cycle.\n\n @param _projectId The ID of the project to which the funding cycle being checked belongs.\n @param _configured The configuration of the funding cycle to check the state of.\n @param _start The start timestamp of the funding cycle to check the state of.\n\n @return The state of the provided ballot. \n */\n function stateOf(\n uint256 _projectId,\n uint256 _configured,\n uint256 _start\n ) public view override returns (JBBallotState) {\n _projectId; // Prevents unused var compiler and natspec complaints.\n\n // If the provided configured timestamp is after the start timestamp, the ballot is Failed.\n if (_configured > _start) return JBBallotState.Failed;\n\n unchecked {\n // If there was sufficient time between configuration and the start of the cycle, it is approved. Otherwise, it is failed.\n return (_start - _configured < duration) ? JBBallotState.Failed : JBBallotState.Approved;\n }\n }\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBFundingCycleBallot).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _duration The number of seconds to wait until a reconfiguration can be either `Approved` or `Failed`.\n */\n constructor(uint256 _duration) {\n duration = _duration;\n }\n}\n" @@ -358,20 +358,20 @@ "contracts/system_tests/TestReconfigure.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.6;\n\nimport './helpers/TestBaseWorkflow.sol';\n\nimport '../JBReconfigurationBufferBallot.sol';\n\nuint256 constant WEIGHT = 1000 * 10**18;\n\ncontract TestReconfigureProject is TestBaseWorkflow {\n JBController controller;\n JBProjectMetadata _projectMetadata;\n JBFundingCycleData _data;\n JBFundingCycleData _dataReconfiguration;\n JBFundingCycleData _dataWithoutBallot;\n JBFundingCycleMetadata _metadata;\n JBReconfigurationBufferBallot _ballot;\n JBGroupedSplits[] _groupedSplits; // Default empty\n JBFundAccessConstraints[] _fundAccessConstraints; // Default empty\n IJBPaymentTerminal[] _terminals; // Default empty\n\n uint256 BALLOT_DURATION = 3 days;\n\n function setUp() public override {\n super.setUp();\n\n controller = jbController();\n\n _projectMetadata = JBProjectMetadata({content: 'myIPFSHash', domain: 1});\n\n _ballot = new JBReconfigurationBufferBallot(BALLOT_DURATION);\n\n _data = JBFundingCycleData({\n duration: 6 days,\n weight: 10000 * 10**18,\n discountRate: 0,\n ballot: _ballot\n });\n\n _dataWithoutBallot = JBFundingCycleData({\n duration: 6 days,\n weight: 1000 * 10**18,\n discountRate: 0,\n ballot: JBReconfigurationBufferBallot(address(0))\n });\n\n _dataReconfiguration = JBFundingCycleData({\n duration: 6 days,\n weight: 69 * 10**18,\n discountRate: 0,\n ballot: JBReconfigurationBufferBallot(address(0))\n });\n\n _metadata = JBFundingCycleMetadata({\n global: JBGlobalFundingCycleMetadata({\n allowSetTerminals: false,\n allowSetController: false,\n pauseTransfers: false\n }),\n reservedRate: 5000,\n redemptionRate: 5000,\n ballotRedemptionRate: 0,\n pausePay: false,\n pauseDistributions: false,\n pauseRedeem: false,\n pauseBurn: false,\n allowMinting: true,\n allowTerminalMigration: false,\n allowControllerMigration: false,\n holdFees: false,\n preferClaimedTokenOverride: false,\n useTotalOverflowForRedemptions: false,\n useDataSourceForPay: false,\n useDataSourceForRedeem: false,\n dataSource: address(0),\n metadata: 0\n });\n\n _terminals = [jbETHPaymentTerminal()];\n }\n\n function testReconfigureProject() public {\n uint256 projectId = controller.launchProjectFor(\n multisig(),\n _projectMetadata,\n _data,\n _metadata,\n 0, // Start asap\n _groupedSplits,\n _fundAccessConstraints,\n _terminals,\n ''\n );\n\n JBFundingCycle memory fundingCycle = jbFundingCycleStore().currentOf(projectId);\n\n assertEq(fundingCycle.number, 1); // ok\n assertEq(fundingCycle.weight, _data.weight);\n\n uint256 currentConfiguration = fundingCycle.configuration;\n\n evm.warp(block.timestamp + 1); // Avoid overwriting if same timestamp\n\n evm.prank(multisig());\n controller.reconfigureFundingCyclesOf(\n projectId,\n _data, // 3days ballot\n _metadata,\n 0, // Start asap\n _groupedSplits,\n _fundAccessConstraints,\n ''\n );\n\n // Shouldn't have changed\n fundingCycle = jbFundingCycleStore().currentOf(projectId);\n assertEq(fundingCycle.number, 1);\n assertEq(fundingCycle.configuration, currentConfiguration);\n assertEq(fundingCycle.weight, _data.weight);\n\n // should be new funding cycle\n evm.warp(fundingCycle.start + fundingCycle.duration);\n\n JBFundingCycle memory newFundingCycle = jbFundingCycleStore().currentOf(projectId);\n assertEq(newFundingCycle.number, 2);\n assertEq(newFundingCycle.weight, _data.weight);\n }\n\n function testMultipleReconfigurationOnRolledOver() public {\n uint256 weightFirstReconfiguration = 1234 * 10**18;\n uint256 weightSecondReconfiguration = 6969 * 10**18;\n\n uint256 projectId = controller.launchProjectFor(\n multisig(),\n _projectMetadata,\n _data,\n _metadata,\n 0, // Start asap\n _groupedSplits,\n _fundAccessConstraints,\n _terminals,\n ''\n );\n\n JBFundingCycle memory fundingCycle = jbFundingCycleStore().currentOf(projectId);\n\n // Initial funding cycle data\n assertEq(fundingCycle.number, 1);\n assertEq(fundingCycle.weight, _data.weight);\n\n uint256 currentConfiguration = fundingCycle.configuration;\n\n // Jump to FC+1, rolled over\n evm.warp(block.timestamp + fundingCycle.duration);\n\n // First reconfiguration\n evm.prank(multisig());\n controller.reconfigureFundingCyclesOf(\n projectId,\n JBFundingCycleData({\n duration: 6 days,\n weight: weightFirstReconfiguration,\n discountRate: 0,\n ballot: _ballot\n }), // 3days ballot\n _metadata,\n 0, // Start asap\n _groupedSplits,\n _fundAccessConstraints,\n ''\n );\n\n evm.warp(block.timestamp + 1); // Avoid overwrite\n\n // Second reconfiguration (different configuration)\n evm.prank(multisig());\n controller.reconfigureFundingCyclesOf(\n projectId,\n JBFundingCycleData({\n duration: 6 days,\n weight: weightSecondReconfiguration,\n discountRate: 0,\n ballot: _ballot\n }), // 3days ballot\n _metadata,\n 0, // Start asap\n _groupedSplits,\n _fundAccessConstraints,\n ''\n );\n uint256 secondReconfiguration = block.timestamp;\n\n // Shouldn't have changed, still in FC#2, rolled over from FC#1\n fundingCycle = jbFundingCycleStore().currentOf(projectId);\n assertEq(fundingCycle.number, 2);\n assertEq(fundingCycle.configuration, currentConfiguration);\n assertEq(fundingCycle.weight, _data.weight);\n\n // Jump to after the ballot passed, but before the next FC\n evm.warp(fundingCycle.start + fundingCycle.duration - 1);\n\n // Queued should be the second reconfiguration\n JBFundingCycle memory queuedFundingCycle = jbFundingCycleStore().queuedOf(projectId);\n assertEq(queuedFundingCycle.number, 3);\n assertEq(queuedFundingCycle.configuration, secondReconfiguration);\n assertEq(queuedFundingCycle.weight, weightSecondReconfiguration);\n\n evm.warp(fundingCycle.start + fundingCycle.duration);\n\n // Second reconfiguration should be now the current one\n JBFundingCycle memory newFundingCycle = jbFundingCycleStore().currentOf(projectId);\n assertEq(newFundingCycle.number, 3);\n assertEq(newFundingCycle.configuration, secondReconfiguration);\n assertEq(newFundingCycle.weight, weightSecondReconfiguration);\n }\n\n function testMultipleReconfigure(uint8 FUZZED_BALLOT_DURATION) public {\n _ballot = new JBReconfigurationBufferBallot(FUZZED_BALLOT_DURATION);\n\n _data = JBFundingCycleData({\n duration: 6 days,\n weight: 10000 ether,\n discountRate: 0,\n ballot: _ballot\n });\n\n uint256 projectId = controller.launchProjectFor(\n multisig(),\n _projectMetadata,\n _data, // duration 6 days, weight=10k, ballot 3days\n _metadata,\n 0, // Start asap\n _groupedSplits,\n _fundAccessConstraints,\n _terminals,\n ''\n );\n\n JBFundingCycle memory initialFundingCycle = jbFundingCycleStore().currentOf(projectId);\n JBFundingCycle memory currentFundingCycle = initialFundingCycle;\n JBFundingCycle memory queuedFundingCycle = jbFundingCycleStore().queuedOf(projectId);\n\n evm.warp(currentFundingCycle.start + 1); // Avoid overwriting current fc while reconfiguring\n\n for (uint256 i = 0; i < 4; i++) {\n currentFundingCycle = jbFundingCycleStore().currentOf(projectId);\n\n if (FUZZED_BALLOT_DURATION + i * 1 days < currentFundingCycle.duration)\n assertEq(currentFundingCycle.weight, initialFundingCycle.weight - i);\n\n _data = JBFundingCycleData({\n duration: 6 days,\n weight: initialFundingCycle.weight - (i + 1), // i+1 -> next funding cycle\n discountRate: 0,\n ballot: _ballot\n });\n\n evm.prank(multisig());\n controller.reconfigureFundingCyclesOf(\n projectId,\n _data,\n _metadata,\n 0,\n _groupedSplits,\n _fundAccessConstraints,\n ''\n );\n\n currentFundingCycle = jbFundingCycleStore().currentOf(projectId);\n queuedFundingCycle = jbFundingCycleStore().queuedOf(projectId);\n\n // Queued is the funding cycle currently under ballot\n assertEq(queuedFundingCycle.weight, _data.weight);\n assertEq(queuedFundingCycle.number, currentFundingCycle.number + 1);\n\n // Is the full ballot duration included in the funding cycle?\n if (\n FUZZED_BALLOT_DURATION == 0 ||\n currentFundingCycle.duration % (FUZZED_BALLOT_DURATION + i * 1 days) <\n currentFundingCycle.duration\n ) {\n assertEq(currentFundingCycle.weight, initialFundingCycle.weight - i);\n\n uint256 _previousFundingCycleNumber = currentFundingCycle.number;\n\n // we shift forward the start of the ballot into the fc, one day at a time, from fc to fc\n evm.warp(currentFundingCycle.start + currentFundingCycle.duration + i * 1 days);\n\n // Ballot was Approved and we've changed fc, current is the reconfiguration\n currentFundingCycle = jbFundingCycleStore().currentOf(projectId);\n assertEq(currentFundingCycle.weight, _data.weight);\n assertEq(currentFundingCycle.number, _previousFundingCycleNumber + 1);\n\n // Queued is the reconfiguration rolled-over\n queuedFundingCycle = jbFundingCycleStore().queuedOf(projectId);\n assertEq(queuedFundingCycle.weight, _data.weight);\n assertEq(queuedFundingCycle.number, currentFundingCycle.number + 1);\n }\n // the ballot is accross two funding cycles\n else {\n // Warp to begining of next FC: should be the previous fc config rolled over (ballot is in Failed state)\n evm.warp(currentFundingCycle.start + currentFundingCycle.duration);\n assertEq(currentFundingCycle.weight, initialFundingCycle.weight - i);\n uint256 cycleNumber = currentFundingCycle.number;\n\n // Warp to after the end of the ballot, within the same fc: should be the new fc (ballot is in Approved state)\n evm.warp(currentFundingCycle.start + currentFundingCycle.duration + FUZZED_BALLOT_DURATION);\n currentFundingCycle = jbFundingCycleStore().currentOf(projectId);\n assertEq(currentFundingCycle.weight, _data.weight);\n assertEq(currentFundingCycle.number, cycleNumber + 1);\n }\n }\n }\n\n function testReconfigureProjectFuzzRates(\n uint96 RESERVED_RATE,\n uint96 REDEMPTION_RATE,\n uint96 BALANCE\n ) public {\n evm.assume(payable(msg.sender).balance / 2 >= BALANCE);\n evm.assume(100 < BALANCE);\n\n address _beneficiary = address(69420);\n uint256 projectId = controller.launchProjectFor(\n multisig(),\n _projectMetadata,\n _dataWithoutBallot,\n _metadata,\n 0, // _mustStartAtOrAfter\n _groupedSplits,\n _fundAccessConstraints,\n _terminals,\n ''\n );\n\n JBFundingCycle memory fundingCycle = jbFundingCycleStore().currentOf(projectId);\n assertEq(fundingCycle.number, 1);\n\n evm.warp(block.timestamp + 1);\n\n jbETHPaymentTerminal().pay{value: BALANCE}(\n projectId,\n BALANCE,\n address(0),\n _beneficiary,\n 0,\n false,\n 'Forge test',\n new bytes(0)\n );\n\n uint256 _userTokenBalance = PRBMath.mulDiv(BALANCE, (WEIGHT / 10**18), 2); // initial FC rate is 50%\n if (BALANCE != 0)\n assertEq(jbTokenStore().balanceOf(_beneficiary, projectId), _userTokenBalance);\n\n evm.prank(multisig());\n if (RESERVED_RATE > 10000) evm.expectRevert(abi.encodeWithSignature('INVALID_RESERVED_RATE()'));\n else if (REDEMPTION_RATE > 10000)\n evm.expectRevert(abi.encodeWithSignature('INVALID_REDEMPTION_RATE()'));\n\n controller.reconfigureFundingCyclesOf(\n projectId,\n _dataWithoutBallot,\n JBFundingCycleMetadata({\n global: JBGlobalFundingCycleMetadata({\n allowSetTerminals: false,\n allowSetController: false,\n pauseTransfers: false\n }),\n reservedRate: RESERVED_RATE,\n redemptionRate: REDEMPTION_RATE,\n ballotRedemptionRate: 0,\n pausePay: false,\n pauseDistributions: false,\n pauseRedeem: false,\n pauseBurn: false,\n allowMinting: true,\n allowTerminalMigration: false,\n allowControllerMigration: false,\n holdFees: false,\n preferClaimedTokenOverride: false,\n useTotalOverflowForRedemptions: false,\n useDataSourceForPay: false,\n useDataSourceForRedeem: false,\n dataSource: address(0),\n metadata: 0\n }),\n 0,\n _groupedSplits,\n _fundAccessConstraints,\n ''\n );\n\n if (RESERVED_RATE > 10000 || REDEMPTION_RATE > 10000) {\n REDEMPTION_RATE = 5000; // If reconfigure has reverted, keep previous rates\n RESERVED_RATE = 5000;\n }\n\n evm.warp(block.timestamp + fundingCycle.duration);\n\n fundingCycle = jbFundingCycleStore().currentOf(projectId);\n assertEq(fundingCycle.number, 2);\n\n jbETHPaymentTerminal().pay{value: BALANCE}(\n projectId,\n BALANCE,\n address(0),\n _beneficiary,\n 0,\n false,\n 'Forge test',\n new bytes(0)\n );\n\n uint256 _newUserTokenBalance = RESERVED_RATE == 0 // New fc, rate is RESERVED_RATE\n ? PRBMath.mulDiv(BALANCE, WEIGHT, 10**18)\n : PRBMath.mulDiv(PRBMath.mulDiv(BALANCE, WEIGHT, 10**18), 10000 - RESERVED_RATE, 10000);\n\n if (BALANCE != 0)\n assertEq(\n jbTokenStore().balanceOf(_beneficiary, projectId),\n _userTokenBalance + _newUserTokenBalance\n );\n\n uint256 tokenBalance = jbTokenStore().balanceOf(_beneficiary, projectId);\n uint256 totalSupply = jbController().totalOutstandingTokensOf(projectId, RESERVED_RATE);\n uint256 overflow = jbETHPaymentTerminal().currentEthOverflowOf(projectId);\n\n evm.startPrank(_beneficiary);\n jbETHPaymentTerminal().redeemTokensOf(\n _beneficiary,\n projectId,\n tokenBalance,\n address(0), //token (unused)\n 0,\n payable(_beneficiary),\n '',\n new bytes(0)\n );\n evm.stopPrank();\n\n if (BALANCE != 0 && REDEMPTION_RATE != 0)\n assertEq(\n _beneficiary.balance,\n PRBMath.mulDiv(\n PRBMath.mulDiv(overflow, tokenBalance, totalSupply),\n REDEMPTION_RATE + PRBMath.mulDiv(tokenBalance, 10000 - REDEMPTION_RATE, totalSupply),\n 10000\n )\n );\n }\n\n function testLaunchProjectWrongBallot() public {\n uint256 projectId = controller.launchProjectFor(\n multisig(),\n _projectMetadata,\n _data,\n _metadata,\n 0, // Start asap\n _groupedSplits,\n _fundAccessConstraints,\n _terminals,\n ''\n );\n\n JBFundingCycleData memory _dataNew = JBFundingCycleData({\n duration: 6 days,\n weight: 12345 * 10**18,\n discountRate: 0,\n ballot: IJBFundingCycleBallot(address(6969)) // Wrong ballot address\n });\n\n evm.warp(block.timestamp + 1); // Avoid overwriting if same timestamp\n\n evm.prank(multisig());\n evm.expectRevert(abi.encodeWithSignature('INVALID_BALLOT()'));\n controller.reconfigureFundingCyclesOf(\n projectId,\n _dataNew, // wrong ballot\n _metadata,\n 0, // Start asap\n _groupedSplits,\n _fundAccessConstraints,\n ''\n );\n }\n\n function testReconfigureShortDurationProject() public {\n _data = JBFundingCycleData({\n duration: 5 minutes,\n weight: 10000 * 10**18,\n discountRate: 0,\n ballot: _ballot\n });\n\n _dataReconfiguration = JBFundingCycleData({\n duration: 6 days,\n weight: 69 * 10**18,\n discountRate: 0,\n ballot: IJBFundingCycleBallot(address(0))\n });\n\n uint256 projectId = controller.launchProjectFor(\n multisig(),\n _projectMetadata,\n _data,\n _metadata,\n 0, // Start asap\n _groupedSplits,\n _fundAccessConstraints,\n _terminals,\n ''\n );\n\n JBFundingCycle memory fundingCycle = jbFundingCycleStore().currentOf(projectId);\n\n assertEq(fundingCycle.number, 1); // ok\n assertEq(fundingCycle.weight, _data.weight);\n\n uint256 currentConfiguration = fundingCycle.configuration;\n\n evm.warp(block.timestamp + 1); // Avoid overwriting if same timestamp\n\n evm.prank(multisig());\n controller.reconfigureFundingCyclesOf(\n projectId,\n _dataReconfiguration,\n _metadata,\n 0, // Start asap\n _groupedSplits,\n _fundAccessConstraints,\n ''\n );\n\n // Shouldn't have changed (same cycle, with a ballot)\n fundingCycle = jbFundingCycleStore().currentOf(projectId);\n assertEq(fundingCycle.number, 1);\n assertEq(fundingCycle.configuration, currentConfiguration);\n assertEq(fundingCycle.weight, _data.weight);\n\n // shouldn't have changed (new cycle but ballot is still active)\n evm.warp(fundingCycle.start + fundingCycle.duration);\n\n JBFundingCycle memory newFundingCycle = jbFundingCycleStore().currentOf(projectId);\n assertEq(newFundingCycle.number, 2);\n assertEq(newFundingCycle.weight, _data.weight);\n\n // should now be the reconfiguration (ballot duration is over)\n evm.warp(fundingCycle.start + fundingCycle.duration + 3 days);\n\n newFundingCycle = jbFundingCycleStore().currentOf(projectId);\n assertEq(newFundingCycle.number, fundingCycle.number + (3 days / 5 minutes) + 1);\n assertEq(newFundingCycle.weight, _dataReconfiguration.weight);\n }\n\n function testReconfigureWithoutBallot() public {\n _data = JBFundingCycleData({\n duration: 5 minutes,\n weight: 10000 * 10**18,\n discountRate: 0,\n ballot: IJBFundingCycleBallot(address(0))\n });\n\n _dataReconfiguration = JBFundingCycleData({\n duration: 6 days,\n weight: 69 * 10**18,\n discountRate: 0,\n ballot: IJBFundingCycleBallot(address(0))\n });\n\n uint256 projectId = controller.launchProjectFor(\n multisig(),\n _projectMetadata,\n _data,\n _metadata,\n 0, // Start asap\n _groupedSplits,\n _fundAccessConstraints,\n _terminals,\n ''\n );\n\n JBFundingCycle memory fundingCycle = jbFundingCycleStore().currentOf(projectId);\n\n assertEq(fundingCycle.number, 1);\n assertEq(fundingCycle.weight, _data.weight);\n\n evm.warp(block.timestamp + 10); // Avoid overwriting if same timestamp\n\n evm.prank(multisig());\n controller.reconfigureFundingCyclesOf(\n projectId,\n _dataReconfiguration,\n _metadata,\n 0, // Start asap\n _groupedSplits,\n _fundAccessConstraints,\n ''\n );\n // Should not have changed\n fundingCycle = jbFundingCycleStore().currentOf(projectId);\n assertEq(fundingCycle.number, 1);\n assertEq(fundingCycle.weight, _data.weight);\n\n // Should have changed after the current funding cycle is over\n evm.warp(fundingCycle.start + fundingCycle.duration);\n fundingCycle = jbFundingCycleStore().currentOf(projectId);\n assertEq(fundingCycle.number, 2);\n assertEq(fundingCycle.weight, _dataReconfiguration.weight);\n }\n}\n" }, - "contracts/JBETHERC20ProjectPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './interfaces/IJBETHERC20ProjectPayerDeployer.sol';\nimport './JBETHERC20ProjectPayer.sol';\n\n/** \n @notice \n Deploys project payer contracts.\n\n @dev\n Adheres to -\n IJBETHERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBETHERC20ProjectPayerDeployer is IJBETHERC20ProjectPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new project payer contract.\n\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the project payer contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the project payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the project payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the project payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the project payer.\n\n @return projectPayer The project payer contract.\n */\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external override returns (IJBProjectPayer projectPayer) {\n // Deploy the project payer.\n projectPayer = new JBETHERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner\n );\n\n emit DeployProjectPayer(\n projectPayer,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner,\n msg.sender\n );\n }\n}\n" + "contracts/JBGasTokenERC20ProjectPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './interfaces/IJBGasTokenERC20ProjectPayerDeployer.sol';\nimport './JBGasTokenERC20ProjectPayer.sol';\n\n/** \n @notice \n Deploys project payer contracts.\n\n @dev\n Adheres to -\n IJBGasTokenERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBGasTokenERC20ProjectPayerDeployer is IJBGasTokenERC20ProjectPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new project payer contract.\n\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the project payer contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the project payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the project payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the project payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the project payer.\n\n @return projectPayer The project payer contract.\n */\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external override returns (IJBProjectPayer projectPayer) {\n // Deploy the project payer.\n projectPayer = new JBGasTokenERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner\n );\n\n emit DeployProjectPayer(\n projectPayer,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner,\n msg.sender\n );\n }\n}\n" }, - "contracts/interfaces/IJBETHERC20ProjectPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBDirectory.sol';\nimport './IJBProjectPayer.sol';\n\ninterface IJBETHERC20ProjectPayerDeployer {\n event DeployProjectPayer(\n IJBProjectPayer indexed projectPayer,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n IJBDirectory directory,\n address owner,\n address caller\n );\n\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external returns (IJBProjectPayer projectPayer);\n}\n" + "contracts/interfaces/IJBGasTokenERC20ProjectPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBDirectory.sol';\nimport './IJBProjectPayer.sol';\n\ninterface IJBGasTokenERC20ProjectPayerDeployer {\n event DeployProjectPayer(\n IJBProjectPayer indexed projectPayer,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n IJBDirectory directory,\n address owner,\n address caller\n );\n\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external returns (IJBProjectPayer projectPayer);\n}\n" }, "contracts/interfaces/IJBTerminalUtility.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBDirectory.sol';\n\ninterface IJBPaymentTerminalUtility {\n function directory() external view returns (IJBDirectory);\n}\n" }, - "contracts/JBETHERC20SplitsPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './interfaces/IJBETHERC20SplitsPayerDeployer.sol';\nimport './structs/JBSplit.sol';\nimport './structs/JBGroupedSplits.sol';\nimport './JBETHERC20SplitsPayer.sol';\n\n/** \n @notice \n Deploys splits payer contracts.\n\n @dev\n Adheres to -\n IJBETHERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBETHERC20SplitsPayerDeployer is IJBETHERC20SplitsPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @dev\n This contract must have Operator permissions over the SET_SPLITS permission of the specified `_defaultSplitsProjectId`.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplits The splits to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBSplitsPayer splitsPayer) {\n // Use this contract's address as the domain.\n uint256 _domain = uint256(uint160(address(this)));\n\n // Create the random hash using data unique to this instance that'll be used as the storage domain.\n uint256 _group = uint256(keccak256(abi.encodePacked(msg.sender, block.number)));\n\n // Set the splits in the store.\n JBGroupedSplits[] memory _groupedSplits;\n _groupedSplits = new JBGroupedSplits[](1);\n _groupedSplits[0] = JBGroupedSplits(_group, _defaultSplits);\n _splitsStore.set(_defaultSplitsProjectId, _domain, _groupedSplits);\n\n return\n deploySplitsPayer(\n _defaultSplitsProjectId,\n _domain,\n _group,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n }\n\n //*********************************************************************//\n // ---------------------- public transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) public override returns (IJBSplitsPayer splitsPayer) {\n // Deploy the splits payer.\n splitsPayer = new JBETHERC20SplitsPayer(\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeploySplitsPayer(\n splitsPayer,\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner,\n msg.sender\n );\n }\n}\n" + "contracts/JBGasTokenERC20SplitsPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './interfaces/IJBGasTokenERC20SplitsPayerDeployer.sol';\nimport './structs/JBSplit.sol';\nimport './structs/JBGroupedSplits.sol';\nimport './JBGasTokenERC20SplitsPayer.sol';\n\n/** \n @notice \n Deploys splits payer contracts.\n\n @dev\n Adheres to -\n IJBGasTokenERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBGasTokenERC20SplitsPayerDeployer is IJBGasTokenERC20SplitsPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @dev\n This contract must have Operator permissions over the SET_SPLITS permission of the specified `_defaultSplitsProjectId`.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplits The splits to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBSplitsPayer splitsPayer) {\n // Use this contract's address as the domain.\n uint256 _domain = uint256(uint160(address(this)));\n\n // Create the random hash using data unique to this instance that'll be used as the storage domain.\n uint256 _group = uint256(keccak256(abi.encodePacked(msg.sender, block.number)));\n\n // Set the splits in the store.\n JBGroupedSplits[] memory _groupedSplits;\n _groupedSplits = new JBGroupedSplits[](1);\n _groupedSplits[0] = JBGroupedSplits(_group, _defaultSplits);\n _splitsStore.set(_defaultSplitsProjectId, _domain, _groupedSplits);\n\n return\n deploySplitsPayer(\n _defaultSplitsProjectId,\n _domain,\n _group,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n }\n\n //*********************************************************************//\n // ---------------------- public transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) public override returns (IJBSplitsPayer splitsPayer) {\n // Deploy the splits payer.\n splitsPayer = new JBGasTokenERC20SplitsPayer(\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeploySplitsPayer(\n splitsPayer,\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner,\n msg.sender\n );\n }\n}\n" }, - "contracts/interfaces/IJBETHERC20SplitsPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBSplitsPayer.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBETHERC20SplitsPayerDeployer {\n event DeploySplitsPayer(\n IJBSplitsPayer indexed splitsPayer,\n uint256 defaultSplitsProjectId,\n uint256 defaultSplitsDomain,\n uint256 defaultSplitsGroup,\n IJBSplitsStore splitsStore,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n address owner,\n address caller\n );\n\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string calldata _defaultMemo,\n bytes calldata _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n}\n" + "contracts/interfaces/IJBGasTokenERC20SplitsPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBSplitsPayer.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBGasTokenERC20SplitsPayerDeployer {\n event DeploySplitsPayer(\n IJBSplitsPayer indexed splitsPayer,\n uint256 defaultSplitsProjectId,\n uint256 defaultSplitsDomain,\n uint256 defaultSplitsGroup,\n IJBSplitsStore splitsStore,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n address owner,\n address caller\n );\n\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string calldata _defaultMemo,\n bytes calldata _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n}\n" }, "contracts/system_tests/TestDistributeHeldFee.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.6;\n\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport '@paulrberg/contracts/math/PRBMathUD60x18.sol';\n\nimport './helpers/TestBaseWorkflow.sol';\n\ncontract TestDistributeHeldFee is TestBaseWorkflow {\n JBController private _controller;\n JBETHPaymentTerminal private _terminal;\n JBTokenStore private _tokenStore;\n\n JBProjectMetadata private _projectMetadata;\n JBFundingCycleData private _data;\n JBFundingCycleMetadata private _metadata;\n JBGroupedSplits[] private _groupedSplits; // Default empty\n JBFundAccessConstraints[] private _fundAccessConstraints; // Default empty\n IJBPaymentTerminal[] private _terminals; // Default empty\n\n uint256 private _projectId;\n address private _projectOwner;\n uint256 private _weight = 1000 * 10**18;\n uint256 private _targetInWei = 10 * 10**18;\n\n function setUp() public override {\n super.setUp();\n\n _controller = jbController();\n _terminal = jbETHPaymentTerminal();\n _tokenStore = jbTokenStore();\n\n _projectMetadata = JBProjectMetadata({content: 'myIPFSHash', domain: 1});\n\n _data = JBFundingCycleData({\n duration: 14,\n weight: _weight,\n discountRate: 450000000,\n ballot: IJBFundingCycleBallot(address(0))\n });\n\n _metadata = JBFundingCycleMetadata({\n global: JBGlobalFundingCycleMetadata({\n allowSetTerminals: false,\n allowSetController: false,\n pauseTransfers: false\n }),\n reservedRate: 0,\n redemptionRate: 10000, //100%\n ballotRedemptionRate: 0,\n pausePay: false,\n pauseDistributions: false,\n pauseRedeem: false,\n pauseBurn: false,\n allowMinting: false,\n allowTerminalMigration: false,\n allowControllerMigration: false,\n holdFees: true,\n preferClaimedTokenOverride: false,\n useTotalOverflowForRedemptions: false,\n useDataSourceForPay: false,\n useDataSourceForRedeem: false,\n dataSource: address(0),\n metadata: 0\n });\n\n _terminals.push(_terminal);\n\n _fundAccessConstraints.push(\n JBFundAccessConstraints({\n terminal: _terminal,\n token: jbLibraries().ETHToken(),\n distributionLimit: _targetInWei, // 10 ETH target\n overflowAllowance: 5 ether,\n distributionLimitCurrency: 1, // Currency = ETH\n overflowAllowanceCurrency: 1\n })\n );\n\n _projectOwner = multisig();\n\n _projectId = _controller.launchProjectFor(\n _projectOwner,\n _projectMetadata,\n _data,\n _metadata,\n block.timestamp,\n _groupedSplits,\n _fundAccessConstraints,\n _terminals,\n ''\n );\n }\n\n function testHeldFeeReimburse(\n uint256 payAmountInWei,\n uint16 fee,\n uint256 feeDiscount\n ) external {\n // Assuming we don't revert when distributing too much\n evm.assume(payAmountInWei <= _targetInWei);\n // Avoid rounding error\n evm.assume(payAmountInWei > 1);\n evm.assume(feeDiscount <= jbLibraries().MAX_FEE());\n evm.assume(fee <= 50_000_000); // fee cap\n address _userWallet = address(1234);\n\n evm.prank(multisig());\n _terminal.setFee(fee);\n\n IJBFeeGauge feeGauge = IJBFeeGauge(address(69696969));\n evm.etch(address(feeGauge), new bytes(0x1));\n evm.mockCall(\n address(feeGauge),\n abi.encodeWithSignature('currentDiscountFor(uint256)', _projectId),\n abi.encode(feeDiscount)\n );\n evm.prank(multisig());\n _terminal.setFeeGauge(feeGauge);\n\n uint256 discountedFee = fee - PRBMath.mulDiv(fee, feeDiscount, jbLibraries().MAX_FEE());\n\n // -- pay --\n _terminal.pay{value: payAmountInWei}(\n _projectId,\n payAmountInWei,\n address(0),\n /* _beneficiary */\n _userWallet,\n /* _minReturnedTokens */\n 0,\n /* _preferClaimedTokens */\n false,\n /* _memo */\n 'Take my money!',\n /* _delegateMetadata */\n new bytes(0)\n );\n\n // verify: beneficiary should have a balance of JBTokens\n uint256 _userTokenBalance = PRBMathUD60x18.mul(payAmountInWei, _weight);\n assertEq(_tokenStore.balanceOf(_userWallet, _projectId), _userTokenBalance);\n\n // verify: ETH balance in terminal should be up to date\n uint256 _terminalBalanceInWei = payAmountInWei;\n assertEq(jbPaymentTerminalStore().balanceOf(_terminal, _projectId), _terminalBalanceInWei);\n\n // -- distribute --\n _terminal.distributePayoutsOf(\n _projectId,\n payAmountInWei,\n jbLibraries().ETH(),\n address(0), //token (unused)\n /*min out*/\n 0,\n /*LFG*/\n 'lfg'\n );\n\n // verify: should have held the fee\n if (fee > 0) {\n assertEq(_terminal.heldFeesOf(_projectId)[0].fee, _terminal.fee());\n assertEq(_terminal.heldFeesOf(_projectId)[0].feeDiscount, feeDiscount);\n assertEq(_terminal.heldFeesOf(_projectId)[0].amount, payAmountInWei);\n }\n\n // -- add to balance --\n // Will get the fee reimbursed:\n uint256 heldFee = payAmountInWei -\n PRBMath.mulDiv(\n payAmountInWei,\n jbLibraries().MAX_FEE(),\n discountedFee + jbLibraries().MAX_FEE()\n ); // no discount\n uint256 balanceBefore = jbPaymentTerminalStore().balanceOf(_terminal, _projectId);\n _terminal.addToBalanceOf{value: payAmountInWei}(\n _projectId,\n payAmountInWei,\n address(0),\n 'thanks for all the fish',\n /* _delegateMetadata */\n new bytes(0)\n );\n\n // verify: project should get the fee back (plus the addToBalance amount)\n assertEq(\n jbPaymentTerminalStore().balanceOf(_terminal, _projectId),\n balanceBefore + heldFee + payAmountInWei\n );\n }\n\n function testFeeGetsHeldSpecialCase() public {\n uint256 feeDiscount = 0;\n uint256 fee = 50_000_000;\n uint256 payAmountInWei = 1000000000; // The same value as 100% in the split (makes it easy to leave `1` left over)\n\n JBSplit[] memory _jbSplits = new JBSplit[](1);\n _jbSplits[0] = JBSplit(\n false,\n false,\n 1000000000 - 1, // We make it so there is exactly `1` left over (note: change the subtraction to be anything else than 1 for this test to pass)\n 0,\n payable(address(5)),\n 0,\n IJBSplitAllocator(address(0))\n );\n\n JBGroupedSplits[] memory _groupedSplitsLocal = new JBGroupedSplits[](1);\n\n _groupedSplitsLocal[0] = JBGroupedSplits(_terminal.payoutSplitsGroup(), _jbSplits);\n\n _projectId = _controller.launchProjectFor(\n _projectOwner,\n _projectMetadata,\n _data,\n _metadata,\n block.timestamp,\n _groupedSplitsLocal,\n _fundAccessConstraints,\n _terminals,\n ''\n );\n\n address _userWallet = address(1234);\n evm.deal(_userWallet, payAmountInWei);\n evm.prank(multisig());\n _terminal.setFee(fee);\n\n IJBFeeGauge feeGauge = IJBFeeGauge(address(69696969));\n evm.etch(address(feeGauge), new bytes(0x1));\n evm.mockCall(\n address(feeGauge),\n abi.encodeWithSignature('currentDiscountFor(uint256)', _projectId),\n abi.encode(feeDiscount)\n );\n evm.prank(multisig());\n _terminal.setFeeGauge(feeGauge);\n\n // -- pay --\n _terminal.pay{value: payAmountInWei}(\n _projectId,\n payAmountInWei,\n address(0),\n /* _beneficiary */\n _userWallet,\n /* _minReturnedTokens */\n 0,\n /* _preferClaimedTokens */\n false,\n /* _memo */\n 'Take my money!',\n /* _delegateMetadata */\n new bytes(0)\n );\n\n // verify: ETH balance in terminal should be up to date\n uint256 _terminalBalanceInWei = payAmountInWei;\n assertEq(jbPaymentTerminalStore().balanceOf(_terminal, _projectId), _terminalBalanceInWei);\n\n // -- distribute --\n _terminal.distributePayoutsOf(\n _projectId,\n payAmountInWei,\n jbLibraries().ETH(),\n address(0), //token (unused)\n /*min out*/\n 0,\n /*LFG*/\n 'lfg'\n );\n\n // Verify that a fee was held\n assertEq(_terminal.heldFeesOf(_projectId).length, 1);\n\n // verify: should have held the fee\n assertEq(_terminal.heldFeesOf(_projectId)[0].fee, _terminal.fee());\n assertEq(_terminal.heldFeesOf(_projectId)[0].feeDiscount, feeDiscount);\n assertEq(_terminal.heldFeesOf(_projectId)[0].amount, payAmountInWei);\n }\n}\n" @@ -383,7 +383,7 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.6;\n\nimport './helpers/TestBaseWorkflow.sol';\n\ncontract TestERC20Terminal is TestBaseWorkflow {\n JBController controller;\n JBProjectMetadata _projectMetadata;\n JBFundingCycleData _data;\n JBFundingCycleMetadata _metadata;\n JBGroupedSplits[] _groupedSplits;\n JBFundAccessConstraints[] _fundAccessConstraints;\n IJBPaymentTerminal[] _terminals;\n JBTokenStore _tokenStore;\n address _projectOwner;\n\n uint256 WEIGHT = 1000 * 10**18;\n\n function setUp() public override {\n super.setUp();\n\n _projectOwner = multisig();\n\n _tokenStore = jbTokenStore();\n\n controller = jbController();\n\n _projectMetadata = JBProjectMetadata({content: 'myIPFSHash', domain: 1});\n\n _data = JBFundingCycleData({\n duration: 14,\n weight: WEIGHT,\n discountRate: 450000000,\n ballot: IJBFundingCycleBallot(address(0))\n });\n\n _metadata = JBFundingCycleMetadata({\n global: JBGlobalFundingCycleMetadata({\n allowSetTerminals: false,\n allowSetController: false,\n pauseTransfers: false\n }),\n reservedRate: 5000, //50%\n redemptionRate: 5000, //50%\n ballotRedemptionRate: 0,\n pausePay: false,\n pauseDistributions: false,\n pauseRedeem: false,\n pauseBurn: false,\n allowMinting: false,\n allowTerminalMigration: false,\n allowControllerMigration: false,\n holdFees: false,\n preferClaimedTokenOverride: false,\n useTotalOverflowForRedemptions: false,\n useDataSourceForPay: false,\n useDataSourceForRedeem: false,\n dataSource: address(0),\n metadata: 0\n });\n\n _terminals.push(jbERC20PaymentTerminal());\n }\n\n function testAllowanceERC20() public {\n JBERC20PaymentTerminal terminal = jbERC20PaymentTerminal();\n\n _fundAccessConstraints.push(\n JBFundAccessConstraints({\n terminal: terminal,\n token: address(jbToken()),\n distributionLimit: 10 * 10**18,\n overflowAllowance: 5 * 10**18,\n distributionLimitCurrency: jbLibraries().ETH(),\n overflowAllowanceCurrency: jbLibraries().ETH()\n })\n );\n\n uint256 projectId = controller.launchProjectFor(\n _projectOwner,\n _projectMetadata,\n _data,\n _metadata,\n block.timestamp,\n _groupedSplits,\n _fundAccessConstraints,\n _terminals,\n ''\n );\n\n address caller = msg.sender;\n evm.label(caller, 'caller');\n evm.prank(_projectOwner);\n jbToken().transfer(caller, 20 * 10**18);\n\n evm.prank(caller); // back to regular msg.sender (bug?)\n jbToken().approve(address(terminal), 20 * 10**18);\n evm.prank(caller); // back to regular msg.sender (bug?)\n terminal.pay(\n projectId,\n 20 * 10**18,\n address(0),\n msg.sender,\n 0,\n false,\n 'Forge test',\n new bytes(0)\n ); // funding target met and 10 token are now in the overflow\n\n // verify: beneficiary should have a balance of JBTokens (divided by 2 -> reserved rate = 50%)\n uint256 _userTokenBalance = PRBMath.mulDiv(20, WEIGHT, 2); // 18dec is in WEIGHT\n assertEq(_tokenStore.balanceOf(msg.sender, projectId), _userTokenBalance);\n\n // verify: balance in terminal should be up to date\n assertEq(jbPaymentTerminalStore().balanceOf(terminal, projectId), 20 * 10**18);\n\n // Discretionary use of overflow allowance by project owner (allowance = 5ETH)\n evm.prank(_projectOwner); // Prank only next call\n terminal.useAllowanceOf(\n projectId,\n 5 * 10**18,\n 1, // Currency\n address(0), //token (unused)\n 0, // Min wei out\n payable(msg.sender), // Beneficiary\n 'MEMO'\n );\n assertEq(\n jbToken().balanceOf(msg.sender),\n PRBMath.mulDiv(5 * 10**18, jbLibraries().MAX_FEE(), jbLibraries().MAX_FEE() + terminal.fee())\n );\n\n // Distribute the funding target ETH -> splits[] is empty -> everything in left-over, to project owner\n uint256 initBalance = jbToken().balanceOf(_projectOwner);\n evm.prank(_projectOwner);\n terminal.distributePayoutsOf(\n projectId,\n 10 * 10**18,\n 1, // Currency\n address(0), //token (unused)\n 0, // Min wei out\n 'Foundry payment' // Memo\n );\n // Funds leaving the ecosystem -> fee taken\n assertEq(\n jbToken().balanceOf(_projectOwner),\n initBalance +\n (10 * 10**18 * jbLibraries().MAX_FEE()) /\n (terminal.fee() + jbLibraries().MAX_FEE())\n );\n\n // redeem eth from the overflow by the token holder:\n uint256 senderBalance = _tokenStore.balanceOf(msg.sender, projectId);\n evm.prank(msg.sender);\n terminal.redeemTokensOf(\n msg.sender,\n projectId,\n senderBalance,\n address(0), //token (unused)\n 0,\n payable(msg.sender),\n 'gimme my money back',\n new bytes(0)\n );\n\n // verify: beneficiary should have a balance of 0 JBTokens\n assertEq(_tokenStore.balanceOf(msg.sender, projectId), 0);\n }\n\n function testFuzzedAllowanceERC20(\n uint232 ALLOWANCE,\n uint232 TARGET,\n uint96 BALANCE\n ) public {\n evm.assume(jbToken().totalSupply() >= BALANCE);\n\n JBERC20PaymentTerminal terminal = jbERC20PaymentTerminal();\n\n _fundAccessConstraints.push(\n JBFundAccessConstraints({\n terminal: terminal,\n token: address(jbToken()),\n distributionLimit: TARGET,\n overflowAllowance: ALLOWANCE,\n distributionLimitCurrency: jbLibraries().ETH(),\n overflowAllowanceCurrency: jbLibraries().ETH()\n })\n );\n\n uint256 projectId = controller.launchProjectFor(\n _projectOwner,\n _projectMetadata,\n _data,\n _metadata,\n block.timestamp,\n _groupedSplits,\n _fundAccessConstraints,\n _terminals,\n ''\n );\n\n address caller = msg.sender;\n evm.label(caller, 'caller');\n evm.prank(_projectOwner);\n jbToken().transfer(caller, BALANCE);\n\n evm.prank(caller); // back to regular msg.sender (bug?)\n jbToken().approve(address(terminal), BALANCE);\n evm.prank(caller); // back to regular msg.sender (bug?)\n terminal.pay(projectId, BALANCE, address(0), msg.sender, 0, false, 'Forge test', new bytes(0)); // funding target met and 10 ETH are now in the overflow\n\n // verify: beneficiary should have a balance of JBTokens (divided by 2 -> reserved rate = 50%)\n uint256 _userTokenBalance = PRBMath.mulDiv(BALANCE, (WEIGHT / 10**18), 2);\n if (BALANCE != 0) assertEq(_tokenStore.balanceOf(msg.sender, projectId), _userTokenBalance);\n\n // verify: ETH balance in terminal should be up to date\n assertEq(jbPaymentTerminalStore().balanceOf(terminal, projectId), BALANCE);\n\n bool willRevert;\n\n // Discretionary use of overflow allowance by project owner (allowance = 5ETH)\n if (ALLOWANCE == 0) {\n evm.expectRevert(abi.encodeWithSignature('INADEQUATE_CONTROLLER_ALLOWANCE()'));\n willRevert = true;\n } else if (TARGET >= BALANCE || ALLOWANCE > (BALANCE - TARGET)) {\n // Too much to withdraw or no overflow ?\n evm.expectRevert(abi.encodeWithSignature('INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE()'));\n willRevert = true;\n }\n\n evm.prank(_projectOwner); // Prank only next call\n terminal.useAllowanceOf(\n projectId,\n ALLOWANCE,\n 1, // Currency\n address(0), //token (unused)\n 0, // Min wei out\n payable(msg.sender), // Beneficiary\n 'MEMO'\n );\n\n if (BALANCE > 1 && !willRevert)\n assertEq(\n jbToken().balanceOf(msg.sender),\n PRBMath.mulDiv(ALLOWANCE, jbLibraries().MAX_FEE(), jbLibraries().MAX_FEE() + terminal.fee())\n );\n\n // Distribute the funding target ETH -> no split then beneficiary is the project owner\n uint256 initBalance = jbToken().balanceOf(_projectOwner);\n\n if (TARGET > BALANCE)\n evm.expectRevert(abi.encodeWithSignature('INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE()'));\n\n if (TARGET == 0)\n evm.expectRevert(abi.encodeWithSignature('DISTRIBUTION_AMOUNT_LIMIT_REACHED()'));\n\n evm.prank(_projectOwner);\n terminal.distributePayoutsOf(\n projectId,\n TARGET,\n 1, // Currency\n address(0), //token (unused)\n 0, // Min wei out\n 'Foundry payment' // Memo\n );\n // Funds leaving the ecosystem -> fee taken\n if (TARGET <= BALANCE && TARGET > 1)\n assertEq(\n jbToken().balanceOf(_projectOwner),\n initBalance +\n PRBMath.mulDiv(TARGET, jbLibraries().MAX_FEE(), terminal.fee() + jbLibraries().MAX_FEE())\n );\n\n // redeem eth from the overflow by the token holder:\n uint256 senderBalance = _tokenStore.balanceOf(msg.sender, projectId);\n\n evm.prank(msg.sender);\n terminal.redeemTokensOf(\n msg.sender,\n projectId,\n senderBalance,\n address(0), //token (unused)\n 0,\n payable(msg.sender),\n 'gimme my token back',\n new bytes(0)\n );\n\n // verify: beneficiary should have a balance of 0 JBTokens\n assertEq(_tokenStore.balanceOf(msg.sender, projectId), 0);\n }\n}\n" }, "contracts/system_tests/TestDelegates.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.6;\n\nimport './helpers/TestBaseWorkflow.sol';\n\ncontract TestDelegates is TestBaseWorkflow {\n JBController controller;\n JBProjectMetadata _projectMetadata;\n JBFundingCycleData _data;\n JBFundingCycleMetadata _metadata;\n JBGroupedSplits[] _groupedSplits;\n JBFundAccessConstraints[] _fundAccessConstraints;\n IJBPaymentTerminal[] _terminals;\n JBTokenStore _tokenStore;\n\n address _projectOwner;\n address _beneficiary;\n address _datasource = address(bytes20(keccak256('datasource')));\n\n uint256 _projectId;\n\n uint256 WEIGHT = 1000 * 10**18;\n\n function setUp() public override {\n super.setUp();\n\n _projectOwner = multisig();\n\n _beneficiary = beneficiary();\n\n _tokenStore = jbTokenStore();\n\n controller = jbController();\n\n _projectMetadata = JBProjectMetadata({content: 'myIPFSHash', domain: 1});\n\n _data = JBFundingCycleData({\n duration: 14,\n weight: WEIGHT,\n discountRate: 450000000,\n ballot: IJBFundingCycleBallot(address(0))\n });\n\n _metadata = JBFundingCycleMetadata({\n global: JBGlobalFundingCycleMetadata({\n allowSetTerminals: false,\n allowSetController: false,\n pauseTransfers: false\n }),\n reservedRate: 5000, //50%\n redemptionRate: 5000, //50%\n ballotRedemptionRate: 0,\n pausePay: false,\n pauseDistributions: false,\n pauseRedeem: false,\n pauseBurn: false,\n allowMinting: false,\n allowTerminalMigration: false,\n allowControllerMigration: false,\n holdFees: false,\n preferClaimedTokenOverride: false,\n useTotalOverflowForRedemptions: false,\n useDataSourceForPay: true,\n useDataSourceForRedeem: true,\n dataSource: _datasource,\n metadata: 0\n });\n\n _terminals.push(jbETHPaymentTerminal());\n _projectId = controller.launchProjectFor(\n _projectOwner,\n _projectMetadata,\n _data,\n _metadata,\n block.timestamp,\n _groupedSplits,\n _fundAccessConstraints,\n _terminals,\n ''\n );\n }\n\n function testPayDelegates(uint128[] memory payDelegateAmounts) public {\n JBPayDelegateAllocation[] memory _allocations = new JBPayDelegateAllocation[](\n payDelegateAmounts.length\n );\n address _beneficiary = address(bytes20(keccak256('beneficiary')));\n uint256 _paySum;\n\n // Check that we are not going to overflow uint256 and calculate the total pay amount\n for (uint256 i = 0; i < payDelegateAmounts.length; i++) {\n evm.assume(type(uint256).max - _paySum > payDelegateAmounts[i]);\n _paySum += payDelegateAmounts[i];\n }\n\n // We can't do a pay without paying\n evm.assume(_paySum > 0);\n\n (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata) = controller\n .currentFundingCycleOf(_projectId);\n for (uint256 i = 0; i < payDelegateAmounts.length; i++) {\n address _delegateAddress = address(bytes20(keccak256(abi.encodePacked('PayDelegate', i))));\n\n _allocations[i] = JBPayDelegateAllocation(\n IJBPayDelegate(_delegateAddress),\n payDelegateAmounts[i]\n );\n\n bytes memory _metadata;\n JBDidPayData memory _data = JBDidPayData(\n _beneficiary,\n _projectId,\n fundingCycle.configuration,\n JBTokenAmount(\n JBTokens.ETH,\n _paySum,\n JBSingleTokenPaymentTerminal(address(_terminals[0])).decimals(),\n JBSingleTokenPaymentTerminal(address(_terminals[0])).currency()\n ),\n JBTokenAmount(\n JBTokens.ETH,\n payDelegateAmounts[i],\n JBSingleTokenPaymentTerminal(address(_terminals[0])).decimals(),\n JBSingleTokenPaymentTerminal(address(_terminals[0])).currency()\n ),\n 0,\n _beneficiary,\n false,\n '',\n _metadata\n );\n\n // Mock the delegate\n evm.mockCall(_delegateAddress, abi.encodeWithSelector(IJBPayDelegate.didPay.selector), '');\n\n // Assert that the delegate gets called with the expected value\n evm.expectCall(\n _delegateAddress,\n payDelegateAmounts[i],\n abi.encodeWithSelector(IJBPayDelegate.didPay.selector, _data)\n );\n\n // Expect an event to be emitted for every delegate\n evm.expectEmit(true, true, true, true);\n emit DelegateDidPay(\n IJBPayDelegate(_delegateAddress),\n _data,\n payDelegateAmounts[i],\n _beneficiary\n );\n }\n\n evm.mockCall(\n _datasource,\n abi.encodeWithSelector(IJBFundingCycleDataSource.payParams.selector),\n abi.encode(\n 0, // weight\n '', // memo\n _allocations // allocations\n )\n );\n\n evm.deal(_beneficiary, _paySum);\n evm.prank(_beneficiary);\n _terminals[0].pay{value: _paySum}(\n _projectId,\n _paySum,\n address(0),\n _beneficiary,\n 0,\n false,\n 'Forge test',\n new bytes(0)\n );\n }\n\n event DelegateDidPay(\n IJBPayDelegate indexed delegate,\n JBDidPayData data,\n uint256 delegatedAmount,\n address caller\n );\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.6;\n\nimport './helpers/TestBaseWorkflow.sol';\n\ncontract TestDelegates is TestBaseWorkflow {\n JBController controller;\n JBProjectMetadata _projectMetadata;\n JBFundingCycleData _data;\n JBFundingCycleMetadata _metadata;\n JBGroupedSplits[] _groupedSplits;\n JBFundAccessConstraints[] _fundAccessConstraints;\n IJBPaymentTerminal[] _terminals;\n JBTokenStore _tokenStore;\n\n address _projectOwner;\n address _beneficiary;\n address _datasource = address(bytes20(keccak256('datasource')));\n\n uint256 _projectId;\n\n uint256 WEIGHT = 1000 * 10**18;\n\n function setUp() public override {\n super.setUp();\n\n _projectOwner = multisig();\n\n _beneficiary = beneficiary();\n\n _tokenStore = jbTokenStore();\n\n controller = jbController();\n\n _projectMetadata = JBProjectMetadata({content: 'myIPFSHash', domain: 1});\n\n _data = JBFundingCycleData({\n duration: 14,\n weight: WEIGHT,\n discountRate: 450000000,\n ballot: IJBFundingCycleBallot(address(0))\n });\n\n _metadata = JBFundingCycleMetadata({\n global: JBGlobalFundingCycleMetadata({\n allowSetTerminals: false,\n allowSetController: false,\n pauseTransfers: false\n }),\n reservedRate: 5000, //50%\n redemptionRate: 5000, //50%\n ballotRedemptionRate: 0,\n pausePay: false,\n pauseDistributions: false,\n pauseRedeem: false,\n pauseBurn: false,\n allowMinting: false,\n allowTerminalMigration: false,\n allowControllerMigration: false,\n holdFees: false,\n preferClaimedTokenOverride: false,\n useTotalOverflowForRedemptions: false,\n useDataSourceForPay: true,\n useDataSourceForRedeem: true,\n dataSource: _datasource,\n metadata: 0\n });\n\n _terminals.push(jbETHPaymentTerminal());\n _projectId = controller.launchProjectFor(\n _projectOwner,\n _projectMetadata,\n _data,\n _metadata,\n block.timestamp,\n _groupedSplits,\n _fundAccessConstraints,\n _terminals,\n ''\n );\n }\n\n function testPayDelegates(uint128[] memory payDelegateAmounts) public {\n JBPayDelegateAllocation[] memory _allocations = new JBPayDelegateAllocation[](\n payDelegateAmounts.length\n );\n address _beneficiary = address(bytes20(keccak256('beneficiary')));\n uint256 _paySum;\n\n // Check that we are not going to overflow uint256 and calculate the total pay amount\n for (uint256 i = 0; i < payDelegateAmounts.length; i++) {\n evm.assume(type(uint256).max - _paySum > payDelegateAmounts[i]);\n _paySum += payDelegateAmounts[i];\n }\n\n // We can't do a pay without paying\n evm.assume(_paySum > 0);\n\n (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata) = controller\n .currentFundingCycleOf(_projectId);\n for (uint256 i = 0; i < payDelegateAmounts.length; i++) {\n address _delegateAddress = address(bytes20(keccak256(abi.encodePacked('PayDelegate', i))));\n\n _allocations[i] = JBPayDelegateAllocation(\n IJBPayDelegate(_delegateAddress),\n payDelegateAmounts[i]\n );\n\n bytes memory _metadata;\n JBDidPayData memory _data = JBDidPayData(\n _beneficiary,\n _projectId,\n fundingCycle.configuration,\n JBTokenAmount(\n JBTokens.GAS_TOKEN,\n _paySum,\n JBSingleTokenPaymentTerminal(address(_terminals[0])).decimals(),\n JBSingleTokenPaymentTerminal(address(_terminals[0])).currency()\n ),\n JBTokenAmount(\n JBTokens.GAS_TOKEN,\n payDelegateAmounts[i],\n JBSingleTokenPaymentTerminal(address(_terminals[0])).decimals(),\n JBSingleTokenPaymentTerminal(address(_terminals[0])).currency()\n ),\n 0,\n _beneficiary,\n false,\n '',\n _metadata\n );\n\n // Mock the delegate\n evm.mockCall(_delegateAddress, abi.encodeWithSelector(IJBPayDelegate.didPay.selector), '');\n\n // Assert that the delegate gets called with the expected value\n evm.expectCall(\n _delegateAddress,\n payDelegateAmounts[i],\n abi.encodeWithSelector(IJBPayDelegate.didPay.selector, _data)\n );\n\n // Expect an event to be emitted for every delegate\n evm.expectEmit(true, true, true, true);\n emit DelegateDidPay(\n IJBPayDelegate(_delegateAddress),\n _data,\n payDelegateAmounts[i],\n _beneficiary\n );\n }\n\n evm.mockCall(\n _datasource,\n abi.encodeWithSelector(IJBFundingCycleDataSource.payParams.selector),\n abi.encode(\n 0, // weight\n '', // memo\n _allocations // allocations\n )\n );\n\n evm.deal(_beneficiary, _paySum);\n evm.prank(_beneficiary);\n _terminals[0].pay{value: _paySum}(\n _projectId,\n _paySum,\n address(0),\n _beneficiary,\n 0,\n false,\n 'Forge test',\n new bytes(0)\n );\n }\n\n event DelegateDidPay(\n IJBPayDelegate indexed delegate,\n JBDidPayData data,\n uint256 delegatedAmount,\n address caller\n );\n}\n" }, "contracts/system_tests/TestAllowance.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.6;\n\nimport './helpers/TestBaseWorkflow.sol';\n\ncontract TestAllowance is TestBaseWorkflow {\n JBController controller;\n JBProjectMetadata _projectMetadata;\n JBFundingCycleData _data;\n JBFundingCycleMetadata _metadata;\n JBGroupedSplits[] _groupedSplits;\n JBFundAccessConstraints[] _fundAccessConstraints;\n IJBPaymentTerminal[] _terminals;\n JBTokenStore _tokenStore;\n address _projectOwner;\n address _beneficiary;\n\n uint256 WEIGHT = 1000 * 10**18;\n\n function setUp() public override {\n super.setUp();\n\n _projectOwner = multisig();\n\n _beneficiary = beneficiary();\n\n _tokenStore = jbTokenStore();\n\n controller = jbController();\n\n _projectMetadata = JBProjectMetadata({content: 'myIPFSHash', domain: 1});\n\n _data = JBFundingCycleData({\n duration: 14,\n weight: WEIGHT,\n discountRate: 450000000,\n ballot: IJBFundingCycleBallot(address(0))\n });\n\n _metadata = JBFundingCycleMetadata({\n global: JBGlobalFundingCycleMetadata({\n allowSetTerminals: false,\n allowSetController: false,\n pauseTransfers: false\n }),\n reservedRate: 5000, //50%\n redemptionRate: 5000, //50%\n ballotRedemptionRate: 0,\n pausePay: false,\n pauseDistributions: false,\n pauseRedeem: false,\n pauseBurn: false,\n allowMinting: false,\n allowTerminalMigration: false,\n allowControllerMigration: false,\n holdFees: false,\n preferClaimedTokenOverride: false,\n useTotalOverflowForRedemptions: false,\n useDataSourceForPay: false,\n useDataSourceForRedeem: false,\n dataSource: address(0),\n metadata: 0\n });\n\n _terminals.push(jbETHPaymentTerminal());\n }\n\n function testAllowance() public {\n JBETHPaymentTerminal terminal = jbETHPaymentTerminal();\n\n _fundAccessConstraints.push(\n JBFundAccessConstraints({\n terminal: terminal,\n token: jbLibraries().ETHToken(),\n distributionLimit: 10 ether,\n overflowAllowance: 5 ether,\n distributionLimitCurrency: jbLibraries().ETH(),\n overflowAllowanceCurrency: jbLibraries().ETH()\n })\n );\n\n uint256 projectId = controller.launchProjectFor(\n _projectOwner,\n _projectMetadata,\n _data,\n _metadata,\n block.timestamp,\n _groupedSplits,\n _fundAccessConstraints,\n _terminals,\n ''\n );\n\n terminal.pay{value: 20 ether}(\n projectId,\n 20 ether,\n address(0),\n _beneficiary,\n 0,\n false,\n 'Forge test',\n new bytes(0)\n ); // funding target met and 10 ETH are now in the overflow\n\n // verify: beneficiary should have a balance of JBTokens (divided by 2 -> reserved rate = 50%)\n uint256 _userTokenBalance = PRBMath.mulDiv(20 ether, (WEIGHT / 10**18), 2);\n assertEq(_tokenStore.balanceOf(_beneficiary, projectId), _userTokenBalance);\n\n // verify: ETH balance in terminal should be up to date\n assertEq(jbPaymentTerminalStore().balanceOf(terminal, projectId), 20 ether);\n\n // Discretionary use of overflow allowance by project owner (allowance = 5ETH)\n evm.prank(_projectOwner); // Prank only next call\n terminal.useAllowanceOf(\n projectId,\n 5 ether,\n 1, // Currency\n address(0), //token (unused)\n 0, // Min wei out\n payable(_beneficiary), // Beneficiary\n 'MEMO'\n );\n assertEq(\n (_beneficiary).balance,\n PRBMath.mulDiv(5 ether, jbLibraries().MAX_FEE(), jbLibraries().MAX_FEE() + terminal.fee())\n );\n\n // Distribute the funding target ETH -> splits[] is empty -> everything in left-over, to project owner\n evm.prank(_projectOwner);\n terminal.distributePayoutsOf(\n projectId,\n 10 ether,\n 1, // Currency\n address(0), //token (unused)\n 0, // Min wei out\n 'Foundry payment' // Memo\n );\n assertEq(\n _projectOwner.balance,\n (10 ether * jbLibraries().MAX_FEE()) / (terminal.fee() + jbLibraries().MAX_FEE())\n );\n\n // redeem eth from the overflow by the token holder:\n uint256 senderBalance = _tokenStore.balanceOf(_beneficiary, projectId);\n evm.prank(_beneficiary);\n terminal.redeemTokensOf(\n _beneficiary,\n projectId,\n senderBalance,\n address(0), //token (unused)\n 0,\n payable(_beneficiary),\n 'gimme my money back',\n new bytes(0)\n );\n\n // verify: beneficiary should have a balance of 0 JBTokens\n assertEq(_tokenStore.balanceOf(_beneficiary, projectId), 0);\n }\n\n function testFuzzAllowance(\n uint232 ALLOWANCE,\n uint232 TARGET,\n uint96 BALANCE\n ) public {\n evm.assume(jbToken().totalSupply() >= BALANCE);\n\n unchecked {\n // Check for overflow\n evm.assume(ALLOWANCE + TARGET >= ALLOWANCE && ALLOWANCE + TARGET >= TARGET);\n }\n\n uint256 CURRENCY = jbLibraries().ETH(); // Avoid testing revert on this call...\n\n JBETHPaymentTerminal terminal = jbETHPaymentTerminal();\n\n _fundAccessConstraints.push(\n JBFundAccessConstraints({\n terminal: terminal,\n token: jbLibraries().ETHToken(),\n distributionLimit: TARGET,\n distributionLimitCurrency: CURRENCY,\n overflowAllowance: ALLOWANCE,\n overflowAllowanceCurrency: CURRENCY\n })\n );\n\n uint256 projectId = controller.launchProjectFor(\n _projectOwner,\n _projectMetadata,\n _data,\n _metadata,\n block.timestamp,\n _groupedSplits,\n _fundAccessConstraints,\n _terminals,\n ''\n );\n\n terminal.pay{value: BALANCE}(\n projectId,\n BALANCE,\n address(0),\n _beneficiary,\n 0,\n false,\n 'Forge test',\n new bytes(0)\n );\n\n // verify: beneficiary should have a balance of JBTokens (divided by 2 -> reserved rate = 50%)\n uint256 _userTokenBalance = PRBMath.mulDiv(BALANCE, (WEIGHT / 10**18), 2);\n if (BALANCE != 0) assertEq(_tokenStore.balanceOf(_beneficiary, projectId), _userTokenBalance);\n\n // verify: ETH balance in terminal should be up to date\n assertEq(jbPaymentTerminalStore().balanceOf(terminal, projectId), BALANCE);\n\n evm.startPrank(_projectOwner);\n\n bool willRevert;\n\n if (ALLOWANCE == 0) {\n evm.expectRevert(abi.encodeWithSignature('INADEQUATE_CONTROLLER_ALLOWANCE()'));\n willRevert = true;\n } else if (TARGET >= BALANCE || ALLOWANCE > (BALANCE - TARGET)) {\n // Too much to withdraw or no overflow ?\n evm.expectRevert(abi.encodeWithSignature('INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE()'));\n willRevert = true;\n }\n terminal.useAllowanceOf(\n projectId,\n ALLOWANCE,\n CURRENCY, // Currency\n address(0), //token (unused)\n 0, // Min wei out\n payable(_beneficiary), // Beneficiary\n 'MEMO'\n );\n\n if (\n !willRevert && BALANCE != 0 // if allowance ==0 or not enough overflow (target>=balance, allowance > overflow) // there is something to transfer\n )\n assertEq(\n (_beneficiary).balance,\n PRBMath.mulDiv(ALLOWANCE, jbLibraries().MAX_FEE(), jbLibraries().MAX_FEE() + terminal.fee())\n );\n\n if (TARGET > BALANCE)\n evm.expectRevert(abi.encodeWithSignature('INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE()'));\n\n if (TARGET == 0)\n evm.expectRevert(abi.encodeWithSignature('DISTRIBUTION_AMOUNT_LIMIT_REACHED()'));\n\n terminal.distributePayoutsOf(\n projectId,\n TARGET,\n 1, // Currency\n address(0), //token (unused)\n 0, // Min wei out\n 'Foundry payment' // Memo\n );\n if (TARGET <= BALANCE && TARGET > 1)\n // Avoid rounding error\n assertEq(\n _projectOwner.balance,\n (TARGET * jbLibraries().MAX_FEE()) / (terminal.fee() + jbLibraries().MAX_FEE())\n );\n }\n}\n" diff --git a/deployments/goerli/solcInputs/9d8f961b8d6848d1dd32ae08288e8c6a.json b/deployments/goerli/solcInputs/9d8f961b8d6848d1dd32ae08288e8c6a.json index e8dccc0b5..84d50d8cd 100644 --- a/deployments/goerli/solcInputs/9d8f961b8d6848d1dd32ae08288e8c6a.json +++ b/deployments/goerli/solcInputs/9d8f961b8d6848d1dd32ae08288e8c6a.json @@ -164,7 +164,7 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './../structs/JBFundAccessConstraints.sol';\nimport './../structs/JBFundingCycleData.sol';\nimport './../structs/JBFundingCycleMetadata.sol';\nimport './../structs/JBGroupedSplits.sol';\nimport './../structs/JBProjectMetadata.sol';\nimport './IJBDirectory.sol';\nimport './IJBFundingCycleStore.sol';\nimport './IJBMigratable.sol';\nimport './IJBPaymentTerminal.sol';\nimport './IJBSplitsStore.sol';\nimport './IJBTokenStore.sol';\n\ninterface IJBController is IERC165 {\n event LaunchProject(uint256 configuration, uint256 projectId, string memo, address caller);\n\n event LaunchFundingCycles(uint256 configuration, uint256 projectId, string memo, address caller);\n\n event ReconfigureFundingCycles(\n uint256 configuration,\n uint256 projectId,\n string memo,\n address caller\n );\n\n event SetFundAccessConstraints(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n JBFundAccessConstraints constraints,\n address caller\n );\n\n event DistributeReservedTokens(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address beneficiary,\n uint256 tokenCount,\n uint256 beneficiaryTokenCount,\n string memo,\n address caller\n );\n\n event DistributeToReservedTokenSplit(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n JBSplit split,\n uint256 tokenCount,\n address caller\n );\n\n event MintTokens(\n address indexed beneficiary,\n uint256 indexed projectId,\n uint256 tokenCount,\n uint256 beneficiaryTokenCount,\n string memo,\n uint256 reservedRate,\n address caller\n );\n\n event BurnTokens(\n address indexed holder,\n uint256 indexed projectId,\n uint256 tokenCount,\n string memo,\n address caller\n );\n\n event Migrate(uint256 indexed projectId, IJBMigratable to, address caller);\n\n event PrepMigration(uint256 indexed projectId, address from, address caller);\n\n function projects() external view returns (IJBProjects);\n\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\n\n function tokenStore() external view returns (IJBTokenStore);\n\n function splitsStore() external view returns (IJBSplitsStore);\n\n function directory() external view returns (IJBDirectory);\n\n function reservedTokenBalanceOf(uint256 _projectId, uint256 _reservedRate)\n external\n view\n returns (uint256);\n\n function distributionLimitOf(\n uint256 _projectId,\n uint256 _configuration,\n IJBPaymentTerminal _terminal,\n address _token\n ) external view returns (uint256 distributionLimit, uint256 distributionLimitCurrency);\n\n function overflowAllowanceOf(\n uint256 _projectId,\n uint256 _configuration,\n IJBPaymentTerminal _terminal,\n address _token\n ) external view returns (uint256 overflowAllowance, uint256 overflowAllowanceCurrency);\n\n function totalOutstandingTokensOf(uint256 _projectId, uint256 _reservedRate)\n external\n view\n returns (uint256);\n\n function getFundingCycleOf(uint256 _projectId, uint256 _configuration)\n external\n view\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\n\n function latestConfiguredFundingCycleOf(uint256 _projectId)\n external\n view\n returns (\n JBFundingCycle memory,\n JBFundingCycleMetadata memory metadata,\n JBBallotState\n );\n\n function currentFundingCycleOf(uint256 _projectId)\n external\n view\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\n\n function queuedFundingCycleOf(uint256 _projectId)\n external\n view\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\n\n function launchProjectFor(\n address _owner,\n JBProjectMetadata calldata _projectMetadata,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] memory _groupedSplits,\n JBFundAccessConstraints[] memory _fundAccessConstraints,\n IJBPaymentTerminal[] memory _terminals,\n string calldata _memo\n ) external returns (uint256 projectId);\n\n function launchFundingCyclesFor(\n uint256 _projectId,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] memory _groupedSplits,\n JBFundAccessConstraints[] memory _fundAccessConstraints,\n IJBPaymentTerminal[] memory _terminals,\n string calldata _memo\n ) external returns (uint256 configuration);\n\n function reconfigureFundingCyclesOf(\n uint256 _projectId,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] memory _groupedSplits,\n JBFundAccessConstraints[] memory _fundAccessConstraints,\n string calldata _memo\n ) external returns (uint256);\n\n function mintTokensOf(\n uint256 _projectId,\n uint256 _tokenCount,\n address _beneficiary,\n string calldata _memo,\n bool _preferClaimedTokens,\n bool _useReservedRate\n ) external returns (uint256 beneficiaryTokenCount);\n\n function burnTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string calldata _memo,\n bool _preferClaimedTokens\n ) external;\n\n function distributeReservedTokensOf(uint256 _projectId, string memory _memo)\n external\n returns (uint256);\n\n function migrate(uint256 _projectId, IJBMigratable _to) external;\n}\n" }, "contracts/JBSingleTokenPaymentTerminalStore3_1.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController3_1.sol';\nimport './interfaces/IJBFundingCycleDataSource.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './structs/JBPayDelegateAllocation.sol';\nimport './structs/JBPayParamsData.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n\n @dev\n This Store expects a project's controller to be an IJBController3_1. This is the only difference between this version and the original.\n*/\ncontract JBSingleTokenPaymentTerminalStore3_1 is\n ReentrancyGuard,\n IJBSingleTokenPaymentTerminalStore\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId);\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n JBPayDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .payParams(_data);\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\n {\n // Keep a reference to the amount that should be added to the project's balance.\n uint256 _balanceDiff = _amount.value;\n\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\n if (delegateAllocations.length != 0) {\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0) {\n // Can't delegate more than was paid.\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\n\n // Decrement the total amount being added to the balance.\n _balanceDiff = _balanceDiff - _delegatedAmount;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Add the correct balance difference to the token balance of the project.\n if (_balanceDiff != 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _balanceDiff;\n }\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId);\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow != 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\n {\n // Get a reference to the ballot state.\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\n\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n _state == JBBallotState.Active\n ? fundingCycle.ballotRedemptionRate()\n : fundingCycle.redemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\n fundingCycle.dataSource()\n ).redeemParams(_data);\n }\n } else {\n memo = _memo;\n }\n }\n\n // Keep a reference to the amount that should be subtracted from the project's balance.\n uint256 _balanceDiff = reclaimAmount;\n\n if (delegateAllocations.length != 0) {\n // Validate all delegated amounts.\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0)\n // Increment the total amount being subtracted from the balance.\n _balanceDiff = _balanceDiff + _delegatedAmount;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (_balanceDiff != 0) {\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n _balanceDiff;\n }\n }\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).fundAccessConstraintsStore().distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).fundAccessConstraintsStore().overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).fundAccessConstraintsStore().distributionLimitOf(\n _projectId,\n _fundingCycle.configuration,\n _terminal,\n _terminal.token()\n );\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n unchecked {\n return\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i; _i < _terminals.length; ) {\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n unchecked {\n ++_i;\n }\n }\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.ETH\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.ETH, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController3_1.sol';\nimport './interfaces/IJBFundingCycleDataSource.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './structs/JBPayDelegateAllocation.sol';\nimport './structs/JBPayParamsData.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n\n @dev\n This Store expects a project's controller to be an IJBController3_1. This is the only difference between this version and the original.\n*/\ncontract JBSingleTokenPaymentTerminalStore3_1 is\n ReentrancyGuard,\n IJBSingleTokenPaymentTerminalStore\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId);\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n JBPayDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .payParams(_data);\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\n {\n // Keep a reference to the amount that should be added to the project's balance.\n uint256 _balanceDiff = _amount.value;\n\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\n if (delegateAllocations.length != 0) {\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0) {\n // Can't delegate more than was paid.\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\n\n // Decrement the total amount being added to the balance.\n _balanceDiff = _balanceDiff - _delegatedAmount;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Add the correct balance difference to the token balance of the project.\n if (_balanceDiff != 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _balanceDiff;\n }\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId);\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow != 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\n {\n // Get a reference to the ballot state.\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\n\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n _state == JBBallotState.Active\n ? fundingCycle.ballotRedemptionRate()\n : fundingCycle.redemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\n fundingCycle.dataSource()\n ).redeemParams(_data);\n }\n } else {\n memo = _memo;\n }\n }\n\n // Keep a reference to the amount that should be subtracted from the project's balance.\n uint256 _balanceDiff = reclaimAmount;\n\n if (delegateAllocations.length != 0) {\n // Validate all delegated amounts.\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0)\n // Increment the total amount being subtracted from the balance.\n _balanceDiff = _balanceDiff + _delegatedAmount;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (_balanceDiff != 0) {\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n _balanceDiff;\n }\n }\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).fundAccessConstraintsStore().distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).fundAccessConstraintsStore().overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).fundAccessConstraintsStore().distributionLimitOf(\n _projectId,\n _fundingCycle.configuration,\n _terminal,\n _terminal.token()\n );\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n unchecked {\n return\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i; _i < _terminals.length; ) {\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n unchecked {\n ++_i;\n }\n }\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.GAS_CURRENCY\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.GAS_CURRENCY, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" }, "@openzeppelin/contracts/security/ReentrancyGuard.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n constructor() {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n // On the first call to nonReentrant, _notEntered will be true\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n\n _;\n\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n}\n" @@ -224,7 +224,7 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IJBPriceFeed {\n function currentPrice(uint256 _targetDecimals) external view returns (uint256);\n}\n" }, "contracts/JBSingleTokenPaymentTerminalStore.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController.sol';\nimport './interfaces/IJBFundingCycleDataSource.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './structs/JBPayDelegateAllocation.sol';\nimport './structs/JBPayParamsData.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBSingleTokenPaymentTerminalStore is ReentrancyGuard, IJBSingleTokenPaymentTerminalStore {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n JBPayDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .payParams(_data);\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\n {\n // Keep a reference to the amount that should be added to the project's balance.\n uint256 _balanceDiff = _amount.value;\n\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\n if (delegateAllocations.length != 0) {\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0) {\n // Can't delegate more than was paid.\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\n\n // Decrement the total amount being added to the balance.\n _balanceDiff = _balanceDiff - _delegatedAmount;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Add the correct balance difference to the token balance of the project.\n if (_balanceDiff != 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _balanceDiff;\n }\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\n _projectId,\n fundingCycle.reservedRate()\n );\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow != 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\n {\n // Get a reference to the ballot state.\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\n\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n _state == JBBallotState.Active\n ? fundingCycle.ballotRedemptionRate()\n : fundingCycle.redemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\n fundingCycle.dataSource()\n ).redeemParams(_data);\n }\n } else {\n memo = _memo;\n }\n }\n\n // Keep a reference to the amount that should be subtracted from the project's balance.\n uint256 _balanceDiff = reclaimAmount;\n\n if (delegateAllocations.length != 0) {\n // Validate all delegated amounts.\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0)\n // Increment the total amount being subtracted from the balance.\n _balanceDiff = _balanceDiff + _delegatedAmount;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (_balanceDiff != 0) {\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n _balanceDiff;\n }\n }\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n unchecked {\n return\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i; _i < _terminals.length; ) {\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n unchecked {\n ++_i;\n }\n }\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.ETH\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.ETH, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController.sol';\nimport './interfaces/IJBFundingCycleDataSource.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './structs/JBPayDelegateAllocation.sol';\nimport './structs/JBPayParamsData.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBSingleTokenPaymentTerminalStore is ReentrancyGuard, IJBSingleTokenPaymentTerminalStore {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n JBPayDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .payParams(_data);\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\n {\n // Keep a reference to the amount that should be added to the project's balance.\n uint256 _balanceDiff = _amount.value;\n\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\n if (delegateAllocations.length != 0) {\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0) {\n // Can't delegate more than was paid.\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\n\n // Decrement the total amount being added to the balance.\n _balanceDiff = _balanceDiff - _delegatedAmount;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Add the correct balance difference to the token balance of the project.\n if (_balanceDiff != 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _balanceDiff;\n }\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\n _projectId,\n fundingCycle.reservedRate()\n );\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow != 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\n {\n // Get a reference to the ballot state.\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\n\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n _state == JBBallotState.Active\n ? fundingCycle.ballotRedemptionRate()\n : fundingCycle.redemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\n fundingCycle.dataSource()\n ).redeemParams(_data);\n }\n } else {\n memo = _memo;\n }\n }\n\n // Keep a reference to the amount that should be subtracted from the project's balance.\n uint256 _balanceDiff = reclaimAmount;\n\n if (delegateAllocations.length != 0) {\n // Validate all delegated amounts.\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0)\n // Increment the total amount being subtracted from the balance.\n _balanceDiff = _balanceDiff + _delegatedAmount;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (_balanceDiff != 0) {\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n _balanceDiff;\n }\n }\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n unchecked {\n return\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i; _i < _terminals.length; ) {\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n unchecked {\n ++_i;\n }\n }\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.GAS_CURRENCY\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.GAS_CURRENCY, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" }, "contracts/interfaces/IJBPayoutRedemptionPaymentTerminal3_1.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './../structs/JBFee.sol';\nimport './IJBAllowanceTerminal3_1.sol';\nimport './IJBDirectory.sol';\nimport './IJBFeeGauge.sol';\nimport './IJBFeeHoldingTerminal.sol';\nimport './IJBPayDelegate.sol';\nimport './IJBPaymentTerminal.sol';\nimport './IJBPayoutTerminal3_1.sol';\nimport './IJBPrices.sol';\nimport './IJBProjects.sol';\nimport './IJBRedemptionDelegate.sol';\nimport './IJBRedemptionTerminal.sol';\nimport './IJBSingleTokenPaymentTerminalStore.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBPayoutRedemptionPaymentTerminal3_1 is\n IJBPaymentTerminal,\n IJBPayoutTerminal3_1,\n IJBAllowanceTerminal3_1,\n IJBRedemptionTerminal,\n IJBFeeHoldingTerminal\n{\n event AddToBalance(\n uint256 indexed projectId,\n uint256 amount,\n uint256 refundedFees,\n string memo,\n bytes metadata,\n address caller\n );\n\n event Migrate(\n uint256 indexed projectId,\n IJBPaymentTerminal indexed to,\n uint256 amount,\n address caller\n );\n\n event DistributePayouts(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address beneficiary,\n uint256 amount,\n uint256 distributedAmount,\n uint256 fee,\n uint256 beneficiaryDistributionAmount,\n bytes metadata,\n address caller\n );\n\n event UseAllowance(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address beneficiary,\n uint256 amount,\n uint256 distributedAmount,\n uint256 netDistributedamount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event HoldFee(\n uint256 indexed projectId,\n uint256 indexed amount,\n uint256 indexed fee,\n uint256 feeDiscount,\n address beneficiary,\n address caller\n );\n\n event ProcessFee(\n uint256 indexed projectId,\n uint256 indexed amount,\n bool indexed wasHeld,\n address beneficiary,\n address caller\n );\n\n event RefundHeldFees(\n uint256 indexed projectId,\n uint256 indexed amount,\n uint256 indexed refundedFees,\n uint256 leftoverAmount,\n address caller\n );\n\n event Pay(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address payer,\n address beneficiary,\n uint256 amount,\n uint256 beneficiaryTokenCount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DelegateDidPay(\n IJBPayDelegate indexed delegate,\n JBDidPayData data,\n uint256 delegatedAmount,\n address caller\n );\n\n event RedeemTokens(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address holder,\n address beneficiary,\n uint256 tokenCount,\n uint256 reclaimedAmount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DelegateDidRedeem(\n IJBRedemptionDelegate indexed delegate,\n JBDidRedeemData data,\n uint256 delegatedAmount,\n address caller\n );\n\n event DistributeToPayoutSplit(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n JBSplit split,\n uint256 amount,\n uint256 netAmount,\n address caller\n );\n\n event SetFee(uint256 fee, address caller);\n\n event SetFeeGauge(IJBFeeGauge indexed feeGauge, address caller);\n\n event SetFeelessAddress(address indexed addrs, bool indexed flag, address caller);\n\n event PayoutReverted(uint256 indexed projectId, JBSplit split, uint256 amount, bytes reason, address caller);\n\n event FeeReverted(\n uint256 indexed projectId,\n uint256 indexed feeProjectId,\n uint256 amount,\n bytes reason,\n address caller\n );\n\n function projects() external view returns (IJBProjects);\n\n function splitsStore() external view returns (IJBSplitsStore);\n\n function directory() external view returns (IJBDirectory);\n\n function prices() external view returns (IJBPrices);\n\n function store() external view returns (IJBSingleTokenPaymentTerminalStore);\n\n function baseWeightCurrency() external view returns (uint256);\n\n function payoutSplitsGroup() external view returns (uint256);\n\n function heldFeesOf(uint256 _projectId) external view returns (JBFee[] memory);\n\n function fee() external view returns (uint256);\n\n function feeGauge() external view returns (IJBFeeGauge);\n\n function isFeelessAddress(address _contract) external view returns (bool);\n\n function migrate(uint256 _projectId, IJBPaymentTerminal _to) external returns (uint256 balance);\n\n function processFees(uint256 _projectId) external;\n\n function setFee(uint256 _fee) external;\n\n function setFeeGauge(IJBFeeGauge _feeGauge) external;\n\n function setFeelessAddress(address _contract, bool _flag) external;\n}\n" @@ -284,10 +284,10 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nlibrary JBSplitsGroups {\n uint256 public constant ETH_PAYOUT = 1;\n uint256 public constant RESERVED_TOKENS = 2;\n}\n" }, "contracts/JBETHPaymentTerminal3_1.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal3_1.sol';\nimport './libraries/JBSplitsGroups.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal3_1: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal3_1 is JBPayoutRedemptionPaymentTerminal3_1 {\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return address(this).balance;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal3_1(\n JBTokens.ETH,\n 18, // 18 decimals.\n JBCurrencies.ETH,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal3_1.sol';\nimport './libraries/JBSplitsGroups.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal3_1: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal3_1 is JBPayoutRedemptionPaymentTerminal3_1 {\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return address(this).balance;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal3_1(\n JBTokens.GAS_TOKEN,\n 18, // 18 decimals.\n JBCurrencies.GAS_CURRENCY,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n}\n" }, "contracts/abstract/JBPayoutRedemptionPaymentTerminal3_1.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/utils/introspection/ERC165Checker.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal3_1.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBPayDelegateAllocation.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal3_1: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal3_1 is\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n IJBPayoutRedemptionPaymentTerminal3_1\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n @dev\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.ETH)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.ETH, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal3_1).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal3_1).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal3_1).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance.\n */\n function _balance() internal view virtual returns (uint256);\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n bytes calldata _metadata\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _metadata);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes calldata _metadata\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _useAllowanceOf(\n _projectId,\n _amount,\n _currency,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n // Do not refund held fees by default.\n addToBalanceOf(_projectId, _amount, _token, false, _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary, _projectId);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n bool _shouldRefundHeldFees,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.ETH) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance.\n _addToBalanceOf(_projectId, _amount, _shouldRefundHeldFees, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual {\n _from; // Prevents unused var compiler and natspec complaints.\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered if a transfer should be undone\n\n @param _to The address to which the transfer went.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _cancelTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\n {\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\n\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _forwardedAmount,\n _beneficiary,\n _memo,\n _metadata\n );\n\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\n\n emit DelegateDidRedeem(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n bytes calldata _metadata\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n }\n\n // Take the fee.\n _fee = _feeEligibleDistributionAmount != 0\n ? _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n )\n : 0;\n\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\n if (_leftoverDistributionAmount != 0) {\n // Subtract the fee from the net leftover amount.\n netLeftoverDistributionAmount =\n _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n\n // Transfer the amount to the project owner.\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes calldata _metadata\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n // The total percentage available to split\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = _split.percent == leftoverPercentage\n ? leftoverAmount\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\n\n // Decrement the leftover percentage.\n leftoverPercentage -= _split.percent;\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount = _distributeToPayoutSplit(\n _split,\n _projectId,\n _group,\n _payoutAmount,\n _feeDiscount\n );\n\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (_netPayoutAmount != 0 && _netPayoutAmount != _payoutAmount)\n feeEligibleDistributionAmount += _payoutAmount;\n\n if (_payoutAmount > 0) {\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _payoutAmount,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Pays out a split for a project's funding cycle configuration.\n \n @param _split The split to distribute payouts to.\n @param _amount The total amount being distributed to the split, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return netPayoutAmount The amount sent to the split after subtracting fees.\n */\n function _distributeToPayoutSplit(\n JBSplit memory _split,\n uint256 _projectId,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 netPayoutAmount) {\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_split.allocator)]\n )\n netPayoutAmount = _amount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\n }\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), netPayoutAmount);\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n uint256 _error;\n bytes memory _reason;\n\n if (\n ERC165Checker.supportsInterface(\n address(_split.allocator),\n type(IJBSplitAllocator).interfaceId\n )\n )\n // If this terminal's token is ETH, send it in msg.value.\n try _split.allocator.allocate{value: token == JBTokens.ETH ? netPayoutAmount : 0}(_data) {\n\n } catch (bytes memory reason) {\n _reason = reason;\n _error = 1;\n }\n else _error = 2;\n\n\n if (_error != 0) {\n // Trigger any inhereted post-transfer cancelation logic.\n _cancelTransferTo(address(_split.allocator), netPayoutAmount);\n\n // Set the net payout amount to 0 to signal the reversion.\n netPayoutAmount = 0;\n\n // Add undistributed amount back to project's balance.\n store.recordAddedBalanceFor(_projectId, _amount);\n\n emit PayoutReverted(_projectId, _split, _amount, _error == 1 ? _reason : abi.encode(\"IERC165 fail\"), msg.sender);\n }\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (\n _terminal == this ||\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\n isFeelessAddress[address(_terminal)]\n )\n netPayoutAmount = _amount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\n }\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), netPayoutAmount);\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n try\n _terminal.addToBalanceOf{value: token == JBTokens.ETH ? netPayoutAmount : 0}(\n _split.projectId,\n netPayoutAmount,\n token,\n '',\n _projectMetadata\n )\n {} catch (bytes memory reason) {\n // Trigger any inhereted post-transfer cancelation logic.\n _cancelTransferTo(address(_terminal), netPayoutAmount);\n\n // Set the net payout amount to 0 to signal the reversion.\n netPayoutAmount = 0;\n\n // Add undistributed amount back to project's balance.\n store.recordAddedBalanceFor(_projectId, _amount);\n\n emit PayoutReverted(_projectId, _split, _amount, reason, msg.sender);\n }\n else\n try\n _terminal.pay{value: token == JBTokens.ETH ? netPayoutAmount : 0}(\n _split.projectId,\n netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n )\n {} catch (bytes memory reason) {\n // Trigger any inhereted post-transfer cancelation logic.\n _cancelTransferTo(address(_terminal), netPayoutAmount);\n\n // Set the net payout amount to 0 to signal the reversion.\n netPayoutAmount = 0;\n\n // Add undistributed amount back to project's balance.\n store.recordAddedBalanceFor(_projectId, _amount);\n\n emit PayoutReverted(_projectId, _split, _amount, reason, msg.sender);\n }\n } else {\n // Keep a reference to the beneficiary.\n address payable _beneficiary = _split.beneficiary != address(0)\n ? _split.beneficiary\n : payable(msg.sender);\n\n // If there's a full discount, this distribution is not eligible for a fee.\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\n netPayoutAmount = _amount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\n else {\n unchecked {\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\n }\n }\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(address(this), _beneficiary, netPayoutAmount);\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary, _projectId); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n @param _from The project ID the fee is being paid from.\n */\n function _processFee(\n uint256 _amount,\n address _beneficiary,\n uint256 _from\n ) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _amount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_from));\n\n // Trigger any inherited pre-transfer logic if funds will be transferred.\n if (address(_terminal) != address(this)) _beforeTransferTo(address(_terminal), _amount);\n\n try\n // Send the fee.\n _terminal.pay{value: _payableValue}(\n _FEE_BENEFICIARY_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n _projectMetadata\n )\n {} catch (bytes memory reason) {\n // Trigger any inhereted post-transfer cancelation logic if the pre-transfer logic was triggered.\n if (address(_terminal) != address(this)) _cancelTransferTo(address(_terminal), _amount);\n\n // Add fee amount back to project's balance.\n store.recordAddedBalanceFor(_from, _amount);\n\n emit FeeReverted(_from, _FEE_BENEFICIARY_PROJECT_ID, _amount, reason, msg.sender);\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\n {\n JBPayDelegateAllocation[] memory _delegateAllocations;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n _forwardedAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n // Get a reference to the number of delegates to allocate to.\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\n\n emit DelegateDidPay(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n unchecked {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\n IJBPaymentTerminal(address(0))\n ) return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge != IJBFeeGauge(address(0)))\n // If the guage reverts, keep the discount at 0.\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n // If the fee discount is greater than the max, we ignore the return value\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\n } catch {\n return 0;\n }\n\n return 0;\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/utils/introspection/ERC165Checker.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal3_1.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBPayDelegateAllocation.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal3_1: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal3_1 is\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n IJBPayoutRedemptionPaymentTerminal3_1\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n @dev\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.GAS_CURRENCY)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.GAS_CURRENCY, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal3_1).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal3_1).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal3_1).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance.\n */\n function _balance() internal view virtual returns (uint256);\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n bytes calldata _metadata\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _metadata);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes calldata _metadata\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _useAllowanceOf(\n _projectId,\n _amount,\n _currency,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n // Do not refund held fees by default.\n addToBalanceOf(_projectId, _amount, _token, false, _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary, _projectId);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n bool _shouldRefundHeldFees,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.GAS_TOKEN) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance.\n _addToBalanceOf(_projectId, _amount, _shouldRefundHeldFees, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual {\n _from; // Prevents unused var compiler and natspec complaints.\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered if a transfer should be undone\n\n @param _to The address to which the transfer went.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _cancelTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\n {\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\n\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _forwardedAmount,\n _beneficiary,\n _memo,\n _metadata\n );\n\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\n\n emit DelegateDidRedeem(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n bytes calldata _metadata\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n }\n\n // Take the fee.\n _fee = _feeEligibleDistributionAmount != 0\n ? _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n )\n : 0;\n\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\n if (_leftoverDistributionAmount != 0) {\n // Subtract the fee from the net leftover amount.\n netLeftoverDistributionAmount =\n _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n\n // Transfer the amount to the project owner.\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes calldata _metadata\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n // The total percentage available to split\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = _split.percent == leftoverPercentage\n ? leftoverAmount\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\n\n // Decrement the leftover percentage.\n leftoverPercentage -= _split.percent;\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount = _distributeToPayoutSplit(\n _split,\n _projectId,\n _group,\n _payoutAmount,\n _feeDiscount\n );\n\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (_netPayoutAmount != 0 && _netPayoutAmount != _payoutAmount)\n feeEligibleDistributionAmount += _payoutAmount;\n\n if (_payoutAmount > 0) {\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _payoutAmount,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Pays out a split for a project's funding cycle configuration.\n \n @param _split The split to distribute payouts to.\n @param _amount The total amount being distributed to the split, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return netPayoutAmount The amount sent to the split after subtracting fees.\n */\n function _distributeToPayoutSplit(\n JBSplit memory _split,\n uint256 _projectId,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 netPayoutAmount) {\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_split.allocator)]\n )\n netPayoutAmount = _amount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\n }\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), netPayoutAmount);\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n uint256 _error;\n bytes memory _reason;\n\n if (\n ERC165Checker.supportsInterface(\n address(_split.allocator),\n type(IJBSplitAllocator).interfaceId\n )\n )\n // If this terminal's token is ETH, send it in msg.value.\n try _split.allocator.allocate{value: token == JBTokens.GAS_TOKEN ? netPayoutAmount : 0}(_data) {\n\n } catch (bytes memory reason) {\n _reason = reason;\n _error = 1;\n }\n else _error = 2;\n\n\n if (_error != 0) {\n // Trigger any inhereted post-transfer cancelation logic.\n _cancelTransferTo(address(_split.allocator), netPayoutAmount);\n\n // Set the net payout amount to 0 to signal the reversion.\n netPayoutAmount = 0;\n\n // Add undistributed amount back to project's balance.\n store.recordAddedBalanceFor(_projectId, _amount);\n\n emit PayoutReverted(_projectId, _split, _amount, _error == 1 ? _reason : abi.encode(\"IERC165 fail\"), msg.sender);\n }\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (\n _terminal == this ||\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\n isFeelessAddress[address(_terminal)]\n )\n netPayoutAmount = _amount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\n }\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), netPayoutAmount);\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n try\n _terminal.addToBalanceOf{value: token == JBTokens.GAS_TOKEN ? netPayoutAmount : 0}(\n _split.projectId,\n netPayoutAmount,\n token,\n '',\n _projectMetadata\n )\n {} catch (bytes memory reason) {\n // Trigger any inhereted post-transfer cancelation logic.\n _cancelTransferTo(address(_terminal), netPayoutAmount);\n\n // Set the net payout amount to 0 to signal the reversion.\n netPayoutAmount = 0;\n\n // Add undistributed amount back to project's balance.\n store.recordAddedBalanceFor(_projectId, _amount);\n\n emit PayoutReverted(_projectId, _split, _amount, reason, msg.sender);\n }\n else\n try\n _terminal.pay{value: token == JBTokens.GAS_TOKEN ? netPayoutAmount : 0}(\n _split.projectId,\n netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n )\n {} catch (bytes memory reason) {\n // Trigger any inhereted post-transfer cancelation logic.\n _cancelTransferTo(address(_terminal), netPayoutAmount);\n\n // Set the net payout amount to 0 to signal the reversion.\n netPayoutAmount = 0;\n\n // Add undistributed amount back to project's balance.\n store.recordAddedBalanceFor(_projectId, _amount);\n\n emit PayoutReverted(_projectId, _split, _amount, reason, msg.sender);\n }\n } else {\n // Keep a reference to the beneficiary.\n address payable _beneficiary = _split.beneficiary != address(0)\n ? _split.beneficiary\n : payable(msg.sender);\n\n // If there's a full discount, this distribution is not eligible for a fee.\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\n netPayoutAmount = _amount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\n else {\n unchecked {\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\n }\n }\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(address(this), _beneficiary, netPayoutAmount);\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary, _projectId); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n @param _from The project ID the fee is being paid from.\n */\n function _processFee(\n uint256 _amount,\n address _beneficiary,\n uint256 _from\n ) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_from));\n\n // Trigger any inherited pre-transfer logic if funds will be transferred.\n if (address(_terminal) != address(this)) _beforeTransferTo(address(_terminal), _amount);\n\n try\n // Send the fee.\n _terminal.pay{value: _payableValue}(\n _FEE_BENEFICIARY_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n _projectMetadata\n )\n {} catch (bytes memory reason) {\n // Trigger any inhereted post-transfer cancelation logic if the pre-transfer logic was triggered.\n if (address(_terminal) != address(this)) _cancelTransferTo(address(_terminal), _amount);\n\n // Add fee amount back to project's balance.\n store.recordAddedBalanceFor(_from, _amount);\n\n emit FeeReverted(_from, _FEE_BENEFICIARY_PROJECT_ID, _amount, reason, msg.sender);\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\n {\n JBPayDelegateAllocation[] memory _delegateAllocations;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n _forwardedAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n // Get a reference to the number of delegates to allocate to.\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\n\n emit DelegateDidPay(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n unchecked {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\n IJBPaymentTerminal(address(0))\n ) return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge != IJBFeeGauge(address(0)))\n // If the guage reverts, keep the discount at 0.\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n // If the fee discount is greater than the max, we ignore the return value\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\n } catch {\n return 0;\n }\n\n return 0;\n }\n}\n" }, "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165Checker.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Library used to query support of an interface declared via {IERC165}.\n *\n * Note that these functions return the actual result of the query: they do not\n * `revert` if an interface is not supported. It is up to the caller to decide\n * what to do in these cases.\n */\nlibrary ERC165Checker {\n // As per the EIP-165 spec, no interface should ever match 0xffffffff\n bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;\n\n /**\n * @dev Returns true if `account` supports the {IERC165} interface,\n */\n function supportsERC165(address account) internal view returns (bool) {\n // Any contract that implements ERC165 must explicitly indicate support of\n // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid\n return\n _supportsERC165Interface(account, type(IERC165).interfaceId) &&\n !_supportsERC165Interface(account, _INTERFACE_ID_INVALID);\n }\n\n /**\n * @dev Returns true if `account` supports the interface defined by\n * `interfaceId`. Support for {IERC165} itself is queried automatically.\n *\n * See {IERC165-supportsInterface}.\n */\n function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {\n // query support of both ERC165 as per the spec and support of _interfaceId\n return supportsERC165(account) && _supportsERC165Interface(account, interfaceId);\n }\n\n /**\n * @dev Returns a boolean array where each value corresponds to the\n * interfaces passed in and whether they're supported or not. This allows\n * you to batch check interfaces for a contract where your expectation\n * is that some interfaces may not be supported.\n *\n * See {IERC165-supportsInterface}.\n *\n * _Available since v3.4._\n */\n function getSupportedInterfaces(address account, bytes4[] memory interfaceIds)\n internal\n view\n returns (bool[] memory)\n {\n // an array of booleans corresponding to interfaceIds and whether they're supported or not\n bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);\n\n // query support of ERC165 itself\n if (supportsERC165(account)) {\n // query support of each interface in interfaceIds\n for (uint256 i = 0; i < interfaceIds.length; i++) {\n interfaceIdsSupported[i] = _supportsERC165Interface(account, interfaceIds[i]);\n }\n }\n\n return interfaceIdsSupported;\n }\n\n /**\n * @dev Returns true if `account` supports all the interfaces defined in\n * `interfaceIds`. Support for {IERC165} itself is queried automatically.\n *\n * Batch-querying can lead to gas savings by skipping repeated checks for\n * {IERC165} support.\n *\n * See {IERC165-supportsInterface}.\n */\n function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {\n // query support of ERC165 itself\n if (!supportsERC165(account)) {\n return false;\n }\n\n // query support of each interface in _interfaceIds\n for (uint256 i = 0; i < interfaceIds.length; i++) {\n if (!_supportsERC165Interface(account, interfaceIds[i])) {\n return false;\n }\n }\n\n // all interfaces supported\n return true;\n }\n\n /**\n * @notice Query if a contract implements an interface, does not check ERC165 support\n * @param account The address of the contract to query for support of an interface\n * @param interfaceId The interface identifier, as specified in ERC-165\n * @return true if the contract at account indicates support of the interface with\n * identifier interfaceId, false otherwise\n * @dev Assumes that account contains a contract that supports ERC165, otherwise\n * the behavior of this method is undefined. This precondition can be checked\n * with {supportsERC165}.\n * Interface identification is specified in ERC-165.\n */\n function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) {\n bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);\n (bool success, bytes memory result) = account.staticcall{gas: 30000}(encodedParams);\n if (result.length < 32) return false;\n return success && abi.decode(result, (bool));\n }\n}\n" @@ -304,29 +304,29 @@ "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n function safeTransfer(\n IERC20 token,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(\n IERC20 token,\n address from,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n uint256 newAllowance = token.allowance(address(this), spender) + value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n uint256 newAllowance = oldAllowance - value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) {\n // Return data is optional\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" }, - "contracts/JBETHERC20SplitsPayer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBSplitsPayer.sol';\nimport './interfaces/IJBSplitsStore.sol';\nimport './libraries/JBConstants.sol';\nimport './JBETHERC20ProjectPayer.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\n\n @dev\n Adheres to -\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBETHERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBETHERC20SplitsPayer is JBETHERC20ProjectPayer, ReentrancyGuard, IJBSplitsPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The ID of project for which the default splits are stored. \n */\n uint256 public override defaultSplitsProjectId;\n\n /**\n @notice\n The domain within which the default splits are stored. \n */\n uint256 public override defaultSplitsDomain;\n\n /**\n @notice\n The group within which the default splits are stored. \n */\n uint256 public override defaultSplitsGroup;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBETHERC20ProjectPayer, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n )\n JBETHERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _preferAddToBalance,\n _splitsStore.directory(),\n _owner\n )\n {\n defaultSplitsProjectId = _defaultSplitsProjectId;\n defaultSplitsDomain = _defaultSplitsDomain;\n defaultSplitsGroup = _defaultSplitsGroup;\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default split group using the stored default properties.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override nonReentrant {\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n JBTokens.ETH,\n address(this).balance,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // If there is no leftover amount, nothing left to pay.\n if (_leftoverAmount == 0) return;\n\n // If there's a default project ID, try to pay it.\n if (defaultProjectId != 0)\n if (defaultPreferAddToBalance)\n // Pay the project by adding to its balance if prefered.\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.ETH,\n _leftoverAmount,\n 18, // decimals.\n defaultMemo,\n defaultMetadata\n );\n // Otherwise, issue a payment to the project.\n else\n _pay(\n defaultProjectId,\n JBTokens.ETH,\n _leftoverAmount,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n 0, // min returned tokens.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else\n Address.sendValue(\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(tx.origin),\n _leftoverAmount\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the splits in the splits store that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n @param _groupedSplits The split groups to set.\n */\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n JBGroupedSplits[] memory _groupedSplits\n ) external virtual override onlyOwner {\n // Set the splits in the store.\n splitsStore.set(_projectId, _domain, _groupedSplits);\n\n // Set the splits reference.\n setDefaultSplitsReference(_projectId, _domain, _group);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the location of the splits that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n */\n function setDefaultSplitsReference(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) public virtual override onlyOwner {\n // Set the default splits project ID if it's changing.\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\n\n // Set the default splits domain if it's changing.\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\n\n // Set the default splits group if it's changing.\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\n\n emit SetDefaultSplitsReference(_projectId, _domain, _group, msg.sender);\n }\n\n /** \n @notice \n Make a payment to the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Pay any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to pay it.\n if (_projectId != 0) {\n _pay(\n _projectId,\n _token,\n _leftoverAmount,\n _decimals,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? payable(_beneficiary) : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit Pay(\n _projectId,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event. \n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Distribute any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to add to its balance.\n if (_projectId != 0)\n // Add to the project's balance.\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\n\n // Otherwise, send a payment to the beneficiary.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit AddToBalance(\n _projectId,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splitsProjectId The ID of the project to which the splits belong.\n @param _splitsDomain The splits domain to which the group belongs.\n @param _splitsGroup The splits group to pay.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payToSplits(\n uint256 _splitsProjectId,\n uint256 _splitsDomain,\n uint256 _splitsGroup,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Pay the splits.\n leftoverAmount = _payTo(\n splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup),\n _token,\n _amount,\n _decimals,\n _defaultBeneficiary\n );\n emit DistributeToSplitGroup(_splitsProjectId, _splitsDomain, _splitsGroup, msg.sender);\n }\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splits The splits.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payTo(\n JBSplit[] memory _splits,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Set the leftover amount to the initial balance.\n leftoverAmount = _amount;\n\n // Settle between all splits.\n for (uint256 i; i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[i];\n\n // The amount to send towards the split.\n uint256 _splitAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n if (_splitAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n _token,\n _splitAmount,\n _decimals,\n defaultProjectId,\n 0,\n _split\n );\n\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\n if (_token != JBTokens.ETH)\n IERC20(_token).safeApprove(address(_split.allocator), _splitAmount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _splitAmount : 0;\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n if (_split.preferAddToBalance)\n _addToBalanceOf(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n 0,\n _split.preferClaimed,\n defaultMemo,\n defaultMetadata\n );\n } else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : payable(_defaultBeneficiary),\n _splitAmount\n );\n // Or, transfer the ERC20.\n else {\n IERC20(_token).safeTransfer(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n _splitAmount\n );\n }\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _splitAmount;\n }\n\n emit DistributeToSplit(_split, _splitAmount, _defaultBeneficiary, msg.sender);\n\n unchecked {\n ++i;\n }\n }\n }\n}\n" + "contracts/JBGasTokenERC20SplitsPayer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBSplitsPayer.sol';\nimport './interfaces/IJBSplitsStore.sol';\nimport './libraries/JBConstants.sol';\nimport './JBGasTokenERC20ProjectPayer.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\n\n @dev\n Adheres to -\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBGasTokenERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBGasTokenERC20SplitsPayer is JBGasTokenERC20ProjectPayer, ReentrancyGuard, IJBSplitsPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The ID of project for which the default splits are stored. \n */\n uint256 public override defaultSplitsProjectId;\n\n /**\n @notice\n The domain within which the default splits are stored. \n */\n uint256 public override defaultSplitsDomain;\n\n /**\n @notice\n The group within which the default splits are stored. \n */\n uint256 public override defaultSplitsGroup;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBGasTokenERC20ProjectPayer, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n )\n JBGasTokenERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _preferAddToBalance,\n _splitsStore.directory(),\n _owner\n )\n {\n defaultSplitsProjectId = _defaultSplitsProjectId;\n defaultSplitsDomain = _defaultSplitsDomain;\n defaultSplitsGroup = _defaultSplitsGroup;\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default split group using the stored default properties.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override nonReentrant {\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // If there is no leftover amount, nothing left to pay.\n if (_leftoverAmount == 0) return;\n\n // If there's a default project ID, try to pay it.\n if (defaultProjectId != 0)\n if (defaultPreferAddToBalance)\n // Pay the project by adding to its balance if prefered.\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n _leftoverAmount,\n 18, // decimals.\n defaultMemo,\n defaultMetadata\n );\n // Otherwise, issue a payment to the project.\n else\n _pay(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n _leftoverAmount,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n 0, // min returned tokens.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else\n Address.sendValue(\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(tx.origin),\n _leftoverAmount\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the splits in the splits store that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n @param _groupedSplits The split groups to set.\n */\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n JBGroupedSplits[] memory _groupedSplits\n ) external virtual override onlyOwner {\n // Set the splits in the store.\n splitsStore.set(_projectId, _domain, _groupedSplits);\n\n // Set the splits reference.\n setDefaultSplitsReference(_projectId, _domain, _group);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the location of the splits that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n */\n function setDefaultSplitsReference(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) public virtual override onlyOwner {\n // Set the default splits project ID if it's changing.\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\n\n // Set the default splits domain if it's changing.\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\n\n // Set the default splits group if it's changing.\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\n\n emit SetDefaultSplitsReference(_projectId, _domain, _group, msg.sender);\n }\n\n /** \n @notice \n Make a payment to the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Pay any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to pay it.\n if (_projectId != 0) {\n _pay(\n _projectId,\n _token,\n _leftoverAmount,\n _decimals,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? payable(_beneficiary) : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit Pay(\n _projectId,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event. \n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Distribute any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to add to its balance.\n if (_projectId != 0)\n // Add to the project's balance.\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\n\n // Otherwise, send a payment to the beneficiary.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit AddToBalance(\n _projectId,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splitsProjectId The ID of the project to which the splits belong.\n @param _splitsDomain The splits domain to which the group belongs.\n @param _splitsGroup The splits group to pay.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payToSplits(\n uint256 _splitsProjectId,\n uint256 _splitsDomain,\n uint256 _splitsGroup,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Pay the splits.\n leftoverAmount = _payTo(\n splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup),\n _token,\n _amount,\n _decimals,\n _defaultBeneficiary\n );\n emit DistributeToSplitGroup(_splitsProjectId, _splitsDomain, _splitsGroup, msg.sender);\n }\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splits The splits.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payTo(\n JBSplit[] memory _splits,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Set the leftover amount to the initial balance.\n leftoverAmount = _amount;\n\n // Settle between all splits.\n for (uint256 i; i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[i];\n\n // The amount to send towards the split.\n uint256 _splitAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n if (_splitAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n _token,\n _splitAmount,\n _decimals,\n defaultProjectId,\n 0,\n _split\n );\n\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN)\n IERC20(_token).safeApprove(address(_split.allocator), _splitAmount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _splitAmount : 0;\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n if (_split.preferAddToBalance)\n _addToBalanceOf(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n 0,\n _split.preferClaimed,\n defaultMemo,\n defaultMetadata\n );\n } else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : payable(_defaultBeneficiary),\n _splitAmount\n );\n // Or, transfer the ERC20.\n else {\n IERC20(_token).safeTransfer(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n _splitAmount\n );\n }\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _splitAmount;\n }\n\n emit DistributeToSplit(_split, _splitAmount, _defaultBeneficiary, msg.sender);\n\n unchecked {\n ++i;\n }\n }\n }\n}\n" }, "contracts/interfaces/IJBSplitsPayer.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './../structs/JBSplit.sol';\nimport './../structs/JBGroupedSplits.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBSplitsPayer is IERC165 {\n event SetDefaultSplitsReference(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n address caller\n );\n event Pay(\n uint256 indexed projectId,\n address beneficiary,\n address token,\n uint256 amount,\n uint256 decimals,\n uint256 leftoverAmount,\n uint256 minReturnedTokens,\n bool preferClaimedTokens,\n string memo,\n bytes metadata,\n address caller\n );\n\n event AddToBalance(\n uint256 indexed projectId,\n address beneficiary,\n address token,\n uint256 amount,\n uint256 decimals,\n uint256 leftoverAmount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DistributeToSplitGroup(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n address caller\n );\n\n event DistributeToSplit(\n JBSplit split,\n uint256 amount,\n address defaultBeneficiary,\n address caller\n );\n\n function defaultSplitsProjectId() external view returns (uint256);\n\n function defaultSplitsDomain() external view returns (uint256);\n\n function defaultSplitsGroup() external view returns (uint256);\n\n function splitsStore() external view returns (IJBSplitsStore);\n\n function setDefaultSplitsReference(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) external;\n\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n JBGroupedSplits[] memory _splitsGroup\n ) external;\n}\n" }, - "contracts/JBETHERC20ProjectPayer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport './interfaces/IJBProjectPayer.sol';\nimport './libraries/JBTokens.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ERC165: Introspection on interface adherance. \n*/\ncontract JBETHERC20ProjectPayer is Ownable, ERC165, IJBProjectPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // -------------------------- custom errors -------------------------- //\n //*********************************************************************//\n error INCORRECT_DECIMAL_AMOUNT();\n error NO_MSG_VALUE_ALLOWED();\n error TERMINAL_NOT_FOUND();\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice \n A contract storing directories of terminals and controllers for each project.\n */\n IJBDirectory public immutable override directory;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The ID of the project that should be used to forward this contract's received payments.\n */\n uint256 public override defaultProjectId;\n\n /** \n @notice \n The beneficiary that should be used in the payment made when this contract receives payments.\n */\n address payable public override defaultBeneficiary;\n\n /** \n @notice \n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\n */\n bool public override defaultPreferClaimedTokens;\n\n /** \n @notice \n The memo that should be used in the payment made when this contract receives payments.\n */\n string public override defaultMemo;\n\n /** \n @notice \n The metadata that should be used in the payment made when this contract receives payments.\n */\n bytes public override defaultMetadata;\n\n /**\n @notice \n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n bool public override defaultPreferAddToBalance;\n\n //*********************************************************************//\n // ------------------------- public views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) {\n defaultProjectId = _defaultProjectId;\n defaultBeneficiary = _defaultBeneficiary;\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\n defaultMemo = _defaultMemo;\n defaultMetadata = _defaultMetadata;\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n directory = _directory;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default project ID using the stored default properties.\n\n @dev\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override {\n if (defaultPreferAddToBalance)\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.ETH,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n defaultProjectId,\n JBTokens.ETH,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultBeneficiary == address(0) ? tx.origin : defaultBeneficiary,\n 0, // Can't determine expectation of returned tokens ahead of time.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\n\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _beneficiary The address that'll receive the project's tokens. \n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _memo The memo that'll be used. \n @param _metadata The metadata that'll be sent. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external virtual override onlyOwner {\n // Set the default project ID if it has changed.\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\n\n // Set the default beneficiary if it has changed.\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\n\n // Set the default claimed token preference if it has changed.\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\n defaultPreferClaimedTokens = _preferClaimedTokens;\n\n // Set the default memo if it has changed.\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\n defaultMemo = _memo;\n\n // Set the default metadata if it has changed.\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\n defaultMetadata = _metadata;\n\n // Set the add to balance preference if it has changed.\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n\n emit SetDefaultValues(\n _projectId,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata,\n _defaultPreferAddToBalance,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _pay(\n _projectId,\n _token,\n _amount,\n _decimals,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. \n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source and delegate, if provided.\n */\n function _pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.ETH) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\n\n // Send funds to the terminal.\n // If the token is ETH, send it in msg.value.\n _terminal.pay{value: _payableValue}(\n _projectId,\n _amount, // ignored if the token is JBTokens.ETH.\n _token,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.ETH) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\n\n // Add to balance so tokens don't get issued.\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\n }\n}\n" + "contracts/JBGasTokenERC20ProjectPayer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport './interfaces/IJBProjectPayer.sol';\nimport './libraries/JBTokens.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ERC165: Introspection on interface adherance. \n*/\ncontract JBGasTokenERC20ProjectPayer is Ownable, ERC165, IJBProjectPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // -------------------------- custom errors -------------------------- //\n //*********************************************************************//\n error INCORRECT_DECIMAL_AMOUNT();\n error NO_MSG_VALUE_ALLOWED();\n error TERMINAL_NOT_FOUND();\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice \n A contract storing directories of terminals and controllers for each project.\n */\n IJBDirectory public immutable override directory;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The ID of the project that should be used to forward this contract's received payments.\n */\n uint256 public override defaultProjectId;\n\n /** \n @notice \n The beneficiary that should be used in the payment made when this contract receives payments.\n */\n address payable public override defaultBeneficiary;\n\n /** \n @notice \n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\n */\n bool public override defaultPreferClaimedTokens;\n\n /** \n @notice \n The memo that should be used in the payment made when this contract receives payments.\n */\n string public override defaultMemo;\n\n /** \n @notice \n The metadata that should be used in the payment made when this contract receives payments.\n */\n bytes public override defaultMetadata;\n\n /**\n @notice \n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n bool public override defaultPreferAddToBalance;\n\n //*********************************************************************//\n // ------------------------- public views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) {\n defaultProjectId = _defaultProjectId;\n defaultBeneficiary = _defaultBeneficiary;\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\n defaultMemo = _defaultMemo;\n defaultMetadata = _defaultMetadata;\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n directory = _directory;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default project ID using the stored default properties.\n\n @dev\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override {\n if (defaultPreferAddToBalance)\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultBeneficiary == address(0) ? tx.origin : defaultBeneficiary,\n 0, // Can't determine expectation of returned tokens ahead of time.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\n\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _beneficiary The address that'll receive the project's tokens. \n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _memo The memo that'll be used. \n @param _metadata The metadata that'll be sent. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external virtual override onlyOwner {\n // Set the default project ID if it has changed.\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\n\n // Set the default beneficiary if it has changed.\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\n\n // Set the default claimed token preference if it has changed.\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\n defaultPreferClaimedTokens = _preferClaimedTokens;\n\n // Set the default memo if it has changed.\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\n defaultMemo = _memo;\n\n // Set the default metadata if it has changed.\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\n defaultMetadata = _metadata;\n\n // Set the add to balance preference if it has changed.\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n\n emit SetDefaultValues(\n _projectId,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata,\n _defaultPreferAddToBalance,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _pay(\n _projectId,\n _token,\n _amount,\n _decimals,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. \n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source and delegate, if provided.\n */\n function _pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send funds to the terminal.\n // If the token is ETH, send it in msg.value.\n _terminal.pay{value: _payableValue}(\n _projectId,\n _amount, // ignored if the token is JBTokens.GAS_TOKEN.\n _token,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Add to balance so tokens don't get issued.\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\n }\n}\n" }, "contracts/interfaces/IJBProjectPayer.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './IJBDirectory.sol';\n\ninterface IJBProjectPayer is IERC165 {\n event SetDefaultValues(\n uint256 indexed projectId,\n address indexed beneficiary,\n bool preferClaimedTokens,\n string memo,\n bytes metadata,\n bool preferAddToBalance,\n address caller\n );\n\n function directory() external view returns (IJBDirectory);\n\n function defaultProjectId() external view returns (uint256);\n\n function defaultBeneficiary() external view returns (address payable);\n\n function defaultPreferClaimedTokens() external view returns (bool);\n\n function defaultMemo() external view returns (string memory);\n\n function defaultMetadata() external view returns (bytes memory);\n\n function defaultPreferAddToBalance() external view returns (bool);\n\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external;\n\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) external payable;\n\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) external payable;\n\n receive() external payable;\n}\n" }, - "contracts/JBETHERC20SplitsPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './interfaces/IJBETHERC20SplitsPayerDeployer.sol';\nimport './structs/JBSplit.sol';\nimport './structs/JBGroupedSplits.sol';\nimport './JBETHERC20SplitsPayer.sol';\n\n/** \n @notice \n Deploys splits payer contracts.\n\n @dev\n Adheres to -\n IJBETHERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBETHERC20SplitsPayerDeployer is IJBETHERC20SplitsPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @dev\n This contract must have Operator permissions over the SET_SPLITS permission of the specified `_defaultSplitsProjectId`.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplits The splits to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBSplitsPayer splitsPayer) {\n // Use this contract's address as the domain.\n uint256 _domain = uint256(uint160(address(this)));\n\n // Create the random hash using data unique to this instance that'll be used as the storage domain.\n uint256 _group = uint256(keccak256(abi.encodePacked(msg.sender, block.number)));\n\n // Set the splits in the store.\n JBGroupedSplits[] memory _groupedSplits;\n _groupedSplits = new JBGroupedSplits[](1);\n _groupedSplits[0] = JBGroupedSplits(_group, _defaultSplits);\n _splitsStore.set(_defaultSplitsProjectId, _domain, _groupedSplits);\n\n return\n deploySplitsPayer(\n _defaultSplitsProjectId,\n _domain,\n _group,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n }\n\n //*********************************************************************//\n // ---------------------- public transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) public override returns (IJBSplitsPayer splitsPayer) {\n // Deploy the splits payer.\n splitsPayer = new JBETHERC20SplitsPayer(\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeploySplitsPayer(\n splitsPayer,\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner,\n msg.sender\n );\n }\n}\n" + "contracts/JBGasTokenERC20SplitsPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './interfaces/IJBGasTokenERC20SplitsPayerDeployer.sol';\nimport './structs/JBSplit.sol';\nimport './structs/JBGroupedSplits.sol';\nimport './JBGasTokenERC20SplitsPayer.sol';\n\n/** \n @notice \n Deploys splits payer contracts.\n\n @dev\n Adheres to -\n IJBGasTokenERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBGasTokenERC20SplitsPayerDeployer is IJBGasTokenERC20SplitsPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @dev\n This contract must have Operator permissions over the SET_SPLITS permission of the specified `_defaultSplitsProjectId`.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplits The splits to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBSplitsPayer splitsPayer) {\n // Use this contract's address as the domain.\n uint256 _domain = uint256(uint160(address(this)));\n\n // Create the random hash using data unique to this instance that'll be used as the storage domain.\n uint256 _group = uint256(keccak256(abi.encodePacked(msg.sender, block.number)));\n\n // Set the splits in the store.\n JBGroupedSplits[] memory _groupedSplits;\n _groupedSplits = new JBGroupedSplits[](1);\n _groupedSplits[0] = JBGroupedSplits(_group, _defaultSplits);\n _splitsStore.set(_defaultSplitsProjectId, _domain, _groupedSplits);\n\n return\n deploySplitsPayer(\n _defaultSplitsProjectId,\n _domain,\n _group,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n }\n\n //*********************************************************************//\n // ---------------------- public transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) public override returns (IJBSplitsPayer splitsPayer) {\n // Deploy the splits payer.\n splitsPayer = new JBGasTokenERC20SplitsPayer(\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeploySplitsPayer(\n splitsPayer,\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner,\n msg.sender\n );\n }\n}\n" }, - "contracts/interfaces/IJBETHERC20SplitsPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBSplitsPayer.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBETHERC20SplitsPayerDeployer {\n event DeploySplitsPayer(\n IJBSplitsPayer indexed splitsPayer,\n uint256 defaultSplitsProjectId,\n uint256 defaultSplitsDomain,\n uint256 defaultSplitsGroup,\n IJBSplitsStore splitsStore,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n address owner,\n address caller\n );\n\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string calldata _defaultMemo,\n bytes calldata _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n}\n" + "contracts/interfaces/IJBGasTokenERC20SplitsPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBSplitsPayer.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBGasTokenERC20SplitsPayerDeployer {\n event DeploySplitsPayer(\n IJBSplitsPayer indexed splitsPayer,\n uint256 defaultSplitsProjectId,\n uint256 defaultSplitsDomain,\n uint256 defaultSplitsGroup,\n IJBSplitsStore splitsStore,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n address owner,\n address caller\n );\n\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string calldata _defaultMemo,\n bytes calldata _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n}\n" }, - "contracts/JBETHERC20ProjectPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './interfaces/IJBETHERC20ProjectPayerDeployer.sol';\nimport './JBETHERC20ProjectPayer.sol';\n\n/** \n @notice \n Deploys project payer contracts.\n\n @dev\n Adheres to -\n IJBETHERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBETHERC20ProjectPayerDeployer is IJBETHERC20ProjectPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new project payer contract.\n\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the project payer contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the project payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the project payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the project payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the project payer.\n\n @return projectPayer The project payer contract.\n */\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external override returns (IJBProjectPayer projectPayer) {\n // Deploy the project payer.\n projectPayer = new JBETHERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner\n );\n\n emit DeployProjectPayer(\n projectPayer,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner,\n msg.sender\n );\n }\n}\n" + "contracts/JBGasTokenERC20ProjectPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './interfaces/IJBGasTokenERC20ProjectPayerDeployer.sol';\nimport './JBGasTokenERC20ProjectPayer.sol';\n\n/** \n @notice \n Deploys project payer contracts.\n\n @dev\n Adheres to -\n IJBGasTokenERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBGasTokenERC20ProjectPayerDeployer is IJBGasTokenERC20ProjectPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new project payer contract.\n\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the project payer contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the project payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the project payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the project payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the project payer.\n\n @return projectPayer The project payer contract.\n */\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external override returns (IJBProjectPayer projectPayer) {\n // Deploy the project payer.\n projectPayer = new JBGasTokenERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner\n );\n\n emit DeployProjectPayer(\n projectPayer,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner,\n msg.sender\n );\n }\n}\n" }, - "contracts/interfaces/IJBETHERC20ProjectPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBDirectory.sol';\nimport './IJBProjectPayer.sol';\n\ninterface IJBETHERC20ProjectPayerDeployer {\n event DeployProjectPayer(\n IJBProjectPayer indexed projectPayer,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n IJBDirectory directory,\n address owner,\n address caller\n );\n\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external returns (IJBProjectPayer projectPayer);\n}\n" + "contracts/interfaces/IJBGasTokenERC20ProjectPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBDirectory.sol';\nimport './IJBProjectPayer.sol';\n\ninterface IJBGasTokenERC20ProjectPayerDeployer {\n event DeployProjectPayer(\n IJBProjectPayer indexed projectPayer,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n IJBDirectory directory,\n address owner,\n address caller\n );\n\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external returns (IJBProjectPayer projectPayer);\n}\n" }, "contracts/JBDirectory.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport './abstract/JBOperatable.sol';\nimport './interfaces/IJBDirectory.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './libraries/JBOperations.sol';\n\n/**\n @notice\n Keeps a reference of which terminal contracts each project is currently accepting funds through, and which controller contract is managing each project's tokens and funding cycles.\n\n @dev\n Adheres to -\n IJBDirectory: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\ncontract JBDirectory is JBOperatable, Ownable, IJBDirectory {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error DUPLICATE_TERMINALS();\n error INVALID_PROJECT_ID_IN_DIRECTORY();\n error SET_CONTROLLER_NOT_ALLOWED();\n error SET_TERMINALS_NOT_ALLOWED();\n error TOKEN_NOT_ACCEPTED();\n\n //*********************************************************************//\n // --------------------- private stored properties ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n For each project ID, the terminals that are currently managing its funds.\n\n _projectId The ID of the project to get terminals of.\n */\n mapping(uint256 => IJBPaymentTerminal[]) private _terminalsOf;\n\n /**\n @notice\n The project's primary terminal for a token.\n\n _projectId The ID of the project to get the primary terminal of.\n _token The token to get the project's primary terminal of.\n */\n mapping(uint256 => mapping(address => IJBPaymentTerminal)) private _primaryTerminalOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n For each project ID, the controller that manages how terminals interact with tokens and funding cycles.\n\n _projectId The ID of the project to get the controller of.\n */\n mapping(uint256 => address) public override controllerOf;\n\n /**\n @notice\n Addresses that can set a project's first controller on their behalf. These addresses/contracts have been vetted and verified by this contract's owner.\n\n _address The address that is either allowed or not.\n */\n mapping(address => bool) public override isAllowedToSetFirstController;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n For each project ID, the terminals that are currently managing its funds.\n\n @param _projectId The ID of the project to get terminals of.\n\n @return An array of terminal addresses.\n */\n function terminalsOf(uint256 _projectId)\n external\n view\n override\n returns (IJBPaymentTerminal[] memory)\n {\n return _terminalsOf[_projectId];\n }\n\n /**\n @notice\n The primary terminal that is managing funds for a project for a specified token.\n\n @dev\n The zero address is returned if a terminal isn't found for the specified token.\n\n @param _projectId The ID of the project to get a terminal for.\n @param _token The token the terminal accepts.\n\n @return The primary terminal for the project for the specified token.\n */\n function primaryTerminalOf(uint256 _projectId, address _token)\n external\n view\n override\n returns (IJBPaymentTerminal)\n {\n // Keep a reference to the primary terminal for the provided project ID and token.\n IJBPaymentTerminal _primaryTerminal = _primaryTerminalOf[_projectId][_token];\n\n // If a primary terminal for the token was specifically set and it's one of the project's terminals, return it.\n if (\n _primaryTerminal != IJBPaymentTerminal(address(0)) &&\n isTerminalOf(_projectId, _primaryTerminal)\n ) return _primaryTerminal;\n\n // Keep a reference to the number of terminals the project has.\n uint256 _numberOfTerminals = _terminalsOf[_projectId].length;\n\n // Return the first terminal which accepts the specified token.\n for (uint256 _i; _i < _numberOfTerminals; ) {\n // Keep a reference to the terminal being iterated on.\n IJBPaymentTerminal _terminal = _terminalsOf[_projectId][_i];\n\n // If the terminal accepts the specified token, return it.\n if (_terminal.acceptsToken(_token, _projectId)) return _terminal;\n\n unchecked {\n ++_i;\n }\n }\n\n // Not found.\n return IJBPaymentTerminal(address(0));\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Whether or not a specified terminal is a terminal of the specified project.\n\n @param _projectId The ID of the project to check within.\n @param _terminal The address of the terminal to check for.\n\n @return A flag indicating whether or not the specified terminal is a terminal of the specified project.\n */\n function isTerminalOf(uint256 _projectId, IJBPaymentTerminal _terminal)\n public\n view\n override\n returns (bool)\n {\n // Keep a reference to the number of terminals the project has.\n uint256 _numberOfTerminals = _terminalsOf[_projectId].length;\n\n // Loop through and return true if the terminal is contained.\n for (uint256 _i; _i < _numberOfTerminals; ) {\n // If the terminal being iterated on matches the provided terminal, return true.\n if (_terminalsOf[_projectId][_i] == _terminal) return true;\n\n unchecked {\n ++_i;\n }\n }\n\n // Otherwise, return false.\n return false;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _owner The address that will own the contract.\n */\n constructor(\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBFundingCycleStore _fundingCycleStore,\n address _owner\n ) JBOperatable(_operatorStore) {\n projects = _projects;\n fundingCycleStore = _fundingCycleStore;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Update the controller that manages how terminals interact with the ecosystem.\n\n @dev\n A controller can be set if:\n - the message sender is the project owner or an operator having the correct authorization.\n - the message sender is the project's current controller.\n - or, an allowedlisted address is setting a controller for a project that doesn't already have a controller.\n\n @param _projectId The ID of the project to set a new controller for.\n @param _controller The new controller to set.\n */\n function setControllerOf(uint256 _projectId, address _controller)\n external\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.SET_CONTROLLER,\n (msg.sender == address(controllerOf[_projectId]) ||\n (isAllowedToSetFirstController[msg.sender] && controllerOf[_projectId] == address(0)))\n )\n {\n // The project must exist.\n if (projects.count() < _projectId) revert INVALID_PROJECT_ID_IN_DIRECTORY();\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Setting controller is allowed if called from the current controller, or if the project doesn't have a current controller, or if the project's funding cycle allows setting the controller. Revert otherwise.\n if (\n msg.sender != address(controllerOf[_projectId]) &&\n controllerOf[_projectId] != address(0) &&\n !_fundingCycle.global().allowSetController\n ) revert SET_CONTROLLER_NOT_ALLOWED();\n\n // Set the new controller.\n controllerOf[_projectId] = _controller;\n\n emit SetController(_projectId, _controller, msg.sender);\n }\n\n /** \n @notice \n Set a project's terminals.\n\n @dev\n Only a project owner, an operator, or its controller can set its terminals.\n\n @param _projectId The ID of the project having terminals set.\n @param _terminals The terminal to set.\n */\n function setTerminalsOf(uint256 _projectId, IJBPaymentTerminal[] calldata _terminals)\n external\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.SET_TERMINALS,\n msg.sender == address(controllerOf[_projectId])\n )\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Setting terminals must be allowed if not called from the current controller.\n if (\n msg.sender != address(controllerOf[_projectId]) && !_fundingCycle.global().allowSetTerminals\n ) revert SET_TERMINALS_NOT_ALLOWED();\n\n // Set the stored terminals for the project.\n _terminalsOf[_projectId] = _terminals;\n\n // Make sure duplicates were not added.\n if (_terminals.length > 1) {\n for (uint256 _i; _i < _terminals.length; ) {\n for (uint256 _j = _i + 1; _j < _terminals.length; ) {\n if (_terminals[_i] == _terminals[_j]) revert DUPLICATE_TERMINALS();\n\n unchecked {\n ++_j;\n }\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n emit SetTerminals(_projectId, _terminals, msg.sender);\n }\n\n /**\n @notice\n Project's can set which terminal should be their primary for a particular token.\n This is useful in case a project has several terminals connected for a particular token.\n\n @dev\n The terminal will be set as the primary terminal where ecosystem contracts should route tokens.\n\n @dev\n If setting a newly added terminal and the funding cycle doesn't allow new terminals, the caller must be the current controller.\n\n @param _projectId The ID of the project for which a primary token is being set.\n @param _token The token to set the primary terminal of.\n @param _terminal The terminal to make primary.\n */\n function setPrimaryTerminalOf(\n uint256 _projectId,\n address _token,\n IJBPaymentTerminal _terminal\n )\n external\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.SET_PRIMARY_TERMINAL)\n {\n // Can't set the primary terminal for a token if it doesn't accept the token.\n if (!_terminal.acceptsToken(_token, _projectId)) revert TOKEN_NOT_ACCEPTED();\n\n // Add the terminal to the project if it hasn't been already.\n _addTerminalIfNeeded(_projectId, _terminal);\n\n // Store the terminal as the primary for the particular token.\n _primaryTerminalOf[_projectId][_token] = _terminal;\n\n emit SetPrimaryTerminal(_projectId, _token, _terminal, msg.sender);\n }\n\n /** \n @notice\t\n Set a contract to the list of trusted addresses that can set a first controller for any project.\t\n\n @dev\n The owner can add addresses which are allowed to change projects' first controllers. \n These addresses are known and vetted controllers as well as contracts designed to launch new projects. \n A project can set its own controller without it being on the allow list.\n\n @dev\n If you would like an address/contract allowlisted, please reach out to the contract owner.\n\n @param _address The address to allow or revoke allowance from.\n @param _flag Whether allowance is being added or revoked.\n */\n function setIsAllowedToSetFirstController(address _address, bool _flag)\n external\n override\n onlyOwner\n {\n // Set the flag in the allowlist.\n isAllowedToSetFirstController[_address] = _flag;\n\n emit SetIsAllowedToSetFirstController(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Add a terminal to a project's list of terminals if it hasn't been already.\n\n @param _projectId The ID of the project having a terminal added.\n @param _terminal The terminal to add.\n */\n function _addTerminalIfNeeded(uint256 _projectId, IJBPaymentTerminal _terminal) private {\n // Check that the terminal has not already been added.\n if (isTerminalOf(_projectId, _terminal)) return;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Setting terminals must be allowed if not called from the current controller.\n if (\n msg.sender != address(controllerOf[_projectId]) && !_fundingCycle.global().allowSetTerminals\n ) revert SET_TERMINALS_NOT_ALLOWED();\n\n // Add the new terminal.\n _terminalsOf[_projectId].push(_terminal);\n\n emit AddTerminal(_projectId, _terminal, msg.sender);\n }\n}\n" @@ -350,7 +350,7 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './interfaces/IJBOperatorStore.sol';\n\n/** \n @notice\n Stores operator permissions for all addresses. Addresses can give permissions to any other address to take specific indexed actions on their behalf.\n\n @dev\n Adheres to -\n IJBOperatorStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBOperatorStore is IJBOperatorStore {\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error PERMISSION_INDEX_OUT_OF_BOUNDS();\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice\n The permissions that an operator has been given to operate on a specific domain.\n \n @dev\n An account can give an operator permissions that only pertain to a specific domain namespace.\n There is no domain with a value of 0 – accounts can use the 0 domain to give an operator\n permissions to all domains on their behalf.\n\n @dev\n Permissions are stored in a packed `uint256`. Each 256 bits represents the on/off state of a permission. Applications can specify the significance of each index.\n\n _operator The address of the operator.\n _account The address of the account being operated.\n _domain The domain within which the permissions apply. Applications can use the domain namespace as they wish.\n */\n mapping(address => mapping(address => mapping(uint256 => uint256))) public override permissionsOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Whether or not an operator has the permission to take a certain action pertaining to the specified domain.\n\n @param _operator The operator to check.\n @param _account The account that has given out permissions to the operator.\n @param _domain The domain that the operator has been given permissions to operate.\n @param _permissionIndex The permission index to check for.\n\n @return A flag indicating whether the operator has the specified permission.\n */\n function hasPermission(\n address _operator,\n address _account,\n uint256 _domain,\n uint256 _permissionIndex\n ) external view override returns (bool) {\n if (_permissionIndex > 255) revert PERMISSION_INDEX_OUT_OF_BOUNDS();\n\n return (((permissionsOf[_operator][_account][_domain] >> _permissionIndex) & 1) == 1);\n }\n\n /** \n @notice \n Whether or not an operator has the permission to take certain actions pertaining to the specified domain.\n\n @param _operator The operator to check.\n @param _account The account that has given out permissions to the operator.\n @param _domain The domain that the operator has been given permissions to operate.\n @param _permissionIndexes An array of permission indexes to check for.\n\n @return A flag indicating whether the operator has all specified permissions.\n */\n function hasPermissions(\n address _operator,\n address _account,\n uint256 _domain,\n uint256[] calldata _permissionIndexes\n ) external view override returns (bool) {\n for (uint256 _i; _i < _permissionIndexes.length; ) {\n uint256 _permissionIndex = _permissionIndexes[_i];\n\n if (_permissionIndex > 255) revert PERMISSION_INDEX_OUT_OF_BOUNDS();\n\n if (((permissionsOf[_operator][_account][_domain] >> _permissionIndex) & 1) == 0)\n return false;\n\n unchecked {\n ++_i;\n }\n }\n return true;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Sets permissions for an operators.\n\n @dev\n Only an address can set its own operators.\n\n @param _operatorData The data that specifies the params for the operator being set.\n */\n function setOperator(JBOperatorData calldata _operatorData) external override {\n // Pack the indexes into a uint256.\n uint256 _packed = _packedPermissions(_operatorData.permissionIndexes);\n\n // Store the new value.\n permissionsOf[_operatorData.operator][msg.sender][_operatorData.domain] = _packed;\n\n emit SetOperator(\n _operatorData.operator,\n msg.sender,\n _operatorData.domain,\n _operatorData.permissionIndexes,\n _packed\n );\n }\n\n /**\n @notice\n Sets permissions for many operators.\n\n @dev\n Only an address can set its own operators.\n\n @param _operatorData The data that specify the params for each operator being set.\n */\n function setOperators(JBOperatorData[] calldata _operatorData) external override {\n for (uint256 _i; _i < _operatorData.length; ) {\n // Pack the indexes into a uint256.\n uint256 _packed = _packedPermissions(_operatorData[_i].permissionIndexes);\n\n // Store the new value.\n permissionsOf[_operatorData[_i].operator][msg.sender][_operatorData[_i].domain] = _packed;\n\n emit SetOperator(\n _operatorData[_i].operator,\n msg.sender,\n _operatorData[_i].domain,\n _operatorData[_i].permissionIndexes,\n _packed\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Converts an array of permission indexes to a packed `uint256`.\n\n @param _indexes The indexes of the permissions to pack.\n\n @return packed The packed value.\n */\n function _packedPermissions(uint256[] calldata _indexes) private pure returns (uint256 packed) {\n for (uint256 _i; _i < _indexes.length; ) {\n uint256 _index = _indexes[_i];\n\n if (_index > 255) revert PERMISSION_INDEX_OUT_OF_BOUNDS();\n\n // Turn the bit at the index on.\n packed |= 1 << _index;\n\n unchecked {\n ++_i;\n }\n }\n }\n}\n" }, "contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBPayDelegateAllocation.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal is\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n IJBPayoutRedemptionPaymentTerminal\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n @dev\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.ETH)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.ETH, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance.\n */\n function _balance() internal view virtual returns (uint256);\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.ETH) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual {\n _from; // Prevents unused var compiler and natspec complaints.\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\n {\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\n\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _forwardedAmount,\n _beneficiary,\n _memo,\n _metadata\n );\n\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\n\n emit DelegateDidRedeem(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n }\n\n // Take the fee.\n _fee = _feeEligibleDistributionAmount != 0\n ? _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n )\n : 0;\n\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\n if (_leftoverDistributionAmount != 0) {\n // Subtract the fee from the net leftover amount.\n netLeftoverDistributionAmount =\n _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n\n // Transfer the amount to the project owner.\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n // The total percentage available to split\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = _split.percent == leftoverPercentage\n ? leftoverAmount\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\n\n // Decrement the leftover percentage.\n leftoverPercentage -= _split.percent;\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount;\n\n if (_payoutAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\n isFeelessAddress[address(_split.allocator)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n _netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n // If this terminal's token is ETH, send it in msg.value.\n _split.allocator.allocate{value: token == JBTokens.ETH ? _netPayoutAmount : 0}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // Save gas if this contract is being used as the terminal.\n if (_terminal == this) {\n // This distribution does not incur a fee.\n _netPayoutAmount = _payoutAmount;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\n else\n _pay(\n _netPayoutAmount,\n address(this),\n _split.projectId,\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n } else {\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_terminal)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _netPayoutAmount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _terminal.addToBalanceOf{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n '',\n _projectMetadata\n );\n else\n _terminal.pay{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n }\n } else {\n // Keep a reference to the beneficiary.\n address payable _beneficiary = _split.beneficiary != address(0)\n ? _split.beneficiary\n : payable(msg.sender);\n\n // If there's a full discount, this distribution is not eligible for a fee.\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(address(this), _beneficiary, _netPayoutAmount);\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n */\n function _processFee(uint256 _amount, address _beneficiary) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\n\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\n if (_terminal == this)\n _pay(\n _amount,\n address(this),\n _FEE_BENEFICIARY_PROJECT_ID,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the local pay call.\n else {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _amount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _amount : 0;\n\n // Send the payment.\n _terminal.pay{value: _payableValue}(\n _FEE_BENEFICIARY_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the external pay call of the correct terminal.\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\n {\n JBPayDelegateAllocation[] memory _delegateAllocations;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n _forwardedAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n // Get a reference to the number of delegates to allocate to.\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\n\n emit DelegateDidPay(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n unchecked {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\n IJBPaymentTerminal(address(0))\n ) return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge != IJBFeeGauge(address(0)))\n // If the guage reverts, keep the discount at 0.\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n // If the fee discount is greater than the max, we ignore the return value\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\n } catch {\n return 0;\n }\n\n return 0;\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBPayDelegateAllocation.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal is\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n IJBPayoutRedemptionPaymentTerminal\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n @dev\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.GAS_CURRENCY)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.GAS_CURRENCY, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance.\n */\n function _balance() internal view virtual returns (uint256);\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.GAS_TOKEN) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual {\n _from; // Prevents unused var compiler and natspec complaints.\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\n {\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\n\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _forwardedAmount,\n _beneficiary,\n _memo,\n _metadata\n );\n\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\n\n emit DelegateDidRedeem(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n }\n\n // Take the fee.\n _fee = _feeEligibleDistributionAmount != 0\n ? _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n )\n : 0;\n\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\n if (_leftoverDistributionAmount != 0) {\n // Subtract the fee from the net leftover amount.\n netLeftoverDistributionAmount =\n _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n\n // Transfer the amount to the project owner.\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n // The total percentage available to split\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = _split.percent == leftoverPercentage\n ? leftoverAmount\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\n\n // Decrement the leftover percentage.\n leftoverPercentage -= _split.percent;\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount;\n\n if (_payoutAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\n isFeelessAddress[address(_split.allocator)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n _netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n // If this terminal's token is ETH, send it in msg.value.\n _split.allocator.allocate{value: token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // Save gas if this contract is being used as the terminal.\n if (_terminal == this) {\n // This distribution does not incur a fee.\n _netPayoutAmount = _payoutAmount;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\n else\n _pay(\n _netPayoutAmount,\n address(this),\n _split.projectId,\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n } else {\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_terminal)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _terminal.addToBalanceOf{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n '',\n _projectMetadata\n );\n else\n _terminal.pay{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n }\n } else {\n // Keep a reference to the beneficiary.\n address payable _beneficiary = _split.beneficiary != address(0)\n ? _split.beneficiary\n : payable(msg.sender);\n\n // If there's a full discount, this distribution is not eligible for a fee.\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(address(this), _beneficiary, _netPayoutAmount);\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n */\n function _processFee(uint256 _amount, address _beneficiary) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\n\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\n if (_terminal == this)\n _pay(\n _amount,\n address(this),\n _FEE_BENEFICIARY_PROJECT_ID,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the local pay call.\n else {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _amount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send the payment.\n _terminal.pay{value: _payableValue}(\n _FEE_BENEFICIARY_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the external pay call of the correct terminal.\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\n {\n JBPayDelegateAllocation[] memory _delegateAllocations;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n _forwardedAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n // Get a reference to the number of delegates to allocate to.\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\n\n emit DelegateDidPay(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n unchecked {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\n IJBPaymentTerminal(address(0))\n ) return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge != IJBFeeGauge(address(0)))\n // If the guage reverts, keep the discount at 0.\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n // If the fee discount is greater than the max, we ignore the return value\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\n } catch {\n return 0;\n }\n\n return 0;\n }\n}\n" }, "contracts/interfaces/IJBPayoutRedemptionPaymentTerminal.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './../structs/JBFee.sol';\nimport './IJBAllowanceTerminal.sol';\nimport './IJBDirectory.sol';\nimport './IJBFeeGauge.sol';\nimport './IJBPayDelegate.sol';\nimport './IJBPaymentTerminal.sol';\nimport './IJBPayoutTerminal.sol';\nimport './IJBPrices.sol';\nimport './IJBProjects.sol';\nimport './IJBRedemptionDelegate.sol';\nimport './IJBRedemptionTerminal.sol';\nimport './IJBSingleTokenPaymentTerminalStore.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBPayoutRedemptionPaymentTerminal is\n IJBPaymentTerminal,\n IJBPayoutTerminal,\n IJBAllowanceTerminal,\n IJBRedemptionTerminal\n{\n event AddToBalance(\n uint256 indexed projectId,\n uint256 amount,\n uint256 refundedFees,\n string memo,\n bytes metadata,\n address caller\n );\n\n event Migrate(\n uint256 indexed projectId,\n IJBPaymentTerminal indexed to,\n uint256 amount,\n address caller\n );\n\n event DistributePayouts(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address beneficiary,\n uint256 amount,\n uint256 distributedAmount,\n uint256 fee,\n uint256 beneficiaryDistributionAmount,\n string memo,\n address caller\n );\n\n event UseAllowance(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address beneficiary,\n uint256 amount,\n uint256 distributedAmount,\n uint256 netDistributedamount,\n string memo,\n address caller\n );\n\n event HoldFee(\n uint256 indexed projectId,\n uint256 indexed amount,\n uint256 indexed fee,\n uint256 feeDiscount,\n address beneficiary,\n address caller\n );\n\n event ProcessFee(\n uint256 indexed projectId,\n uint256 indexed amount,\n bool indexed wasHeld,\n address beneficiary,\n address caller\n );\n\n event RefundHeldFees(\n uint256 indexed projectId,\n uint256 indexed amount,\n uint256 indexed refundedFees,\n uint256 leftoverAmount,\n address caller\n );\n\n event Pay(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address payer,\n address beneficiary,\n uint256 amount,\n uint256 beneficiaryTokenCount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DelegateDidPay(\n IJBPayDelegate indexed delegate,\n JBDidPayData data,\n uint256 delegatedAmount,\n address caller\n );\n\n event RedeemTokens(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address holder,\n address beneficiary,\n uint256 tokenCount,\n uint256 reclaimedAmount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DelegateDidRedeem(\n IJBRedemptionDelegate indexed delegate,\n JBDidRedeemData data,\n uint256 delegatedAmount,\n address caller\n );\n\n event DistributeToPayoutSplit(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n JBSplit split,\n uint256 amount,\n address caller\n );\n\n event SetFee(uint256 fee, address caller);\n\n event SetFeeGauge(IJBFeeGauge indexed feeGauge, address caller);\n\n event SetFeelessAddress(address indexed addrs, bool indexed flag, address caller);\n\n function projects() external view returns (IJBProjects);\n\n function splitsStore() external view returns (IJBSplitsStore);\n\n function directory() external view returns (IJBDirectory);\n\n function prices() external view returns (IJBPrices);\n\n function store() external view returns (IJBSingleTokenPaymentTerminalStore);\n\n function baseWeightCurrency() external view returns (uint256);\n\n function payoutSplitsGroup() external view returns (uint256);\n\n function heldFeesOf(uint256 _projectId) external view returns (JBFee[] memory);\n\n function fee() external view returns (uint256);\n\n function feeGauge() external view returns (IJBFeeGauge);\n\n function isFeelessAddress(address _contract) external view returns (bool);\n\n function migrate(uint256 _projectId, IJBPaymentTerminal _to) external returns (uint256 balance);\n\n function processFees(uint256 _projectId) external;\n\n function setFee(uint256 _fee) external;\n\n function setFeeGauge(IJBFeeGauge _feeGauge) external;\n\n function setFeelessAddress(address _contract, bool _flag) external;\n}\n" @@ -362,7 +362,7 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IJBPayoutTerminal {\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) external returns (uint256 netLeftoverDistributionAmount);\n}\n" }, "contracts/JBETHPaymentTerminal.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\nimport './libraries/JBSplitsGroups.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return address(this).balance;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n JBTokens.ETH,\n 18, // 18 decimals.\n JBCurrencies.ETH,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\nimport './libraries/JBSplitsGroups.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return address(this).balance;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n JBTokens.GAS_TOKEN,\n 18, // 18 decimals.\n JBCurrencies.GAS_CURRENCY,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n}\n" }, "contracts/JBERC20PaymentTerminal.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\n\n/** \n @notice \n Manages the inflows and outflows of an ERC-20 token.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\ncontract JBERC20PaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return IERC20(token).balanceOf(address(this));\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n IERC20Metadata _token,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n address(_token),\n _token.decimals(),\n _currency,\n _baseWeightCurrency,\n _payoutSplitsGroup,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from == address(this)\n ? IERC20(token).safeTransfer(_to, _amount)\n : IERC20(token).safeTransferFrom(_from, _to, _amount);\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal override {\n IERC20(token).safeApprove(_to, _amount);\n }\n}\n" diff --git a/deployments/goerli/solcInputs/c01efb3c94c1f18d90d0889134c73f7b.json b/deployments/goerli/solcInputs/c01efb3c94c1f18d90d0889134c73f7b.json index 5d7cb2121..8d5ecbf08 100644 --- a/deployments/goerli/solcInputs/c01efb3c94c1f18d90d0889134c73f7b.json +++ b/deployments/goerli/solcInputs/c01efb3c94c1f18d90d0889134c73f7b.json @@ -161,7 +161,7 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './../structs/JBFundAccessConstraints.sol';\nimport './../structs/JBFundingCycleData.sol';\nimport './../structs/JBFundingCycleMetadata.sol';\nimport './../structs/JBGroupedSplits.sol';\nimport './../structs/JBProjectMetadata.sol';\nimport './IJBDirectory.sol';\nimport './IJBFundingCycleStore.sol';\nimport './IJBMigratable.sol';\nimport './IJBPaymentTerminal.sol';\nimport './IJBSplitsStore.sol';\nimport './IJBTokenStore.sol';\n\ninterface IJBController is IERC165 {\n event LaunchProject(uint256 configuration, uint256 projectId, string memo, address caller);\n\n event LaunchFundingCycles(uint256 configuration, uint256 projectId, string memo, address caller);\n\n event ReconfigureFundingCycles(\n uint256 configuration,\n uint256 projectId,\n string memo,\n address caller\n );\n\n event SetFundAccessConstraints(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n JBFundAccessConstraints constraints,\n address caller\n );\n\n event DistributeReservedTokens(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address beneficiary,\n uint256 tokenCount,\n uint256 beneficiaryTokenCount,\n string memo,\n address caller\n );\n\n event DistributeToReservedTokenSplit(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n JBSplit split,\n uint256 tokenCount,\n address caller\n );\n\n event MintTokens(\n address indexed beneficiary,\n uint256 indexed projectId,\n uint256 tokenCount,\n uint256 beneficiaryTokenCount,\n string memo,\n uint256 reservedRate,\n address caller\n );\n\n event BurnTokens(\n address indexed holder,\n uint256 indexed projectId,\n uint256 tokenCount,\n string memo,\n address caller\n );\n\n event Migrate(uint256 indexed projectId, IJBMigratable to, address caller);\n\n event PrepMigration(uint256 indexed projectId, address from, address caller);\n\n function projects() external view returns (IJBProjects);\n\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\n\n function tokenStore() external view returns (IJBTokenStore);\n\n function splitsStore() external view returns (IJBSplitsStore);\n\n function directory() external view returns (IJBDirectory);\n\n function reservedTokenBalanceOf(uint256 _projectId, uint256 _reservedRate)\n external\n view\n returns (uint256);\n\n function distributionLimitOf(\n uint256 _projectId,\n uint256 _configuration,\n IJBPaymentTerminal _terminal,\n address _token\n ) external view returns (uint256 distributionLimit, uint256 distributionLimitCurrency);\n\n function overflowAllowanceOf(\n uint256 _projectId,\n uint256 _configuration,\n IJBPaymentTerminal _terminal,\n address _token\n ) external view returns (uint256 overflowAllowance, uint256 overflowAllowanceCurrency);\n\n function totalOutstandingTokensOf(uint256 _projectId, uint256 _reservedRate)\n external\n view\n returns (uint256);\n\n function getFundingCycleOf(uint256 _projectId, uint256 _configuration)\n external\n view\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\n\n function latestConfiguredFundingCycleOf(uint256 _projectId)\n external\n view\n returns (\n JBFundingCycle memory,\n JBFundingCycleMetadata memory metadata,\n JBBallotState\n );\n\n function currentFundingCycleOf(uint256 _projectId)\n external\n view\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\n\n function queuedFundingCycleOf(uint256 _projectId)\n external\n view\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\n\n function launchProjectFor(\n address _owner,\n JBProjectMetadata calldata _projectMetadata,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] memory _groupedSplits,\n JBFundAccessConstraints[] memory _fundAccessConstraints,\n IJBPaymentTerminal[] memory _terminals,\n string calldata _memo\n ) external returns (uint256 projectId);\n\n function launchFundingCyclesFor(\n uint256 _projectId,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] memory _groupedSplits,\n JBFundAccessConstraints[] memory _fundAccessConstraints,\n IJBPaymentTerminal[] memory _terminals,\n string calldata _memo\n ) external returns (uint256 configuration);\n\n function reconfigureFundingCyclesOf(\n uint256 _projectId,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] memory _groupedSplits,\n JBFundAccessConstraints[] memory _fundAccessConstraints,\n string calldata _memo\n ) external returns (uint256);\n\n function mintTokensOf(\n uint256 _projectId,\n uint256 _tokenCount,\n address _beneficiary,\n string calldata _memo,\n bool _preferClaimedTokens,\n bool _useReservedRate\n ) external returns (uint256 beneficiaryTokenCount);\n\n function burnTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string calldata _memo,\n bool _preferClaimedTokens\n ) external;\n\n function distributeReservedTokensOf(uint256 _projectId, string memory _memo)\n external\n returns (uint256);\n\n function migrate(uint256 _projectId, IJBMigratable _to) external;\n}\n" }, "contracts/JBSingleTokenPaymentTerminalStore3_1.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController3_1.sol';\nimport './interfaces/IJBFundingCycleDataSource.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './structs/JBPayDelegateAllocation.sol';\nimport './structs/JBPayParamsData.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n\n @dev\n This Store expects a project's controller to be an IJBController3_1. This is the only difference between this version and the original.\n*/\ncontract JBSingleTokenPaymentTerminalStore3_1 is\n ReentrancyGuard,\n IJBSingleTokenPaymentTerminalStore\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId);\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n JBPayDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .payParams(_data);\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\n {\n // Keep a reference to the amount that should be added to the project's balance.\n uint256 _balanceDiff = _amount.value;\n\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\n if (delegateAllocations.length != 0) {\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0) {\n // Can't delegate more than was paid.\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\n\n // Decrement the total amount being added to the balance.\n _balanceDiff = _balanceDiff - _delegatedAmount;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Add the correct balance difference to the token balance of the project.\n if (_balanceDiff != 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _balanceDiff;\n }\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId);\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow != 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\n {\n // Get a reference to the ballot state.\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\n\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n _state == JBBallotState.Active\n ? fundingCycle.ballotRedemptionRate()\n : fundingCycle.redemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\n fundingCycle.dataSource()\n ).redeemParams(_data);\n }\n } else {\n memo = _memo;\n }\n }\n\n // Keep a reference to the amount that should be subtracted from the project's balance.\n uint256 _balanceDiff = reclaimAmount;\n\n if (delegateAllocations.length != 0) {\n // Validate all delegated amounts.\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0)\n // Increment the total amount being subtracted from the balance.\n _balanceDiff = _balanceDiff + _delegatedAmount;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (_balanceDiff != 0) {\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n _balanceDiff;\n }\n }\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n unchecked {\n return\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i; _i < _terminals.length; ) {\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n unchecked {\n ++_i;\n }\n }\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.ETH\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.ETH, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController3_1.sol';\nimport './interfaces/IJBFundingCycleDataSource.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './structs/JBPayDelegateAllocation.sol';\nimport './structs/JBPayParamsData.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n\n @dev\n This Store expects a project's controller to be an IJBController3_1. This is the only difference between this version and the original.\n*/\ncontract JBSingleTokenPaymentTerminalStore3_1 is\n ReentrancyGuard,\n IJBSingleTokenPaymentTerminalStore\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId);\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n JBPayDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .payParams(_data);\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\n {\n // Keep a reference to the amount that should be added to the project's balance.\n uint256 _balanceDiff = _amount.value;\n\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\n if (delegateAllocations.length != 0) {\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0) {\n // Can't delegate more than was paid.\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\n\n // Decrement the total amount being added to the balance.\n _balanceDiff = _balanceDiff - _delegatedAmount;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Add the correct balance difference to the token balance of the project.\n if (_balanceDiff != 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _balanceDiff;\n }\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId);\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow != 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\n {\n // Get a reference to the ballot state.\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\n\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n _state == JBBallotState.Active\n ? fundingCycle.ballotRedemptionRate()\n : fundingCycle.redemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\n fundingCycle.dataSource()\n ).redeemParams(_data);\n }\n } else {\n memo = _memo;\n }\n }\n\n // Keep a reference to the amount that should be subtracted from the project's balance.\n uint256 _balanceDiff = reclaimAmount;\n\n if (delegateAllocations.length != 0) {\n // Validate all delegated amounts.\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0)\n // Increment the total amount being subtracted from the balance.\n _balanceDiff = _balanceDiff + _delegatedAmount;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (_balanceDiff != 0) {\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n _balanceDiff;\n }\n }\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n unchecked {\n return\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i; _i < _terminals.length; ) {\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n unchecked {\n ++_i;\n }\n }\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.GAS_CURRENCY\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.GAS_CURRENCY, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" }, "@openzeppelin/contracts/security/ReentrancyGuard.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n constructor() {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n // On the first call to nonReentrant, _notEntered will be true\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n\n _;\n\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n}\n" @@ -221,7 +221,7 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IJBPriceFeed {\n function currentPrice(uint256 _targetDecimals) external view returns (uint256);\n}\n" }, "contracts/JBSingleTokenPaymentTerminalStore.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController.sol';\nimport './interfaces/IJBFundingCycleDataSource.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './structs/JBPayDelegateAllocation.sol';\nimport './structs/JBPayParamsData.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBSingleTokenPaymentTerminalStore is ReentrancyGuard, IJBSingleTokenPaymentTerminalStore {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n JBPayDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .payParams(_data);\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\n {\n // Keep a reference to the amount that should be added to the project's balance.\n uint256 _balanceDiff = _amount.value;\n\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\n if (delegateAllocations.length != 0) {\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0) {\n // Can't delegate more than was paid.\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\n\n // Decrement the total amount being added to the balance.\n _balanceDiff = _balanceDiff - _delegatedAmount;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Add the correct balance difference to the token balance of the project.\n if (_balanceDiff != 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _balanceDiff;\n }\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\n _projectId,\n fundingCycle.reservedRate()\n );\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow != 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\n {\n // Get a reference to the ballot state.\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\n\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n _state == JBBallotState.Active\n ? fundingCycle.ballotRedemptionRate()\n : fundingCycle.redemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\n fundingCycle.dataSource()\n ).redeemParams(_data);\n }\n } else {\n memo = _memo;\n }\n }\n\n // Keep a reference to the amount that should be subtracted from the project's balance.\n uint256 _balanceDiff = reclaimAmount;\n\n if (delegateAllocations.length != 0) {\n // Validate all delegated amounts.\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0)\n // Increment the total amount being subtracted from the balance.\n _balanceDiff = _balanceDiff + _delegatedAmount;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (_balanceDiff != 0) {\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n _balanceDiff;\n }\n }\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n unchecked {\n return\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i; _i < _terminals.length; ) {\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n unchecked {\n ++_i;\n }\n }\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.ETH\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.ETH, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController.sol';\nimport './interfaces/IJBFundingCycleDataSource.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './structs/JBPayDelegateAllocation.sol';\nimport './structs/JBPayParamsData.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBSingleTokenPaymentTerminalStore is ReentrancyGuard, IJBSingleTokenPaymentTerminalStore {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n JBPayDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .payParams(_data);\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\n {\n // Keep a reference to the amount that should be added to the project's balance.\n uint256 _balanceDiff = _amount.value;\n\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\n if (delegateAllocations.length != 0) {\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0) {\n // Can't delegate more than was paid.\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\n\n // Decrement the total amount being added to the balance.\n _balanceDiff = _balanceDiff - _delegatedAmount;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Add the correct balance difference to the token balance of the project.\n if (_balanceDiff != 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _balanceDiff;\n }\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\n _projectId,\n fundingCycle.reservedRate()\n );\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow != 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\n {\n // Get a reference to the ballot state.\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\n\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n _state == JBBallotState.Active\n ? fundingCycle.ballotRedemptionRate()\n : fundingCycle.redemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\n fundingCycle.dataSource()\n ).redeemParams(_data);\n }\n } else {\n memo = _memo;\n }\n }\n\n // Keep a reference to the amount that should be subtracted from the project's balance.\n uint256 _balanceDiff = reclaimAmount;\n\n if (delegateAllocations.length != 0) {\n // Validate all delegated amounts.\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0)\n // Increment the total amount being subtracted from the balance.\n _balanceDiff = _balanceDiff + _delegatedAmount;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (_balanceDiff != 0) {\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n _balanceDiff;\n }\n }\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n unchecked {\n return\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i; _i < _terminals.length; ) {\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n unchecked {\n ++_i;\n }\n }\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.GAS_CURRENCY\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.GAS_CURRENCY, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" }, "contracts/JBController3_1.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport '@openzeppelin/contracts/utils/math/SafeCast.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './abstract/JBOperatable.sol';\nimport './interfaces/IJBController3_1.sol';\nimport './interfaces/IJBMigratable.sol';\nimport './interfaces/IJBOperatorStore.sol';\nimport './interfaces/IJBPaymentTerminal.sol';\nimport './interfaces/IJBProjects.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './libraries/JBOperations.sol';\nimport './libraries/JBSplitsGroups.sol';\n\n/**\n @notice\n Stitches together funding cycles and project tokens, making sure all activity is accounted for and correct.\n\n @dev\n Adheres to -\n IJBController3_1: General interface for the generic controller methods in this contract that interacts with funding cycles and tokens according to the protocol's rules.\n IJBMigratable: Allows migrating to this contract, with a hook called to prepare for the migration.\n\n @dev\n Inherits from -\n JBOperatable: Several functions in this contract can only be accessed by a project owner, or an address that has been preconfifigured to be an operator of the project.\n ERC165: Introspection on interface adherance. \n\n @dev\n This Controller has the same functionality as JBController3_1, except it is not backwards compatible with the original IJBController view methods.\n*/\ncontract JBController3_1 is JBOperatable, ERC165, IJBController3_1, IJBMigratable {\n // A library that parses the packed funding cycle metadata into a more friendly format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error BURN_PAUSED_AND_SENDER_NOT_VALID_TERMINAL_DELEGATE();\n error CANT_MIGRATE_TO_CURRENT_CONTROLLER();\n error FUNDING_CYCLE_ALREADY_LAUNCHED();\n error INVALID_BALLOT_REDEMPTION_RATE();\n error INVALID_DISTRIBUTION_LIMIT();\n error INVALID_DISTRIBUTION_LIMIT_CURRENCY();\n error INVALID_OVERFLOW_ALLOWANCE();\n error INVALID_OVERFLOW_ALLOWANCE_CURRENCY();\n error INVALID_REDEMPTION_RATE();\n error INVALID_RESERVED_RATE();\n error MIGRATION_NOT_ALLOWED();\n error MINT_NOT_ALLOWED_AND_NOT_TERMINAL_DELEGATE();\n error NO_BURNABLE_TOKENS();\n error NOT_CURRENT_CONTROLLER();\n error OVERFLOW_ALERT();\n error ZERO_TOKENS_TO_MINT();\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Data regarding the distribution limit of a project during a configuration.\n\n @dev\n bits 0-231: The amount of token that a project can distribute per funding cycle.\n\n @dev\n bits 232-255: The currency of amount that a project can distribute.\n\n _projectId The ID of the project to get the packed distribution limit data of.\n _configuration The configuration during which the packed distribution limit data applies.\n _terminal The terminal from which distributions are being limited.\n _token The token for which distributions are being limited.\n */\n mapping(uint256 => mapping(uint256 => mapping(IJBPaymentTerminal => mapping(address => uint256))))\n internal _packedDistributionLimitDataOf;\n\n /**\n @notice\n Data regarding the overflow allowance of a project during a configuration.\n\n @dev\n bits 0-231: The amount of overflow that a project is allowed to tap into on-demand throughout the configuration.\n\n @dev\n bits 232-255: The currency of the amount of overflow that a project is allowed to tap.\n\n _projectId The ID of the project to get the packed overflow allowance data of.\n _configuration The configuration during which the packed overflow allowance data applies.\n _terminal The terminal managing the overflow.\n _token The token for which overflow is being allowed.\n */\n mapping(uint256 => mapping(uint256 => mapping(IJBPaymentTerminal => mapping(address => uint256))))\n internal _packedOverflowAllowanceDataOf;\n\n //*********************************************************************//\n // --------------- public immutable stored properties ---------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that manages token minting and burning.\n */\n IJBTokenStore public immutable override tokenStore;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The current undistributed reserved token balance of.\n\n _projectId The ID of the project to get a reserved token balance of.\n */\n mapping(uint256 => uint256) public override reservedTokenBalanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of token that a project can distribute per funding cycle, and the currency it's in terms of.\n\n @dev\n The number of decimals in the returned fixed point amount is the same as that of the specified terminal. \n\n @param _projectId The ID of the project to get the distribution limit of.\n @param _configuration The configuration during which the distribution limit applies.\n @param _terminal The terminal from which distributions are being limited.\n @param _token The token for which the distribution limit applies.\n\n @return The distribution limit, as a fixed point number with the same number of decimals as the provided terminal.\n @return The currency of the distribution limit.\n */\n function distributionLimitOf(\n uint256 _projectId,\n uint256 _configuration,\n IJBPaymentTerminal _terminal,\n address _token\n ) external view override returns (uint256, uint256) {\n // Get a reference to the packed data.\n uint256 _data = _packedDistributionLimitDataOf[_projectId][_configuration][_terminal][_token];\n\n // The limit is in bits 0-231. The currency is in bits 232-255.\n return (uint256(uint232(_data)), _data >> 232);\n }\n\n /**\n @notice\n The amount of overflow that a project is allowed to tap into on-demand throughout a configuration, and the currency it's in terms of.\n\n @dev\n The number of decimals in the returned fixed point amount is the same as that of the specified terminal. \n\n @param _projectId The ID of the project to get the overflow allowance of.\n @param _configuration The configuration of the during which the allowance applies.\n @param _terminal The terminal managing the overflow.\n @param _token The token for which the overflow allowance applies.\n\n @return The overflow allowance, as a fixed point number with the same number of decimals as the provided terminal.\n @return The currency of the overflow allowance.\n */\n function overflowAllowanceOf(\n uint256 _projectId,\n uint256 _configuration,\n IJBPaymentTerminal _terminal,\n address _token\n ) external view override returns (uint256, uint256) {\n // Get a reference to the packed data.\n uint256 _data = _packedOverflowAllowanceDataOf[_projectId][_configuration][_terminal][_token];\n\n // The allowance is in bits 0-231. The currency is in bits 232-255.\n return (uint256(uint232(_data)), _data >> 232);\n }\n\n /** \n @notice\n A project's funding cycle for the specified configuration along with its metadata.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n \n @return fundingCycle The funding cycle.\n @return metadata The funding cycle's metadata.\n */\n function getFundingCycleOf(uint256 _projectId, uint256 _configuration)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata)\n {\n fundingCycle = fundingCycleStore.get(_projectId, _configuration);\n metadata = fundingCycle.expandMetadata();\n }\n\n /** \n @notice\n A project's latest configured funding cycle along with its metadata and the ballot state of the configuration.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n \n @return fundingCycle The latest configured funding cycle.\n @return metadata The latest configured funding cycle's metadata.\n @return ballotState The state of the configuration.\n */\n function latestConfiguredFundingCycleOf(uint256 _projectId)\n external\n view\n override\n returns (\n JBFundingCycle memory fundingCycle,\n JBFundingCycleMetadata memory metadata,\n JBBallotState ballotState\n )\n {\n (fundingCycle, ballotState) = fundingCycleStore.latestConfiguredOf(_projectId);\n metadata = fundingCycle.expandMetadata();\n }\n\n /** \n @notice\n A project's current funding cycle along with its metadata.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n \n @return fundingCycle The current funding cycle.\n @return metadata The current funding cycle's metadata.\n */\n function currentFundingCycleOf(uint256 _projectId)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata)\n {\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n metadata = fundingCycle.expandMetadata();\n }\n\n /** \n @notice\n A project's queued funding cycle along with its metadata.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n \n @return fundingCycle The queued funding cycle.\n @return metadata The queued funding cycle's metadata.\n */\n function queuedFundingCycleOf(uint256 _projectId)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata)\n {\n fundingCycle = fundingCycleStore.queuedOf(_projectId);\n metadata = fundingCycle.expandMetadata();\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current total amount of outstanding tokens for a project.\n\n @param _projectId The ID of the project to get total outstanding tokens of.\n\n @return The current total amount of outstanding tokens for the project.\n */\n function totalOutstandingTokensOf(uint256 _projectId) public view override returns (uint256) {\n // Add the reserved tokens to the total supply.\n return tokenStore.totalSupplyOf(_projectId) + reservedTokenBalanceOf[_projectId];\n }\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBController3_1).interfaceId ||\n _interfaceId == type(IJBController3_0_1).interfaceId ||\n _interfaceId == type(IJBMigratable).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // ---------------------------- constructor -------------------------- //\n //*********************************************************************//\n\n /**\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _tokenStore A contract that manages token minting and burning.\n @param _splitsStore A contract that stores splits for each project.\n */\n constructor(\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBTokenStore _tokenStore,\n IJBSplitsStore _splitsStore\n ) JBOperatable(_operatorStore) {\n projects = _projects;\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n tokenStore = _tokenStore;\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // --------------------- external transactions ----------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Creates a project. This will mint an ERC-721 into the specified owner's account, configure a first funding cycle, and set up any splits.\n\n @dev\n Each operation within this transaction can be done in sequence separately.\n\n @dev\n Anyone can deploy a project on an owner's behalf.\n\n @param _owner The address to set as the owner of the project. The project ERC-721 will be owned by this address.\n @param _projectMetadata Metadata to associate with the project within a particular domain. This can be updated any time by the owner of the project.\n @param _data Data that defines the project's first funding cycle. These properties will remain fixed for the duration of the funding cycle.\n @param _metadata Metadata specifying the controller specific params that a funding cycle can have. These properties will remain fixed for the duration of the funding cycle.\n @param _mustStartAtOrAfter The time before which the configured funding cycle cannot start.\n @param _groupedSplits An array of splits to set for any number of groups. \n @param _fundAccessConstraints An array containing amounts that a project can use from its treasury for each payment terminal. Amounts are fixed point numbers using the same number of decimals as the accompanying terminal. The `_distributionLimit` and `_overflowAllowance` parameters must fit in a `uint232`.\n @param _terminals Payment terminals to add for the project.\n @param _memo A memo to pass along to the emitted event.\n\n @return projectId The ID of the project.\n */\n function launchProjectFor(\n address _owner,\n JBProjectMetadata calldata _projectMetadata,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] calldata _groupedSplits,\n JBFundAccessConstraints[] calldata _fundAccessConstraints,\n IJBPaymentTerminal[] memory _terminals,\n string memory _memo\n ) external virtual override returns (uint256 projectId) {\n // Keep a reference to the directory.\n IJBDirectory _directory = directory;\n\n // Mint the project into the wallet of the owner.\n projectId = projects.createFor(_owner, _projectMetadata);\n\n // Set this contract as the project's controller in the directory.\n _directory.setControllerOf(projectId, address(this));\n\n // Configure the first funding cycle.\n uint256 _configuration = _configure(\n projectId,\n _data,\n _metadata,\n _mustStartAtOrAfter,\n _groupedSplits,\n _fundAccessConstraints\n );\n\n // Add the provided terminals to the list of terminals.\n if (_terminals.length > 0) _directory.setTerminalsOf(projectId, _terminals);\n\n emit LaunchProject(_configuration, projectId, _memo, msg.sender);\n }\n\n /**\n @notice\n Creates a funding cycle for an already existing project ERC-721.\n\n @dev\n Each operation within this transaction can be done in sequence separately.\n\n @dev\n Only a project owner or operator can launch its funding cycles.\n\n @param _projectId The ID of the project to launch funding cycles for.\n @param _data Data that defines the project's first funding cycle. These properties will remain fixed for the duration of the funding cycle.\n @param _metadata Metadata specifying the controller specific params that a funding cycle can have. These properties will remain fixed for the duration of the funding cycle.\n @param _mustStartAtOrAfter The time before which the configured funding cycle cannot start.\n @param _groupedSplits An array of splits to set for any number of groups. \n @param _fundAccessConstraints An array containing amounts that a project can use from its treasury for each payment terminal. Amounts are fixed point numbers using the same number of decimals as the accompanying terminal. The `_distributionLimit` and `_overflowAllowance` parameters must fit in a `uint232`.\n @param _terminals Payment terminals to add for the project.\n @param _memo A memo to pass along to the emitted event.\n\n @return configuration The configuration of the funding cycle that was successfully created.\n */\n function launchFundingCyclesFor(\n uint256 _projectId,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] calldata _groupedSplits,\n JBFundAccessConstraints[] memory _fundAccessConstraints,\n IJBPaymentTerminal[] memory _terminals,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.RECONFIGURE)\n returns (uint256 configuration)\n {\n // If there is a previous configuration, reconfigureFundingCyclesOf should be called instead\n if (fundingCycleStore.latestConfigurationOf(_projectId) > 0)\n revert FUNDING_CYCLE_ALREADY_LAUNCHED();\n\n // Set this contract as the project's controller in the directory.\n directory.setControllerOf(_projectId, address(this));\n\n // Configure the first funding cycle.\n configuration = _configure(\n _projectId,\n _data,\n _metadata,\n _mustStartAtOrAfter,\n _groupedSplits,\n _fundAccessConstraints\n );\n\n // Add the provided terminals to the list of terminals.\n if (_terminals.length > 0) directory.setTerminalsOf(_projectId, _terminals);\n\n emit LaunchFundingCycles(configuration, _projectId, _memo, msg.sender);\n }\n\n /**\n @notice\n Proposes a configuration of a subsequent funding cycle that will take effect once the current one expires if it is approved by the current funding cycle's ballot.\n\n @dev\n Only a project's owner or a designated operator can configure its funding cycles.\n\n @param _projectId The ID of the project whose funding cycles are being reconfigured.\n @param _data Data that defines the funding cycle. These properties will remain fixed for the duration of the funding cycle.\n @param _metadata Metadata specifying the controller specific params that a funding cycle can have. These properties will remain fixed for the duration of the funding cycle.\n @param _mustStartAtOrAfter The time before which the configured funding cycle cannot start.\n @param _groupedSplits An array of splits to set for any number of groups. \n @param _fundAccessConstraints An array containing amounts that a project can use from its treasury for each payment terminal. Amounts are fixed point numbers using the same number of decimals as the accompanying terminal. The `_distributionLimit` and `_overflowAllowance` parameters must fit in a `uint232`.\n @param _memo A memo to pass along to the emitted event.\n\n @return configuration The configuration of the funding cycle that was successfully reconfigured.\n */\n function reconfigureFundingCyclesOf(\n uint256 _projectId,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] calldata _groupedSplits,\n JBFundAccessConstraints[] calldata _fundAccessConstraints,\n string calldata _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.RECONFIGURE)\n returns (uint256 configuration)\n {\n // Configure the next funding cycle.\n configuration = _configure(\n _projectId,\n _data,\n _metadata,\n _mustStartAtOrAfter,\n _groupedSplits,\n _fundAccessConstraints\n );\n\n emit ReconfigureFundingCycles(configuration, _projectId, _memo, msg.sender);\n }\n\n /**\n @notice\n Mint new token supply into an account, and optionally reserve a supply to be distributed according to the project's current funding cycle configuration.\n\n @dev\n Only a project's owner, a designated operator, one of its terminals, or the current data source can mint its tokens.\n\n @param _projectId The ID of the project to which the tokens being minted belong.\n @param _tokenCount The amount of tokens to mint in total, counting however many should be reserved.\n @param _beneficiary The account that the tokens are being minted for.\n @param _memo A memo to pass along to the emitted event.\n @param _preferClaimedTokens A flag indicating whether a project's attached token contract should be minted if they have been issued.\n @param _useReservedRate Whether to use the current funding cycle's reserved rate in the mint calculation.\n\n @return beneficiaryTokenCount The amount of tokens minted for the beneficiary.\n */\n function mintTokensOf(\n uint256 _projectId,\n uint256 _tokenCount,\n address _beneficiary,\n string calldata _memo,\n bool _preferClaimedTokens,\n bool _useReservedRate\n ) external virtual override returns (uint256 beneficiaryTokenCount) {\n // There should be tokens to mint.\n if (_tokenCount == 0) revert ZERO_TOKENS_TO_MINT();\n\n // Define variables that will be needed outside scoped section below.\n // Keep a reference to the reserved rate to use\n uint256 _reservedRate;\n\n // Scoped section prevents stack too deep. `_fundingCycle` only used within scope.\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Minting limited to: project owner, authorized callers, project terminal and current funding cycle data source\n _requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.MINT,\n directory.isTerminalOf(_projectId, IJBPaymentTerminal(msg.sender)) ||\n msg.sender == address(_fundingCycle.dataSource())\n );\n\n // If the message sender is not a terminal or a datasource, the current funding cycle must allow minting.\n if (\n !_fundingCycle.mintingAllowed() &&\n !directory.isTerminalOf(_projectId, IJBPaymentTerminal(msg.sender)) &&\n msg.sender != address(_fundingCycle.dataSource())\n ) revert MINT_NOT_ALLOWED_AND_NOT_TERMINAL_DELEGATE();\n\n // Determine the reserved rate to use.\n _reservedRate = _useReservedRate ? _fundingCycle.reservedRate() : 0;\n\n // Override the claimed token preference with the funding cycle value.\n _preferClaimedTokens = _preferClaimedTokens == true\n ? _preferClaimedTokens\n : _fundingCycle.preferClaimedTokenOverride();\n }\n\n if (_reservedRate != JBConstants.MAX_RESERVED_RATE) {\n // The unreserved token count that will be minted for the beneficiary.\n beneficiaryTokenCount = PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_RESERVED_RATE - _reservedRate,\n JBConstants.MAX_RESERVED_RATE\n );\n\n // Mint the tokens.\n tokenStore.mintFor(_beneficiary, _projectId, beneficiaryTokenCount, _preferClaimedTokens);\n }\n\n // Add reserved tokens if needed\n if (_reservedRate > 0)\n reservedTokenBalanceOf[_projectId] += _tokenCount - beneficiaryTokenCount;\n\n emit MintTokens(\n _beneficiary,\n _projectId,\n _tokenCount,\n beneficiaryTokenCount,\n _memo,\n _reservedRate,\n msg.sender\n );\n }\n\n /**\n @notice\n Burns a token holder's supply.\n\n @dev\n Only a token's holder, a designated operator, or a project's terminal can burn it.\n\n @param _holder The account that is having its tokens burned.\n @param _projectId The ID of the project to which the tokens being burned belong.\n @param _tokenCount The number of tokens to burn.\n @param _memo A memo to pass along to the emitted event.\n @param _preferClaimedTokens A flag indicating whether a project's attached token contract should be burned first if they have been issued.\n */\n function burnTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string calldata _memo,\n bool _preferClaimedTokens\n )\n external\n virtual\n override\n requirePermissionAllowingOverride(\n _holder,\n _projectId,\n JBOperations.BURN,\n directory.isTerminalOf(_projectId, IJBPaymentTerminal(msg.sender))\n )\n {\n // There should be tokens to burn\n if (_tokenCount == 0) revert NO_BURNABLE_TOKENS();\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // If the message sender is a terminal, the current funding cycle must not be paused.\n if (\n _fundingCycle.burnPaused() &&\n !directory.isTerminalOf(_projectId, IJBPaymentTerminal(msg.sender))\n ) revert BURN_PAUSED_AND_SENDER_NOT_VALID_TERMINAL_DELEGATE();\n\n // Burn the tokens.\n tokenStore.burnFrom(_holder, _projectId, _tokenCount, _preferClaimedTokens);\n\n emit BurnTokens(_holder, _projectId, _tokenCount, _memo, msg.sender);\n }\n\n /**\n @notice\n Distributes all outstanding reserved tokens for a project.\n\n @param _projectId The ID of the project to which the reserved tokens belong.\n @param _memo A memo to pass along to the emitted event.\n\n @return The amount of minted reserved tokens.\n */\n function distributeReservedTokensOf(uint256 _projectId, string calldata _memo)\n external\n virtual\n override\n returns (uint256)\n {\n return _distributeReservedTokensOf(_projectId, _memo);\n }\n\n /**\n @notice\n Allows other controllers to signal to this one that a migration is expected for the specified project.\n\n @dev\n This controller should not yet be the project's controller.\n\n @param _projectId The ID of the project that will be migrated to this controller.\n @param _from The controller being migrated from.\n */\n function prepForMigrationOf(uint256 _projectId, address _from) external virtual override {\n _projectId; // Prevents unused var compiler and natspec complaints.\n _from; // Prevents unused var compiler and natspec complaints.\n }\n\n /**\n @notice\n Allows a project to migrate from this controller to another.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project that will be migrated from this controller.\n @param _to The controller to which the project is migrating.\n */\n function migrate(uint256 _projectId, IJBMigratable _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_CONTROLLER)\n {\n // Keep a reference to the directory.\n IJBDirectory _directory = directory;\n\n // This controller must be the project's current controller.\n if (_directory.controllerOf(_projectId) != address(this)) revert NOT_CURRENT_CONTROLLER();\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.controllerMigrationAllowed()) revert MIGRATION_NOT_ALLOWED();\n\n // All reserved tokens must be minted before migrating.\n if (reservedTokenBalanceOf[_projectId] != 0) _distributeReservedTokensOf(_projectId, '');\n\n // Make sure the new controller is prepped for the migration.\n _to.prepForMigrationOf(_projectId, address(this));\n\n // Set the new controller.\n _directory.setControllerOf(_projectId, address(_to));\n\n emit Migrate(_projectId, _to, msg.sender);\n }\n\n //*********************************************************************//\n // ------------------------ internal functions ----------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Distributes all outstanding reserved tokens for a project.\n\n @param _projectId The ID of the project to which the reserved tokens belong.\n @param _memo A memo to pass along to the emitted event.\n\n @return tokenCount The amount of minted reserved tokens.\n */\n function _distributeReservedTokensOf(uint256 _projectId, string memory _memo)\n internal\n returns (uint256 tokenCount)\n {\n // Keep a reference to the token store.\n IJBTokenStore _tokenStore = tokenStore;\n\n // Get the current funding cycle to read the reserved rate from.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the number of tokens that need to be minted.\n tokenCount = reservedTokenBalanceOf[_projectId];\n\n // Reset the reserved token balance\n reservedTokenBalanceOf[_projectId] = 0;\n\n // Get a reference to the project owner.\n address _owner = projects.ownerOf(_projectId);\n\n // Distribute tokens to splits and get a reference to the leftover amount to mint after all splits have gotten their share.\n uint256 _leftoverTokenCount = tokenCount == 0\n ? 0\n : _distributeToReservedTokenSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n JBSplitsGroups.RESERVED_TOKENS,\n tokenCount\n );\n\n // Mint any leftover tokens to the project owner.\n if (_leftoverTokenCount > 0)\n _tokenStore.mintFor(_owner, _projectId, _leftoverTokenCount, false);\n\n emit DistributeReservedTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _owner,\n tokenCount,\n _leftoverTokenCount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Distribute tokens to the splits according to the specified funding cycle configuration.\n\n @param _projectId The ID of the project for which reserved token splits are being distributed.\n @param _domain The domain of the splits to distribute the reserved tokens between.\n @param _group The group of the splits to distribute the reserved tokens between.\n @param _amount The total amount of tokens to mint.\n\n @return leftoverAmount If the splits percents dont add up to 100%, the leftover amount is returned.\n */\n function _distributeToReservedTokenSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount\n ) internal returns (uint256 leftoverAmount) {\n // Keep a reference to the token store.\n IJBTokenStore _tokenStore = tokenStore;\n\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n\n // Get a reference to the project's reserved token splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n //Transfer between all splits.\n for (uint256 _i; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _tokenCount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n // Mints tokens for the split if needed.\n if (_tokenCount > 0) {\n _tokenStore.mintFor(\n // If an allocator is set in the splits, set it as the beneficiary.\n // Otherwise if a projectId is set in the split, set the project's owner as the beneficiary.\n // If the split has a beneficiary send to the split's beneficiary. Otherwise send to the msg.sender.\n _split.allocator != IJBSplitAllocator(address(0))\n ? address(_split.allocator)\n : _split.projectId != 0\n ? projects.ownerOf(_split.projectId)\n : _split.beneficiary != address(0)\n ? _split.beneficiary\n : msg.sender,\n _projectId,\n _tokenCount,\n _split.preferClaimed\n );\n\n // If there's an allocator set, trigger its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0)))\n _split.allocator.allocate(\n JBSplitAllocationData(\n address(_tokenStore.tokenOf(_projectId)),\n _tokenCount,\n 18,\n _projectId,\n _group,\n _split\n )\n );\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _tokenCount;\n }\n\n emit DistributeToReservedTokenSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _tokenCount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Configures a funding cycle and stores information pertinent to the configuration.\n\n @param _projectId The ID of the project whose funding cycles are being reconfigured.\n @param _data Data that defines the funding cycle. These properties will remain fixed for the duration of the funding cycle.\n @param _metadata Metadata specifying the controller specific params that a funding cycle can have. These properties will remain fixed for the duration of the funding cycle.\n @param _mustStartAtOrAfter The time before which the configured funding cycle cannot start.\n @param _groupedSplits An array of splits to set for any number of groups. \n @param _fundAccessConstraints An array containing amounts that a project can use from its treasury for each payment terminal. Amounts are fixed point numbers using the same number of decimals as the accompanying terminal.\n\n @return configuration The configuration of the funding cycle that was successfully reconfigured.\n */\n function _configure(\n uint256 _projectId,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] memory _groupedSplits,\n JBFundAccessConstraints[] memory _fundAccessConstraints\n ) internal returns (uint256) {\n // Make sure the provided reserved rate is valid.\n if (_metadata.reservedRate > JBConstants.MAX_RESERVED_RATE) revert INVALID_RESERVED_RATE();\n\n // Make sure the provided redemption rate is valid.\n if (_metadata.redemptionRate > JBConstants.MAX_REDEMPTION_RATE)\n revert INVALID_REDEMPTION_RATE();\n\n // Make sure the provided ballot redemption rate is valid.\n if (_metadata.ballotRedemptionRate > JBConstants.MAX_REDEMPTION_RATE)\n revert INVALID_BALLOT_REDEMPTION_RATE();\n\n // Configure the funding cycle's properties.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.configureFor(\n _projectId,\n _data,\n JBFundingCycleMetadataResolver.packFundingCycleMetadata(_metadata),\n _mustStartAtOrAfter\n );\n\n // Set splits for the group.\n splitsStore.set(_projectId, _fundingCycle.configuration, _groupedSplits);\n\n // Set distribution limits if there are any.\n for (uint256 _i; _i < _fundAccessConstraints.length; ) {\n JBFundAccessConstraints memory _constraints = _fundAccessConstraints[_i];\n\n // If distribution limit value is larger than 232 bits, revert.\n if (_constraints.distributionLimit > type(uint232).max) revert INVALID_DISTRIBUTION_LIMIT();\n\n // If distribution limit currency value is larger than 24 bits, revert.\n if (_constraints.distributionLimitCurrency > type(uint24).max)\n revert INVALID_DISTRIBUTION_LIMIT_CURRENCY();\n\n // If overflow allowance value is larger than 232 bits, revert.\n if (_constraints.overflowAllowance > type(uint232).max) revert INVALID_OVERFLOW_ALLOWANCE();\n\n // If overflow allowance currency value is larger than 24 bits, revert.\n if (_constraints.overflowAllowanceCurrency > type(uint24).max)\n revert INVALID_OVERFLOW_ALLOWANCE_CURRENCY();\n\n // Set the distribution limit if there is one.\n if (_constraints.distributionLimit > 0)\n _packedDistributionLimitDataOf[_projectId][_fundingCycle.configuration][\n _constraints.terminal\n ][_constraints.token] =\n _constraints.distributionLimit |\n (_constraints.distributionLimitCurrency << 232);\n\n // Set the overflow allowance if there is one.\n if (_constraints.overflowAllowance > 0)\n _packedOverflowAllowanceDataOf[_projectId][_fundingCycle.configuration][\n _constraints.terminal\n ][_constraints.token] =\n _constraints.overflowAllowance |\n (_constraints.overflowAllowanceCurrency << 232);\n\n emit SetFundAccessConstraints(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _constraints,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n\n return _fundingCycle.configuration;\n }\n}\n" @@ -233,13 +233,13 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nlibrary JBSplitsGroups {\n uint256 public constant ETH_PAYOUT = 1;\n uint256 public constant RESERVED_TOKENS = 2;\n}\n" }, "contracts/JBETHPaymentTerminal.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\nimport './libraries/JBSplitsGroups.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return address(this).balance;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n JBTokens.ETH,\n 18, // 18 decimals.\n JBCurrencies.ETH,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\nimport './libraries/JBSplitsGroups.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return address(this).balance;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n JBTokens.GAS_TOKEN,\n 18, // 18 decimals.\n JBCurrencies.GAS_CURRENCY,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n}\n" }, "@openzeppelin/contracts/utils/Address.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" }, "contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBPayDelegateAllocation.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal is\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n IJBPayoutRedemptionPaymentTerminal\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n @dev\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.ETH)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.ETH, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance.\n */\n function _balance() internal view virtual returns (uint256);\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.ETH) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual {\n _from; // Prevents unused var compiler and natspec complaints.\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\n {\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\n\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _forwardedAmount,\n _beneficiary,\n _memo,\n _metadata\n );\n\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\n\n emit DelegateDidRedeem(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n }\n\n // Take the fee.\n _fee = _feeEligibleDistributionAmount != 0\n ? _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n )\n : 0;\n\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\n if (_leftoverDistributionAmount != 0) {\n // Subtract the fee from the net leftover amount.\n netLeftoverDistributionAmount =\n _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n\n // Transfer the amount to the project owner.\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n // The total percentage available to split\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = _split.percent == leftoverPercentage\n ? leftoverAmount\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\n\n // Decrement the leftover percentage.\n leftoverPercentage -= _split.percent;\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount;\n\n if (_payoutAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\n isFeelessAddress[address(_split.allocator)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n _netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n // If this terminal's token is ETH, send it in msg.value.\n _split.allocator.allocate{value: token == JBTokens.ETH ? _netPayoutAmount : 0}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // Save gas if this contract is being used as the terminal.\n if (_terminal == this) {\n // This distribution does not incur a fee.\n _netPayoutAmount = _payoutAmount;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\n else\n _pay(\n _netPayoutAmount,\n address(this),\n _split.projectId,\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n } else {\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_terminal)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _netPayoutAmount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _terminal.addToBalanceOf{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n '',\n _projectMetadata\n );\n else\n _terminal.pay{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n }\n } else {\n // Keep a reference to the beneficiary.\n address payable _beneficiary = _split.beneficiary != address(0)\n ? _split.beneficiary\n : payable(msg.sender);\n\n // If there's a full discount, this distribution is not eligible for a fee.\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(address(this), _beneficiary, _netPayoutAmount);\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n */\n function _processFee(uint256 _amount, address _beneficiary) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\n\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\n if (_terminal == this)\n _pay(\n _amount,\n address(this),\n _FEE_BENEFICIARY_PROJECT_ID,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the local pay call.\n else {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _amount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _amount : 0;\n\n // Send the payment.\n _terminal.pay{value: _payableValue}(\n _FEE_BENEFICIARY_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the external pay call of the correct terminal.\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\n {\n JBPayDelegateAllocation[] memory _delegateAllocations;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n _forwardedAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n // Get a reference to the number of delegates to allocate to.\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\n\n emit DelegateDidPay(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n unchecked {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\n IJBPaymentTerminal(address(0))\n ) return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge != IJBFeeGauge(address(0)))\n // If the guage reverts, keep the discount at 0.\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n // If the fee discount is greater than the max, we ignore the return value\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\n } catch {\n return 0;\n }\n\n return 0;\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBPayDelegateAllocation.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal is\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n IJBPayoutRedemptionPaymentTerminal\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n @dev\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.GAS_CURRENCY)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.GAS_CURRENCY, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance.\n */\n function _balance() internal view virtual returns (uint256);\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.GAS_TOKEN) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual {\n _from; // Prevents unused var compiler and natspec complaints.\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\n {\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\n\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _forwardedAmount,\n _beneficiary,\n _memo,\n _metadata\n );\n\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\n\n emit DelegateDidRedeem(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n }\n\n // Take the fee.\n _fee = _feeEligibleDistributionAmount != 0\n ? _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n )\n : 0;\n\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\n if (_leftoverDistributionAmount != 0) {\n // Subtract the fee from the net leftover amount.\n netLeftoverDistributionAmount =\n _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n\n // Transfer the amount to the project owner.\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n // The total percentage available to split\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = _split.percent == leftoverPercentage\n ? leftoverAmount\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\n\n // Decrement the leftover percentage.\n leftoverPercentage -= _split.percent;\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount;\n\n if (_payoutAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\n isFeelessAddress[address(_split.allocator)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n _netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n // If this terminal's token is ETH, send it in msg.value.\n _split.allocator.allocate{value: token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // Save gas if this contract is being used as the terminal.\n if (_terminal == this) {\n // This distribution does not incur a fee.\n _netPayoutAmount = _payoutAmount;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\n else\n _pay(\n _netPayoutAmount,\n address(this),\n _split.projectId,\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n } else {\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_terminal)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _terminal.addToBalanceOf{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n '',\n _projectMetadata\n );\n else\n _terminal.pay{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n }\n } else {\n // Keep a reference to the beneficiary.\n address payable _beneficiary = _split.beneficiary != address(0)\n ? _split.beneficiary\n : payable(msg.sender);\n\n // If there's a full discount, this distribution is not eligible for a fee.\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(address(this), _beneficiary, _netPayoutAmount);\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n */\n function _processFee(uint256 _amount, address _beneficiary) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\n\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\n if (_terminal == this)\n _pay(\n _amount,\n address(this),\n _FEE_BENEFICIARY_PROJECT_ID,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the local pay call.\n else {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _amount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send the payment.\n _terminal.pay{value: _payableValue}(\n _FEE_BENEFICIARY_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the external pay call of the correct terminal.\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\n {\n JBPayDelegateAllocation[] memory _delegateAllocations;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n _forwardedAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n // Get a reference to the number of delegates to allocate to.\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\n\n emit DelegateDidPay(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n unchecked {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\n IJBPaymentTerminal(address(0))\n ) return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge != IJBFeeGauge(address(0)))\n // If the guage reverts, keep the discount at 0.\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n // If the fee discount is greater than the max, we ignore the return value\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\n } catch {\n return 0;\n }\n\n return 0;\n }\n}\n" }, "contracts/interfaces/IJBPayoutRedemptionPaymentTerminal.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './../structs/JBFee.sol';\nimport './IJBAllowanceTerminal.sol';\nimport './IJBDirectory.sol';\nimport './IJBFeeGauge.sol';\nimport './IJBPayDelegate.sol';\nimport './IJBPaymentTerminal.sol';\nimport './IJBPayoutTerminal.sol';\nimport './IJBPrices.sol';\nimport './IJBProjects.sol';\nimport './IJBRedemptionDelegate.sol';\nimport './IJBRedemptionTerminal.sol';\nimport './IJBSingleTokenPaymentTerminalStore.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBPayoutRedemptionPaymentTerminal is\n IJBPaymentTerminal,\n IJBPayoutTerminal,\n IJBAllowanceTerminal,\n IJBRedemptionTerminal\n{\n event AddToBalance(\n uint256 indexed projectId,\n uint256 amount,\n uint256 refundedFees,\n string memo,\n bytes metadata,\n address caller\n );\n\n event Migrate(\n uint256 indexed projectId,\n IJBPaymentTerminal indexed to,\n uint256 amount,\n address caller\n );\n\n event DistributePayouts(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address beneficiary,\n uint256 amount,\n uint256 distributedAmount,\n uint256 fee,\n uint256 beneficiaryDistributionAmount,\n string memo,\n address caller\n );\n\n event UseAllowance(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address beneficiary,\n uint256 amount,\n uint256 distributedAmount,\n uint256 netDistributedamount,\n string memo,\n address caller\n );\n\n event HoldFee(\n uint256 indexed projectId,\n uint256 indexed amount,\n uint256 indexed fee,\n uint256 feeDiscount,\n address beneficiary,\n address caller\n );\n\n event ProcessFee(\n uint256 indexed projectId,\n uint256 indexed amount,\n bool indexed wasHeld,\n address beneficiary,\n address caller\n );\n\n event RefundHeldFees(\n uint256 indexed projectId,\n uint256 indexed amount,\n uint256 indexed refundedFees,\n uint256 leftoverAmount,\n address caller\n );\n\n event Pay(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address payer,\n address beneficiary,\n uint256 amount,\n uint256 beneficiaryTokenCount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DelegateDidPay(\n IJBPayDelegate indexed delegate,\n JBDidPayData data,\n uint256 delegatedAmount,\n address caller\n );\n\n event RedeemTokens(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address holder,\n address beneficiary,\n uint256 tokenCount,\n uint256 reclaimedAmount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DelegateDidRedeem(\n IJBRedemptionDelegate indexed delegate,\n JBDidRedeemData data,\n uint256 delegatedAmount,\n address caller\n );\n\n event DistributeToPayoutSplit(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n JBSplit split,\n uint256 amount,\n address caller\n );\n\n event SetFee(uint256 fee, address caller);\n\n event SetFeeGauge(IJBFeeGauge indexed feeGauge, address caller);\n\n event SetFeelessAddress(address indexed addrs, bool indexed flag, address caller);\n\n function projects() external view returns (IJBProjects);\n\n function splitsStore() external view returns (IJBSplitsStore);\n\n function directory() external view returns (IJBDirectory);\n\n function prices() external view returns (IJBPrices);\n\n function store() external view returns (IJBSingleTokenPaymentTerminalStore);\n\n function baseWeightCurrency() external view returns (uint256);\n\n function payoutSplitsGroup() external view returns (uint256);\n\n function heldFeesOf(uint256 _projectId) external view returns (JBFee[] memory);\n\n function fee() external view returns (uint256);\n\n function feeGauge() external view returns (IJBFeeGauge);\n\n function isFeelessAddress(address _contract) external view returns (bool);\n\n function migrate(uint256 _projectId, IJBPaymentTerminal _to) external returns (uint256 balance);\n\n function processFees(uint256 _projectId) external;\n\n function setFee(uint256 _fee) external;\n\n function setFeeGauge(IJBFeeGauge _feeGauge) external;\n\n function setFeelessAddress(address _contract, bool _flag) external;\n}\n" @@ -271,23 +271,23 @@ "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n function safeTransfer(\n IERC20 token,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(\n IERC20 token,\n address from,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n uint256 newAllowance = token.allowance(address(this), spender) + value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n uint256 newAllowance = oldAllowance - value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) {\n // Return data is optional\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" }, - "contracts/JBETHERC20SplitsPayer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBSplitsPayer.sol';\nimport './interfaces/IJBSplitsStore.sol';\nimport './libraries/JBConstants.sol';\nimport './JBETHERC20ProjectPayer.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\n\n @dev\n Adheres to -\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBETHERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBETHERC20SplitsPayer is JBETHERC20ProjectPayer, ReentrancyGuard, IJBSplitsPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The ID of project for which the default splits are stored. \n */\n uint256 public override defaultSplitsProjectId;\n\n /**\n @notice\n The domain within which the default splits are stored. \n */\n uint256 public override defaultSplitsDomain;\n\n /**\n @notice\n The group within which the default splits are stored. \n */\n uint256 public override defaultSplitsGroup;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBETHERC20ProjectPayer, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n )\n JBETHERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _preferAddToBalance,\n _splitsStore.directory(),\n _owner\n )\n {\n defaultSplitsProjectId = _defaultSplitsProjectId;\n defaultSplitsDomain = _defaultSplitsDomain;\n defaultSplitsGroup = _defaultSplitsGroup;\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default split group using the stored default properties.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override nonReentrant {\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n JBTokens.ETH,\n address(this).balance,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // If there is no leftover amount, nothing left to pay.\n if (_leftoverAmount == 0) return;\n\n // If there's a default project ID, try to pay it.\n if (defaultProjectId != 0)\n if (defaultPreferAddToBalance)\n // Pay the project by adding to its balance if prefered.\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.ETH,\n _leftoverAmount,\n 18, // decimals.\n defaultMemo,\n defaultMetadata\n );\n // Otherwise, issue a payment to the project.\n else\n _pay(\n defaultProjectId,\n JBTokens.ETH,\n _leftoverAmount,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n 0, // min returned tokens.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else\n Address.sendValue(\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(tx.origin),\n _leftoverAmount\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the splits in the splits store that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n @param _groupedSplits The split groups to set.\n */\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n JBGroupedSplits[] memory _groupedSplits\n ) external virtual override onlyOwner {\n // Set the splits in the store.\n splitsStore.set(_projectId, _domain, _groupedSplits);\n\n // Set the splits reference.\n setDefaultSplitsReference(_projectId, _domain, _group);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the location of the splits that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n */\n function setDefaultSplitsReference(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) public virtual override onlyOwner {\n // Set the default splits project ID if it's changing.\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\n\n // Set the default splits domain if it's changing.\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\n\n // Set the default splits group if it's changing.\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\n\n emit SetDefaultSplitsReference(_projectId, _domain, _group, msg.sender);\n }\n\n /** \n @notice \n Make a payment to the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Pay any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to pay it.\n if (_projectId != 0) {\n _pay(\n _projectId,\n _token,\n _leftoverAmount,\n _decimals,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? payable(_beneficiary) : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit Pay(\n _projectId,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event. \n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Distribute any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to add to its balance.\n if (_projectId != 0)\n // Add to the project's balance.\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\n\n // Otherwise, send a payment to the beneficiary.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit AddToBalance(\n _projectId,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splitsProjectId The ID of the project to which the splits belong.\n @param _splitsDomain The splits domain to which the group belongs.\n @param _splitsGroup The splits group to pay.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payToSplits(\n uint256 _splitsProjectId,\n uint256 _splitsDomain,\n uint256 _splitsGroup,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Pay the splits.\n leftoverAmount = _payTo(\n splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup),\n _token,\n _amount,\n _decimals,\n _defaultBeneficiary\n );\n emit DistributeToSplitGroup(_splitsProjectId, _splitsDomain, _splitsGroup, msg.sender);\n }\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splits The splits.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payTo(\n JBSplit[] memory _splits,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Set the leftover amount to the initial balance.\n leftoverAmount = _amount;\n\n // Settle between all splits.\n for (uint256 i; i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[i];\n\n // The amount to send towards the split.\n uint256 _splitAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n if (_splitAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n _token,\n _splitAmount,\n _decimals,\n defaultProjectId,\n 0,\n _split\n );\n\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\n if (_token != JBTokens.ETH)\n IERC20(_token).safeApprove(address(_split.allocator), _splitAmount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _splitAmount : 0;\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n if (_split.preferAddToBalance)\n _addToBalanceOf(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n 0,\n _split.preferClaimed,\n defaultMemo,\n defaultMetadata\n );\n } else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : payable(_defaultBeneficiary),\n _splitAmount\n );\n // Or, transfer the ERC20.\n else {\n IERC20(_token).safeTransfer(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n _splitAmount\n );\n }\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _splitAmount;\n }\n\n emit DistributeToSplit(_split, _splitAmount, _defaultBeneficiary, msg.sender);\n\n unchecked {\n ++i;\n }\n }\n }\n}\n" + "contracts/JBGasTokenERC20SplitsPayer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBSplitsPayer.sol';\nimport './interfaces/IJBSplitsStore.sol';\nimport './libraries/JBConstants.sol';\nimport './JBGasTokenERC20ProjectPayer.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\n\n @dev\n Adheres to -\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBGasTokenERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBGasTokenERC20SplitsPayer is JBGasTokenERC20ProjectPayer, ReentrancyGuard, IJBSplitsPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The ID of project for which the default splits are stored. \n */\n uint256 public override defaultSplitsProjectId;\n\n /**\n @notice\n The domain within which the default splits are stored. \n */\n uint256 public override defaultSplitsDomain;\n\n /**\n @notice\n The group within which the default splits are stored. \n */\n uint256 public override defaultSplitsGroup;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBGasTokenERC20ProjectPayer, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n )\n JBGasTokenERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _preferAddToBalance,\n _splitsStore.directory(),\n _owner\n )\n {\n defaultSplitsProjectId = _defaultSplitsProjectId;\n defaultSplitsDomain = _defaultSplitsDomain;\n defaultSplitsGroup = _defaultSplitsGroup;\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default split group using the stored default properties.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override nonReentrant {\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // If there is no leftover amount, nothing left to pay.\n if (_leftoverAmount == 0) return;\n\n // If there's a default project ID, try to pay it.\n if (defaultProjectId != 0)\n if (defaultPreferAddToBalance)\n // Pay the project by adding to its balance if prefered.\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n _leftoverAmount,\n 18, // decimals.\n defaultMemo,\n defaultMetadata\n );\n // Otherwise, issue a payment to the project.\n else\n _pay(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n _leftoverAmount,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n 0, // min returned tokens.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else\n Address.sendValue(\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(tx.origin),\n _leftoverAmount\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the splits in the splits store that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n @param _groupedSplits The split groups to set.\n */\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n JBGroupedSplits[] memory _groupedSplits\n ) external virtual override onlyOwner {\n // Set the splits in the store.\n splitsStore.set(_projectId, _domain, _groupedSplits);\n\n // Set the splits reference.\n setDefaultSplitsReference(_projectId, _domain, _group);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the location of the splits that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n */\n function setDefaultSplitsReference(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) public virtual override onlyOwner {\n // Set the default splits project ID if it's changing.\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\n\n // Set the default splits domain if it's changing.\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\n\n // Set the default splits group if it's changing.\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\n\n emit SetDefaultSplitsReference(_projectId, _domain, _group, msg.sender);\n }\n\n /** \n @notice \n Make a payment to the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Pay any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to pay it.\n if (_projectId != 0) {\n _pay(\n _projectId,\n _token,\n _leftoverAmount,\n _decimals,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? payable(_beneficiary) : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit Pay(\n _projectId,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event. \n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Distribute any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to add to its balance.\n if (_projectId != 0)\n // Add to the project's balance.\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\n\n // Otherwise, send a payment to the beneficiary.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit AddToBalance(\n _projectId,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splitsProjectId The ID of the project to which the splits belong.\n @param _splitsDomain The splits domain to which the group belongs.\n @param _splitsGroup The splits group to pay.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payToSplits(\n uint256 _splitsProjectId,\n uint256 _splitsDomain,\n uint256 _splitsGroup,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Pay the splits.\n leftoverAmount = _payTo(\n splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup),\n _token,\n _amount,\n _decimals,\n _defaultBeneficiary\n );\n emit DistributeToSplitGroup(_splitsProjectId, _splitsDomain, _splitsGroup, msg.sender);\n }\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splits The splits.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payTo(\n JBSplit[] memory _splits,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Set the leftover amount to the initial balance.\n leftoverAmount = _amount;\n\n // Settle between all splits.\n for (uint256 i; i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[i];\n\n // The amount to send towards the split.\n uint256 _splitAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n if (_splitAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n _token,\n _splitAmount,\n _decimals,\n defaultProjectId,\n 0,\n _split\n );\n\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN)\n IERC20(_token).safeApprove(address(_split.allocator), _splitAmount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _splitAmount : 0;\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n if (_split.preferAddToBalance)\n _addToBalanceOf(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n 0,\n _split.preferClaimed,\n defaultMemo,\n defaultMetadata\n );\n } else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : payable(_defaultBeneficiary),\n _splitAmount\n );\n // Or, transfer the ERC20.\n else {\n IERC20(_token).safeTransfer(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n _splitAmount\n );\n }\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _splitAmount;\n }\n\n emit DistributeToSplit(_split, _splitAmount, _defaultBeneficiary, msg.sender);\n\n unchecked {\n ++i;\n }\n }\n }\n}\n" }, "contracts/interfaces/IJBSplitsPayer.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './../structs/JBSplit.sol';\nimport './../structs/JBGroupedSplits.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBSplitsPayer is IERC165 {\n event SetDefaultSplitsReference(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n address caller\n );\n event Pay(\n uint256 indexed projectId,\n address beneficiary,\n address token,\n uint256 amount,\n uint256 decimals,\n uint256 leftoverAmount,\n uint256 minReturnedTokens,\n bool preferClaimedTokens,\n string memo,\n bytes metadata,\n address caller\n );\n\n event AddToBalance(\n uint256 indexed projectId,\n address beneficiary,\n address token,\n uint256 amount,\n uint256 decimals,\n uint256 leftoverAmount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DistributeToSplitGroup(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n address caller\n );\n\n event DistributeToSplit(\n JBSplit split,\n uint256 amount,\n address defaultBeneficiary,\n address caller\n );\n\n function defaultSplitsProjectId() external view returns (uint256);\n\n function defaultSplitsDomain() external view returns (uint256);\n\n function defaultSplitsGroup() external view returns (uint256);\n\n function splitsStore() external view returns (IJBSplitsStore);\n\n function setDefaultSplitsReference(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) external;\n\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n JBGroupedSplits[] memory _splitsGroup\n ) external;\n}\n" }, - "contracts/JBETHERC20ProjectPayer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport './interfaces/IJBProjectPayer.sol';\nimport './libraries/JBTokens.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ERC165: Introspection on interface adherance. \n*/\ncontract JBETHERC20ProjectPayer is Ownable, ERC165, IJBProjectPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // -------------------------- custom errors -------------------------- //\n //*********************************************************************//\n error INCORRECT_DECIMAL_AMOUNT();\n error NO_MSG_VALUE_ALLOWED();\n error TERMINAL_NOT_FOUND();\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice \n A contract storing directories of terminals and controllers for each project.\n */\n IJBDirectory public immutable override directory;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The ID of the project that should be used to forward this contract's received payments.\n */\n uint256 public override defaultProjectId;\n\n /** \n @notice \n The beneficiary that should be used in the payment made when this contract receives payments.\n */\n address payable public override defaultBeneficiary;\n\n /** \n @notice \n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\n */\n bool public override defaultPreferClaimedTokens;\n\n /** \n @notice \n The memo that should be used in the payment made when this contract receives payments.\n */\n string public override defaultMemo;\n\n /** \n @notice \n The metadata that should be used in the payment made when this contract receives payments.\n */\n bytes public override defaultMetadata;\n\n /**\n @notice \n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n bool public override defaultPreferAddToBalance;\n\n //*********************************************************************//\n // ------------------------- public views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) {\n defaultProjectId = _defaultProjectId;\n defaultBeneficiary = _defaultBeneficiary;\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\n defaultMemo = _defaultMemo;\n defaultMetadata = _defaultMetadata;\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n directory = _directory;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default project ID using the stored default properties.\n\n @dev\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override {\n if (defaultPreferAddToBalance)\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.ETH,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n defaultProjectId,\n JBTokens.ETH,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultBeneficiary == address(0) ? tx.origin : defaultBeneficiary,\n 0, // Can't determine expectation of returned tokens ahead of time.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\n\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _beneficiary The address that'll receive the project's tokens. \n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _memo The memo that'll be used. \n @param _metadata The metadata that'll be sent. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external virtual override onlyOwner {\n // Set the default project ID if it has changed.\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\n\n // Set the default beneficiary if it has changed.\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\n\n // Set the default claimed token preference if it has changed.\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\n defaultPreferClaimedTokens = _preferClaimedTokens;\n\n // Set the default memo if it has changed.\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\n defaultMemo = _memo;\n\n // Set the default metadata if it has changed.\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\n defaultMetadata = _metadata;\n\n // Set the add to balance preference if it has changed.\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n\n emit SetDefaultValues(\n _projectId,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata,\n _defaultPreferAddToBalance,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _pay(\n _projectId,\n _token,\n _amount,\n _decimals,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. \n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source and delegate, if provided.\n */\n function _pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.ETH) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\n\n // Send funds to the terminal.\n // If the token is ETH, send it in msg.value.\n _terminal.pay{value: _payableValue}(\n _projectId,\n _amount, // ignored if the token is JBTokens.ETH.\n _token,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.ETH) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\n\n // Add to balance so tokens don't get issued.\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\n }\n}\n" + "contracts/JBGasTokenERC20ProjectPayer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport './interfaces/IJBProjectPayer.sol';\nimport './libraries/JBTokens.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ERC165: Introspection on interface adherance. \n*/\ncontract JBGasTokenERC20ProjectPayer is Ownable, ERC165, IJBProjectPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // -------------------------- custom errors -------------------------- //\n //*********************************************************************//\n error INCORRECT_DECIMAL_AMOUNT();\n error NO_MSG_VALUE_ALLOWED();\n error TERMINAL_NOT_FOUND();\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice \n A contract storing directories of terminals and controllers for each project.\n */\n IJBDirectory public immutable override directory;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The ID of the project that should be used to forward this contract's received payments.\n */\n uint256 public override defaultProjectId;\n\n /** \n @notice \n The beneficiary that should be used in the payment made when this contract receives payments.\n */\n address payable public override defaultBeneficiary;\n\n /** \n @notice \n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\n */\n bool public override defaultPreferClaimedTokens;\n\n /** \n @notice \n The memo that should be used in the payment made when this contract receives payments.\n */\n string public override defaultMemo;\n\n /** \n @notice \n The metadata that should be used in the payment made when this contract receives payments.\n */\n bytes public override defaultMetadata;\n\n /**\n @notice \n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n bool public override defaultPreferAddToBalance;\n\n //*********************************************************************//\n // ------------------------- public views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) {\n defaultProjectId = _defaultProjectId;\n defaultBeneficiary = _defaultBeneficiary;\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\n defaultMemo = _defaultMemo;\n defaultMetadata = _defaultMetadata;\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n directory = _directory;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default project ID using the stored default properties.\n\n @dev\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override {\n if (defaultPreferAddToBalance)\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultBeneficiary == address(0) ? tx.origin : defaultBeneficiary,\n 0, // Can't determine expectation of returned tokens ahead of time.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\n\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _beneficiary The address that'll receive the project's tokens. \n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _memo The memo that'll be used. \n @param _metadata The metadata that'll be sent. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external virtual override onlyOwner {\n // Set the default project ID if it has changed.\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\n\n // Set the default beneficiary if it has changed.\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\n\n // Set the default claimed token preference if it has changed.\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\n defaultPreferClaimedTokens = _preferClaimedTokens;\n\n // Set the default memo if it has changed.\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\n defaultMemo = _memo;\n\n // Set the default metadata if it has changed.\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\n defaultMetadata = _metadata;\n\n // Set the add to balance preference if it has changed.\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n\n emit SetDefaultValues(\n _projectId,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata,\n _defaultPreferAddToBalance,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _pay(\n _projectId,\n _token,\n _amount,\n _decimals,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. \n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source and delegate, if provided.\n */\n function _pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send funds to the terminal.\n // If the token is ETH, send it in msg.value.\n _terminal.pay{value: _payableValue}(\n _projectId,\n _amount, // ignored if the token is JBTokens.GAS_TOKEN.\n _token,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Add to balance so tokens don't get issued.\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\n }\n}\n" }, "contracts/interfaces/IJBProjectPayer.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './IJBDirectory.sol';\n\ninterface IJBProjectPayer is IERC165 {\n event SetDefaultValues(\n uint256 indexed projectId,\n address indexed beneficiary,\n bool preferClaimedTokens,\n string memo,\n bytes metadata,\n bool preferAddToBalance,\n address caller\n );\n\n function directory() external view returns (IJBDirectory);\n\n function defaultProjectId() external view returns (uint256);\n\n function defaultBeneficiary() external view returns (address payable);\n\n function defaultPreferClaimedTokens() external view returns (bool);\n\n function defaultMemo() external view returns (string memory);\n\n function defaultMetadata() external view returns (bytes memory);\n\n function defaultPreferAddToBalance() external view returns (bool);\n\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external;\n\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) external payable;\n\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) external payable;\n\n receive() external payable;\n}\n" }, - "contracts/JBETHERC20SplitsPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './interfaces/IJBETHERC20SplitsPayerDeployer.sol';\nimport './structs/JBSplit.sol';\nimport './structs/JBGroupedSplits.sol';\nimport './JBETHERC20SplitsPayer.sol';\n\n/** \n @notice \n Deploys splits payer contracts.\n\n @dev\n Adheres to -\n IJBETHERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBETHERC20SplitsPayerDeployer is IJBETHERC20SplitsPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @dev\n This contract must have Operator permissions over the SET_SPLITS permission of the specified `_defaultSplitsProjectId`.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplits The splits to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBSplitsPayer splitsPayer) {\n // Use this contract's address as the domain.\n uint256 _domain = uint256(uint160(address(this)));\n\n // Create the random hash using data unique to this instance that'll be used as the storage domain.\n uint256 _group = uint256(keccak256(abi.encodePacked(msg.sender, block.number)));\n\n // Set the splits in the store.\n JBGroupedSplits[] memory _groupedSplits;\n _groupedSplits = new JBGroupedSplits[](1);\n _groupedSplits[0] = JBGroupedSplits(_group, _defaultSplits);\n _splitsStore.set(_defaultSplitsProjectId, _domain, _groupedSplits);\n\n return\n deploySplitsPayer(\n _defaultSplitsProjectId,\n _domain,\n _group,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n }\n\n //*********************************************************************//\n // ---------------------- public transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) public override returns (IJBSplitsPayer splitsPayer) {\n // Deploy the splits payer.\n splitsPayer = new JBETHERC20SplitsPayer(\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeploySplitsPayer(\n splitsPayer,\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner,\n msg.sender\n );\n }\n}\n" + "contracts/JBGasTokenERC20SplitsPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './interfaces/IJBGasTokenERC20SplitsPayerDeployer.sol';\nimport './structs/JBSplit.sol';\nimport './structs/JBGroupedSplits.sol';\nimport './JBGasTokenERC20SplitsPayer.sol';\n\n/** \n @notice \n Deploys splits payer contracts.\n\n @dev\n Adheres to -\n IJBGasTokenERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBGasTokenERC20SplitsPayerDeployer is IJBGasTokenERC20SplitsPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @dev\n This contract must have Operator permissions over the SET_SPLITS permission of the specified `_defaultSplitsProjectId`.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplits The splits to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBSplitsPayer splitsPayer) {\n // Use this contract's address as the domain.\n uint256 _domain = uint256(uint160(address(this)));\n\n // Create the random hash using data unique to this instance that'll be used as the storage domain.\n uint256 _group = uint256(keccak256(abi.encodePacked(msg.sender, block.number)));\n\n // Set the splits in the store.\n JBGroupedSplits[] memory _groupedSplits;\n _groupedSplits = new JBGroupedSplits[](1);\n _groupedSplits[0] = JBGroupedSplits(_group, _defaultSplits);\n _splitsStore.set(_defaultSplitsProjectId, _domain, _groupedSplits);\n\n return\n deploySplitsPayer(\n _defaultSplitsProjectId,\n _domain,\n _group,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n }\n\n //*********************************************************************//\n // ---------------------- public transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) public override returns (IJBSplitsPayer splitsPayer) {\n // Deploy the splits payer.\n splitsPayer = new JBGasTokenERC20SplitsPayer(\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeploySplitsPayer(\n splitsPayer,\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner,\n msg.sender\n );\n }\n}\n" }, - "contracts/interfaces/IJBETHERC20SplitsPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBSplitsPayer.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBETHERC20SplitsPayerDeployer {\n event DeploySplitsPayer(\n IJBSplitsPayer indexed splitsPayer,\n uint256 defaultSplitsProjectId,\n uint256 defaultSplitsDomain,\n uint256 defaultSplitsGroup,\n IJBSplitsStore splitsStore,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n address owner,\n address caller\n );\n\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string calldata _defaultMemo,\n bytes calldata _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n}\n" + "contracts/interfaces/IJBGasTokenERC20SplitsPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBSplitsPayer.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBGasTokenERC20SplitsPayerDeployer {\n event DeploySplitsPayer(\n IJBSplitsPayer indexed splitsPayer,\n uint256 defaultSplitsProjectId,\n uint256 defaultSplitsDomain,\n uint256 defaultSplitsGroup,\n IJBSplitsStore splitsStore,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n address owner,\n address caller\n );\n\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string calldata _defaultMemo,\n bytes calldata _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n}\n" }, "contracts/JBSplitsStore.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './abstract/JBOperatable.sol';\nimport './interfaces/IJBDirectory.sol';\nimport './interfaces/IJBSplitsStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBOperations.sol';\n\n/**\n @notice\n Stores splits for each project.\n\n @dev\n Adheres to -\n IJBSplitsStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\ncontract JBSplitsStore is JBOperatable, IJBSplitsStore {\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_LOCKED_UNTIL();\n error INVALID_PROJECT_ID();\n error INVALID_SPLIT_PERCENT();\n error INVALID_TOTAL_PERCENT();\n error PREVIOUS_LOCKED_SPLITS_NOT_INCLUDED();\n\n //*********************************************************************//\n // --------------------- private stored properties ------------------- //\n //*********************************************************************//\n\n /** \n @notice\n The number of splits currently set for each project ID's configurations.\n\n _projectId The ID of the project to get the split count for.\n _domain An identifier within which the returned splits should be considered active.\n _group The identifying group of the splits.\n */\n mapping(uint256 => mapping(uint256 => mapping(uint256 => uint256))) private _splitCountOf;\n\n /** \n @notice\n Packed data of splits for each project ID's configurations.\n\n _projectId The ID of the project to get packed splits data for.\n _domain An identifier within which the returned splits should be considered active.\n _group The identifying group of the splits.\n _index The indexed order that the split was set at.\n */\n mapping(uint256 => mapping(uint256 => mapping(uint256 => mapping(uint256 => uint256))))\n private _packedSplitParts1Of;\n\n /** \n @notice\n More packed data of splits for each project ID's configurations.\n\n @dev\n This packed data is often 0.\n\n _projectId The ID of the project to get packed splits data for.\n _domain An identifier within which the returned splits should be considered active.\n _group The identifying group of the splits.\n _index The indexed order that the split was set at.\n */\n mapping(uint256 => mapping(uint256 => mapping(uint256 => mapping(uint256 => uint256))))\n private _packedSplitParts2Of;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /** \n @notice \n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /** \n @notice \n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice \n Get all splits for the specified project ID, within the specified domain, for the specified group.\n\n @param _projectId The ID of the project to get splits for.\n @param _domain An identifier within which the returned splits should be considered active.\n @param _group The identifying group of the splits.\n\n @return An array of all splits for the project.\n*/\n function splitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) external view override returns (JBSplit[] memory) {\n return _getStructsFor(_projectId, _domain, _group);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n */\n constructor(\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory\n ) JBOperatable(_operatorStore) {\n projects = _projects;\n directory = _directory;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets a project's splits.\n\n @dev\n Only the owner or operator of a project, or the current controller contract of the project, can set its splits.\n\n @dev\n The new splits must include any currently set splits that are locked.\n\n @param _projectId The ID of the project for which splits are being added.\n @param _domain An identifier within which the splits should be considered active.\n @param _groupedSplits An array of splits to set for any number of groups. \n */\n function set(\n uint256 _projectId,\n uint256 _domain,\n JBGroupedSplits[] calldata _groupedSplits\n )\n external\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.SET_SPLITS,\n address(directory.controllerOf(_projectId)) == msg.sender\n )\n {\n // Push array length in stack\n uint256 _groupedSplitsLength = _groupedSplits.length;\n\n // Set each grouped splits.\n for (uint256 _i; _i < _groupedSplitsLength; ) {\n // Get a reference to the grouped split being iterated on.\n JBGroupedSplits memory _groupedSplit = _groupedSplits[_i];\n\n // Set the splits for the group.\n _set(_projectId, _domain, _groupedSplit.group, _groupedSplit.splits);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets a project's splits.\n\n @dev\n The new splits must include any currently set splits that are locked.\n\n @param _projectId The ID of the project for which splits are being added.\n @param _domain An identifier within which the splits should be considered active.\n @param _group An identifier between of splits being set. All splits within this _group must add up to within 100%.\n @param _splits The splits to set.\n */\n function _set(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n JBSplit[] memory _splits\n ) internal {\n // Get a reference to the project's current splits.\n JBSplit[] memory _currentSplits = _getStructsFor(_projectId, _domain, _group);\n\n // Keep a reference to the number of splits.\n uint256 _currentSplitsLength = _currentSplits.length;\n\n // Check to see if all locked splits are included.\n for (uint256 _i; _i < _currentSplitsLength; ) {\n // If not locked, continue.\n if (\n block.timestamp < _currentSplits[_i].lockedUntil &&\n !_includesLocked(_splits, _currentSplits[_i])\n ) revert PREVIOUS_LOCKED_SPLITS_NOT_INCLUDED();\n\n unchecked {\n ++_i;\n }\n }\n\n // Add up all the percents to make sure they cumulatively are under 100%.\n uint256 _percentTotal;\n\n // Keep a reference to the number of splits.\n uint256 _splitsLength = _splits.length;\n\n for (uint256 _i; _i < _splitsLength; ) {\n // The percent should be greater than 0.\n if (_splits[_i].percent == 0) revert INVALID_SPLIT_PERCENT();\n\n // ProjectId should be within a uint56\n if (_splits[_i].projectId > type(uint56).max) revert INVALID_PROJECT_ID();\n\n // Add to the total percents.\n _percentTotal = _percentTotal + _splits[_i].percent;\n\n // Validate the total does not exceed the expected value.\n if (_percentTotal > JBConstants.SPLITS_TOTAL_PERCENT) revert INVALID_TOTAL_PERCENT();\n\n uint256 _packedSplitParts1;\n\n // prefer claimed in bit 0.\n if (_splits[_i].preferClaimed) _packedSplitParts1 = 1;\n // prefer add to balance in bit 1.\n if (_splits[_i].preferAddToBalance) _packedSplitParts1 |= 1 << 1;\n // percent in bits 2-33.\n _packedSplitParts1 |= _splits[_i].percent << 2;\n // projectId in bits 32-89.\n _packedSplitParts1 |= _splits[_i].projectId << 34;\n // beneficiary in bits 90-249.\n _packedSplitParts1 |= uint256(uint160(address(_splits[_i].beneficiary))) << 90;\n\n // Store the first split part.\n _packedSplitParts1Of[_projectId][_domain][_group][_i] = _packedSplitParts1;\n\n // If there's data to store in the second packed split part, pack and store.\n if (_splits[_i].lockedUntil > 0 || _splits[_i].allocator != IJBSplitAllocator(address(0))) {\n // Locked until should be within a uint48\n if (_splits[_i].lockedUntil > type(uint48).max) revert INVALID_LOCKED_UNTIL();\n\n // lockedUntil in bits 0-47.\n uint256 _packedSplitParts2 = uint48(_splits[_i].lockedUntil);\n // allocator in bits 48-207.\n _packedSplitParts2 |= uint256(uint160(address(_splits[_i].allocator))) << 48;\n\n // Store the second split part.\n _packedSplitParts2Of[_projectId][_domain][_group][_i] = _packedSplitParts2;\n\n // Otherwise if there's a value stored in the indexed position, delete it.\n } else if (_packedSplitParts2Of[_projectId][_domain][_group][_i] > 0)\n delete _packedSplitParts2Of[_projectId][_domain][_group][_i];\n\n emit SetSplit(_projectId, _domain, _group, _splits[_i], msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n\n // Set the new length of the splits.\n _splitCountOf[_projectId][_domain][_group] = _splitsLength;\n }\n\n /** \n @notice\n A flag indiciating if the provided splits array includes the locked split. \n\n @param _splits The array of splits to check within.\n @param _lockedSplit The locked split.\n\n @return A flag indicating if the `_lockedSplit` is contained in the `_splits`.\n */\n function _includesLocked(JBSplit[] memory _splits, JBSplit memory _lockedSplit)\n private\n pure\n returns (bool)\n {\n // Keep a reference to the number of splits.\n uint256 _numberOfSplits = _splits.length;\n\n for (uint256 _i; _i < _numberOfSplits; ) {\n // Check for sameness.\n if (\n _splits[_i].percent == _lockedSplit.percent &&\n _splits[_i].beneficiary == _lockedSplit.beneficiary &&\n _splits[_i].allocator == _lockedSplit.allocator &&\n _splits[_i].projectId == _lockedSplit.projectId &&\n _splits[_i].preferClaimed == _lockedSplit.preferClaimed &&\n _splits[_i].preferAddToBalance == _lockedSplit.preferAddToBalance &&\n // Allow lock extention.\n _splits[_i].lockedUntil >= _lockedSplit.lockedUntil\n ) return true;\n\n unchecked {\n ++_i;\n }\n }\n\n return false;\n }\n\n /**\n @notice \n Unpack splits' packed stored values into easy-to-work-with split structs.\n\n @param _projectId The ID of the project to which the split belongs.\n @param _domain The identifier within which the returned splits should be considered active.\n @param _group The identifying group of the splits.\n\n @return splits The split structs.\n */\n function _getStructsFor(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) private view returns (JBSplit[] memory) {\n // Get a reference to the number of splits that need to be added to the returned array.\n uint256 _splitCount = _splitCountOf[_projectId][_domain][_group];\n\n // Initialize an array to be returned that has the set length.\n JBSplit[] memory _splits = new JBSplit[](_splitCount);\n\n // Loop through each split and unpack the values into structs.\n for (uint256 _i; _i < _splitCount; ) {\n // Get a reference to the fist packed data.\n uint256 _packedSplitPart1 = _packedSplitParts1Of[_projectId][_domain][_group][_i];\n\n // Populate the split struct.\n JBSplit memory _split;\n\n // prefer claimed in bit 0.\n _split.preferClaimed = _packedSplitPart1 & 1 == 1;\n // prefer add to balance in bit 1.\n _split.preferAddToBalance = (_packedSplitPart1 >> 1) & 1 == 1;\n // percent in bits 2-33.\n _split.percent = uint256(uint32(_packedSplitPart1 >> 2));\n // projectId in bits 32-89.\n _split.projectId = uint256(uint56(_packedSplitPart1 >> 34));\n // beneficiary in bits 90-249.\n _split.beneficiary = payable(address(uint160(_packedSplitPart1 >> 90)));\n\n // Get a reference to the second packed data.\n uint256 _packedSplitPart2 = _packedSplitParts2Of[_projectId][_domain][_group][_i];\n\n // If there's anything in it, unpack.\n if (_packedSplitPart2 > 0) {\n // lockedUntil in bits 0-47.\n _split.lockedUntil = uint256(uint48(_packedSplitPart2));\n // allocator in bits 48-207.\n _split.allocator = IJBSplitAllocator(address(uint160(_packedSplitPart2 >> 48)));\n }\n\n // Add the split to the value being returned.\n _splits[_i] = _split;\n\n unchecked {\n ++_i;\n }\n }\n\n return _splits;\n }\n}\n" @@ -322,11 +322,11 @@ "contracts/interfaces/IJBTerminalUtility.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBDirectory.sol';\n\ninterface IJBPaymentTerminalUtility {\n function directory() external view returns (IJBDirectory);\n}\n" }, - "contracts/JBETHERC20ProjectPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './interfaces/IJBETHERC20ProjectPayerDeployer.sol';\nimport './JBETHERC20ProjectPayer.sol';\n\n/** \n @notice \n Deploys project payer contracts.\n\n @dev\n Adheres to -\n IJBETHERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBETHERC20ProjectPayerDeployer is IJBETHERC20ProjectPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new project payer contract.\n\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the project payer contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the project payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the project payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the project payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the project payer.\n\n @return projectPayer The project payer contract.\n */\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external override returns (IJBProjectPayer projectPayer) {\n // Deploy the project payer.\n projectPayer = new JBETHERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner\n );\n\n emit DeployProjectPayer(\n projectPayer,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner,\n msg.sender\n );\n }\n}\n" + "contracts/JBGasTokenERC20ProjectPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './interfaces/IJBGasTokenERC20ProjectPayerDeployer.sol';\nimport './JBGasTokenERC20ProjectPayer.sol';\n\n/** \n @notice \n Deploys project payer contracts.\n\n @dev\n Adheres to -\n IJBGasTokenERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBGasTokenERC20ProjectPayerDeployer is IJBGasTokenERC20ProjectPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new project payer contract.\n\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the project payer contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the project payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the project payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the project payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the project payer.\n\n @return projectPayer The project payer contract.\n */\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external override returns (IJBProjectPayer projectPayer) {\n // Deploy the project payer.\n projectPayer = new JBGasTokenERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner\n );\n\n emit DeployProjectPayer(\n projectPayer,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner,\n msg.sender\n );\n }\n}\n" }, - "contracts/interfaces/IJBETHERC20ProjectPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBDirectory.sol';\nimport './IJBProjectPayer.sol';\n\ninterface IJBETHERC20ProjectPayerDeployer {\n event DeployProjectPayer(\n IJBProjectPayer indexed projectPayer,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n IJBDirectory directory,\n address owner,\n address caller\n );\n\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external returns (IJBProjectPayer projectPayer);\n}\n" + "contracts/interfaces/IJBGasTokenERC20ProjectPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBDirectory.sol';\nimport './IJBProjectPayer.sol';\n\ninterface IJBGasTokenERC20ProjectPayerDeployer {\n event DeployProjectPayer(\n IJBProjectPayer indexed projectPayer,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n IJBDirectory directory,\n address owner,\n address caller\n );\n\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external returns (IJBProjectPayer projectPayer);\n}\n" }, "contracts/JBReconfigurationBufferBallot.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport './interfaces/IJBFundingCycleBallot.sol';\nimport './structs/JBFundingCycle.sol';\n\n/** \n @notice \n Manages approving funding cycle reconfigurations automatically after a buffer period.\n\n @dev\n Adheres to -\n IJBFundingCycleBallot: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ERC165: Introspection on interface adherance. \n*/\ncontract JBReconfigurationBufferBallot is ERC165, IJBFundingCycleBallot {\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice \n The number of seconds that must pass for a funding cycle reconfiguration to become either `Approved` or `Failed`.\n */\n uint256 public immutable override duration;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice \n The approval state of a particular funding cycle.\n\n @param _projectId The ID of the project to which the funding cycle being checked belongs.\n @param _configured The configuration of the funding cycle to check the state of.\n @param _start The start timestamp of the funding cycle to check the state of.\n\n @return The state of the provided ballot. \n */\n function stateOf(\n uint256 _projectId,\n uint256 _configured,\n uint256 _start\n ) public view override returns (JBBallotState) {\n _projectId; // Prevents unused var compiler and natspec complaints.\n\n // If the provided configured timestamp is after the start timestamp, the ballot is Failed.\n if (_configured > _start) return JBBallotState.Failed;\n\n unchecked {\n // If there was sufficient time between configuration and the start of the cycle, it is approved. Otherwise, it is failed.\n return (_start - _configured < duration) ? JBBallotState.Failed : JBBallotState.Approved;\n }\n }\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBFundingCycleBallot).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _duration The number of seconds to wait until a reconfiguration can be either `Approved` or `Failed`.\n */\n constructor(uint256 _duration) {\n duration = _duration;\n }\n}\n" diff --git a/deployments/goerli/solcInputs/e87fd161fb98793b8dd4dcaee81afb88.json b/deployments/goerli/solcInputs/e87fd161fb98793b8dd4dcaee81afb88.json index 611253126..c4b1a1061 100644 --- a/deployments/goerli/solcInputs/e87fd161fb98793b8dd4dcaee81afb88.json +++ b/deployments/goerli/solcInputs/e87fd161fb98793b8dd4dcaee81afb88.json @@ -164,7 +164,7 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './../structs/JBFundAccessConstraints.sol';\nimport './../structs/JBFundingCycleData.sol';\nimport './../structs/JBFundingCycleMetadata.sol';\nimport './../structs/JBGroupedSplits.sol';\nimport './../structs/JBProjectMetadata.sol';\nimport './IJBDirectory.sol';\nimport './IJBFundingCycleStore.sol';\nimport './IJBMigratable.sol';\nimport './IJBPaymentTerminal.sol';\nimport './IJBSplitsStore.sol';\nimport './IJBTokenStore.sol';\n\ninterface IJBController is IERC165 {\n event LaunchProject(uint256 configuration, uint256 projectId, string memo, address caller);\n\n event LaunchFundingCycles(uint256 configuration, uint256 projectId, string memo, address caller);\n\n event ReconfigureFundingCycles(\n uint256 configuration,\n uint256 projectId,\n string memo,\n address caller\n );\n\n event SetFundAccessConstraints(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n JBFundAccessConstraints constraints,\n address caller\n );\n\n event DistributeReservedTokens(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address beneficiary,\n uint256 tokenCount,\n uint256 beneficiaryTokenCount,\n string memo,\n address caller\n );\n\n event DistributeToReservedTokenSplit(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n JBSplit split,\n uint256 tokenCount,\n address caller\n );\n\n event MintTokens(\n address indexed beneficiary,\n uint256 indexed projectId,\n uint256 tokenCount,\n uint256 beneficiaryTokenCount,\n string memo,\n uint256 reservedRate,\n address caller\n );\n\n event BurnTokens(\n address indexed holder,\n uint256 indexed projectId,\n uint256 tokenCount,\n string memo,\n address caller\n );\n\n event Migrate(uint256 indexed projectId, IJBMigratable to, address caller);\n\n event PrepMigration(uint256 indexed projectId, address from, address caller);\n\n function projects() external view returns (IJBProjects);\n\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\n\n function tokenStore() external view returns (IJBTokenStore);\n\n function splitsStore() external view returns (IJBSplitsStore);\n\n function directory() external view returns (IJBDirectory);\n\n function reservedTokenBalanceOf(uint256 _projectId, uint256 _reservedRate)\n external\n view\n returns (uint256);\n\n function distributionLimitOf(\n uint256 _projectId,\n uint256 _configuration,\n IJBPaymentTerminal _terminal,\n address _token\n ) external view returns (uint256 distributionLimit, uint256 distributionLimitCurrency);\n\n function overflowAllowanceOf(\n uint256 _projectId,\n uint256 _configuration,\n IJBPaymentTerminal _terminal,\n address _token\n ) external view returns (uint256 overflowAllowance, uint256 overflowAllowanceCurrency);\n\n function totalOutstandingTokensOf(uint256 _projectId, uint256 _reservedRate)\n external\n view\n returns (uint256);\n\n function getFundingCycleOf(uint256 _projectId, uint256 _configuration)\n external\n view\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\n\n function latestConfiguredFundingCycleOf(uint256 _projectId)\n external\n view\n returns (\n JBFundingCycle memory,\n JBFundingCycleMetadata memory metadata,\n JBBallotState\n );\n\n function currentFundingCycleOf(uint256 _projectId)\n external\n view\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\n\n function queuedFundingCycleOf(uint256 _projectId)\n external\n view\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\n\n function launchProjectFor(\n address _owner,\n JBProjectMetadata calldata _projectMetadata,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] memory _groupedSplits,\n JBFundAccessConstraints[] memory _fundAccessConstraints,\n IJBPaymentTerminal[] memory _terminals,\n string calldata _memo\n ) external returns (uint256 projectId);\n\n function launchFundingCyclesFor(\n uint256 _projectId,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] memory _groupedSplits,\n JBFundAccessConstraints[] memory _fundAccessConstraints,\n IJBPaymentTerminal[] memory _terminals,\n string calldata _memo\n ) external returns (uint256 configuration);\n\n function reconfigureFundingCyclesOf(\n uint256 _projectId,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] memory _groupedSplits,\n JBFundAccessConstraints[] memory _fundAccessConstraints,\n string calldata _memo\n ) external returns (uint256);\n\n function mintTokensOf(\n uint256 _projectId,\n uint256 _tokenCount,\n address _beneficiary,\n string calldata _memo,\n bool _preferClaimedTokens,\n bool _useReservedRate\n ) external returns (uint256 beneficiaryTokenCount);\n\n function burnTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string calldata _memo,\n bool _preferClaimedTokens\n ) external;\n\n function distributeReservedTokensOf(uint256 _projectId, string memory _memo)\n external\n returns (uint256);\n\n function migrate(uint256 _projectId, IJBMigratable _to) external;\n}\n" }, "contracts/JBSingleTokenPaymentTerminalStore3_1.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController3_1.sol';\nimport './interfaces/IJBFundingCycleDataSource.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './structs/JBPayDelegateAllocation.sol';\nimport './structs/JBPayParamsData.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n\n @dev\n This Store expects a project's controller to be an IJBController3_1. This is the only difference between this version and the original.\n*/\ncontract JBSingleTokenPaymentTerminalStore3_1 is\n ReentrancyGuard,\n IJBSingleTokenPaymentTerminalStore\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId);\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n JBPayDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .payParams(_data);\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\n {\n // Keep a reference to the amount that should be added to the project's balance.\n uint256 _balanceDiff = _amount.value;\n\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\n if (delegateAllocations.length != 0) {\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0) {\n // Can't delegate more than was paid.\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\n\n // Decrement the total amount being added to the balance.\n _balanceDiff = _balanceDiff - _delegatedAmount;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Add the correct balance difference to the token balance of the project.\n if (_balanceDiff != 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _balanceDiff;\n }\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId);\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow != 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\n {\n // Get a reference to the ballot state.\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\n\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n _state == JBBallotState.Active\n ? fundingCycle.ballotRedemptionRate()\n : fundingCycle.redemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\n fundingCycle.dataSource()\n ).redeemParams(_data);\n }\n } else {\n memo = _memo;\n }\n }\n\n // Keep a reference to the amount that should be subtracted from the project's balance.\n uint256 _balanceDiff = reclaimAmount;\n\n if (delegateAllocations.length != 0) {\n // Validate all delegated amounts.\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0)\n // Increment the total amount being subtracted from the balance.\n _balanceDiff = _balanceDiff + _delegatedAmount;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (_balanceDiff != 0) {\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n _balanceDiff;\n }\n }\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).fundAccessConstraintsStore().distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).fundAccessConstraintsStore().overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).fundAccessConstraintsStore().distributionLimitOf(\n _projectId,\n _fundingCycle.configuration,\n _terminal,\n _terminal.token()\n );\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n unchecked {\n return\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i; _i < _terminals.length; ) {\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n unchecked {\n ++_i;\n }\n }\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.ETH\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.ETH, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController3_1.sol';\nimport './interfaces/IJBFundingCycleDataSource.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './structs/JBPayDelegateAllocation.sol';\nimport './structs/JBPayParamsData.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n\n @dev\n This Store expects a project's controller to be an IJBController3_1. This is the only difference between this version and the original.\n*/\ncontract JBSingleTokenPaymentTerminalStore3_1 is\n ReentrancyGuard,\n IJBSingleTokenPaymentTerminalStore\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId);\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n JBPayDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .payParams(_data);\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\n {\n // Keep a reference to the amount that should be added to the project's balance.\n uint256 _balanceDiff = _amount.value;\n\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\n if (delegateAllocations.length != 0) {\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0) {\n // Can't delegate more than was paid.\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\n\n // Decrement the total amount being added to the balance.\n _balanceDiff = _balanceDiff - _delegatedAmount;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Add the correct balance difference to the token balance of the project.\n if (_balanceDiff != 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _balanceDiff;\n }\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId);\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow != 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\n {\n // Get a reference to the ballot state.\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\n\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n _state == JBBallotState.Active\n ? fundingCycle.ballotRedemptionRate()\n : fundingCycle.redemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\n fundingCycle.dataSource()\n ).redeemParams(_data);\n }\n } else {\n memo = _memo;\n }\n }\n\n // Keep a reference to the amount that should be subtracted from the project's balance.\n uint256 _balanceDiff = reclaimAmount;\n\n if (delegateAllocations.length != 0) {\n // Validate all delegated amounts.\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0)\n // Increment the total amount being subtracted from the balance.\n _balanceDiff = _balanceDiff + _delegatedAmount;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (_balanceDiff != 0) {\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n _balanceDiff;\n }\n }\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).fundAccessConstraintsStore().distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).fundAccessConstraintsStore().overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).fundAccessConstraintsStore().distributionLimitOf(\n _projectId,\n _fundingCycle.configuration,\n _terminal,\n _terminal.token()\n );\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n unchecked {\n return\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i; _i < _terminals.length; ) {\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n unchecked {\n ++_i;\n }\n }\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.GAS_CURRENCY\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.GAS_CURRENCY, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" }, "@openzeppelin/contracts/security/ReentrancyGuard.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n constructor() {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n // On the first call to nonReentrant, _notEntered will be true\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n\n _;\n\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n}\n" @@ -224,7 +224,7 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IJBPriceFeed {\n function currentPrice(uint256 _targetDecimals) external view returns (uint256);\n}\n" }, "contracts/JBSingleTokenPaymentTerminalStore.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController.sol';\nimport './interfaces/IJBFundingCycleDataSource.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './structs/JBPayDelegateAllocation.sol';\nimport './structs/JBPayParamsData.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBSingleTokenPaymentTerminalStore is ReentrancyGuard, IJBSingleTokenPaymentTerminalStore {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n JBPayDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .payParams(_data);\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\n {\n // Keep a reference to the amount that should be added to the project's balance.\n uint256 _balanceDiff = _amount.value;\n\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\n if (delegateAllocations.length != 0) {\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0) {\n // Can't delegate more than was paid.\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\n\n // Decrement the total amount being added to the balance.\n _balanceDiff = _balanceDiff - _delegatedAmount;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Add the correct balance difference to the token balance of the project.\n if (_balanceDiff != 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _balanceDiff;\n }\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\n _projectId,\n fundingCycle.reservedRate()\n );\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow != 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\n {\n // Get a reference to the ballot state.\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\n\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n _state == JBBallotState.Active\n ? fundingCycle.ballotRedemptionRate()\n : fundingCycle.redemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\n fundingCycle.dataSource()\n ).redeemParams(_data);\n }\n } else {\n memo = _memo;\n }\n }\n\n // Keep a reference to the amount that should be subtracted from the project's balance.\n uint256 _balanceDiff = reclaimAmount;\n\n if (delegateAllocations.length != 0) {\n // Validate all delegated amounts.\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0)\n // Increment the total amount being subtracted from the balance.\n _balanceDiff = _balanceDiff + _delegatedAmount;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (_balanceDiff != 0) {\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n _balanceDiff;\n }\n }\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n unchecked {\n return\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i; _i < _terminals.length; ) {\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n unchecked {\n ++_i;\n }\n }\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.ETH\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.ETH, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController.sol';\nimport './interfaces/IJBFundingCycleDataSource.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './structs/JBPayDelegateAllocation.sol';\nimport './structs/JBPayParamsData.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBSingleTokenPaymentTerminalStore is ReentrancyGuard, IJBSingleTokenPaymentTerminalStore {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n JBPayDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .payParams(_data);\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\n {\n // Keep a reference to the amount that should be added to the project's balance.\n uint256 _balanceDiff = _amount.value;\n\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\n if (delegateAllocations.length != 0) {\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0) {\n // Can't delegate more than was paid.\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\n\n // Decrement the total amount being added to the balance.\n _balanceDiff = _balanceDiff - _delegatedAmount;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Add the correct balance difference to the token balance of the project.\n if (_balanceDiff != 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _balanceDiff;\n }\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\n _projectId,\n fundingCycle.reservedRate()\n );\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow != 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\n {\n // Get a reference to the ballot state.\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\n\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n _state == JBBallotState.Active\n ? fundingCycle.ballotRedemptionRate()\n : fundingCycle.redemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\n fundingCycle.dataSource()\n ).redeemParams(_data);\n }\n } else {\n memo = _memo;\n }\n }\n\n // Keep a reference to the amount that should be subtracted from the project's balance.\n uint256 _balanceDiff = reclaimAmount;\n\n if (delegateAllocations.length != 0) {\n // Validate all delegated amounts.\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0)\n // Increment the total amount being subtracted from the balance.\n _balanceDiff = _balanceDiff + _delegatedAmount;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (_balanceDiff != 0) {\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n _balanceDiff;\n }\n }\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n unchecked {\n return\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i; _i < _terminals.length; ) {\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n unchecked {\n ++_i;\n }\n }\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.GAS_CURRENCY\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.GAS_CURRENCY, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" }, "contracts/interfaces/IJBPayoutRedemptionPaymentTerminal3_1.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './../structs/JBFee.sol';\nimport './IJBAllowanceTerminal3_1.sol';\nimport './IJBDirectory.sol';\nimport './IJBFeeGauge.sol';\nimport './IJBFeeHoldingTerminal.sol';\nimport './IJBPayDelegate.sol';\nimport './IJBPaymentTerminal.sol';\nimport './IJBPayoutTerminal3_1.sol';\nimport './IJBPrices.sol';\nimport './IJBProjects.sol';\nimport './IJBRedemptionDelegate.sol';\nimport './IJBRedemptionTerminal.sol';\nimport './IJBSingleTokenPaymentTerminalStore.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBPayoutRedemptionPaymentTerminal3_1 is\n IJBPaymentTerminal,\n IJBPayoutTerminal3_1,\n IJBAllowanceTerminal3_1,\n IJBRedemptionTerminal,\n IJBFeeHoldingTerminal\n{\n event AddToBalance(\n uint256 indexed projectId,\n uint256 amount,\n uint256 refundedFees,\n string memo,\n bytes metadata,\n address caller\n );\n\n event Migrate(\n uint256 indexed projectId,\n IJBPaymentTerminal indexed to,\n uint256 amount,\n address caller\n );\n\n event DistributePayouts(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address beneficiary,\n uint256 amount,\n uint256 distributedAmount,\n uint256 fee,\n uint256 beneficiaryDistributionAmount,\n bytes metadata,\n address caller\n );\n\n event UseAllowance(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address beneficiary,\n uint256 amount,\n uint256 distributedAmount,\n uint256 netDistributedamount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event HoldFee(\n uint256 indexed projectId,\n uint256 indexed amount,\n uint256 indexed fee,\n uint256 feeDiscount,\n address beneficiary,\n address caller\n );\n\n event ProcessFee(\n uint256 indexed projectId,\n uint256 indexed amount,\n bool indexed wasHeld,\n address beneficiary,\n address caller\n );\n\n event RefundHeldFees(\n uint256 indexed projectId,\n uint256 indexed amount,\n uint256 indexed refundedFees,\n uint256 leftoverAmount,\n address caller\n );\n\n event Pay(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address payer,\n address beneficiary,\n uint256 amount,\n uint256 beneficiaryTokenCount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DelegateDidPay(\n IJBPayDelegate indexed delegate,\n JBDidPayData data,\n uint256 delegatedAmount,\n address caller\n );\n\n event RedeemTokens(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address holder,\n address beneficiary,\n uint256 tokenCount,\n uint256 reclaimedAmount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DelegateDidRedeem(\n IJBRedemptionDelegate indexed delegate,\n JBDidRedeemData data,\n uint256 delegatedAmount,\n address caller\n );\n\n event DistributeToPayoutSplit(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n JBSplit split,\n uint256 amount,\n uint256 netAmount,\n address caller\n );\n\n event SetFee(uint256 fee, address caller);\n\n event SetFeeGauge(IJBFeeGauge indexed feeGauge, address caller);\n\n event SetFeelessAddress(address indexed addrs, bool indexed flag, address caller);\n\n event PayoutReverted(uint256 indexed projectId, JBSplit split, uint256 amount, bytes reason, address caller);\n\n event FeeReverted(\n uint256 indexed projectId,\n uint256 indexed feeProjectId,\n uint256 amount,\n bytes reason,\n address caller\n );\n\n function projects() external view returns (IJBProjects);\n\n function splitsStore() external view returns (IJBSplitsStore);\n\n function directory() external view returns (IJBDirectory);\n\n function prices() external view returns (IJBPrices);\n\n function store() external view returns (IJBSingleTokenPaymentTerminalStore);\n\n function baseWeightCurrency() external view returns (uint256);\n\n function payoutSplitsGroup() external view returns (uint256);\n\n function heldFeesOf(uint256 _projectId) external view returns (JBFee[] memory);\n\n function fee() external view returns (uint256);\n\n function feeGauge() external view returns (IJBFeeGauge);\n\n function isFeelessAddress(address _contract) external view returns (bool);\n\n function migrate(uint256 _projectId, IJBPaymentTerminal _to) external returns (uint256 balance);\n\n function processFees(uint256 _projectId) external;\n\n function setFee(uint256 _fee) external;\n\n function setFeeGauge(IJBFeeGauge _feeGauge) external;\n\n function setFeelessAddress(address _contract, bool _flag) external;\n}\n" @@ -296,10 +296,10 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nlibrary JBSplitsGroups {\n uint256 public constant ETH_PAYOUT = 1;\n uint256 public constant RESERVED_TOKENS = 2;\n}\n" }, "contracts/JBETHPaymentTerminal3_1.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal3_1.sol';\nimport './libraries/JBSplitsGroups.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal3_1: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal3_1 is JBPayoutRedemptionPaymentTerminal3_1 {\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return address(this).balance;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal3_1(\n JBTokens.ETH,\n 18, // 18 decimals.\n JBCurrencies.ETH,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal3_1.sol';\nimport './libraries/JBSplitsGroups.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal3_1: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal3_1 is JBPayoutRedemptionPaymentTerminal3_1 {\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return address(this).balance;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal3_1(\n JBTokens.GAS_TOKEN,\n 18, // 18 decimals.\n JBCurrencies.GAS_CURRENCY,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n}\n" }, "contracts/abstract/JBPayoutRedemptionPaymentTerminal3_1.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/utils/introspection/ERC165Checker.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal3_1.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBPayDelegateAllocation.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal3_1: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal3_1 is\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n IJBPayoutRedemptionPaymentTerminal3_1\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n @dev\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.ETH)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.ETH, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal3_1).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal3_1).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal3_1).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance.\n */\n function _balance() internal view virtual returns (uint256);\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n bytes calldata _metadata\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _metadata);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes calldata _metadata\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _useAllowanceOf(\n _projectId,\n _amount,\n _currency,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n // Do not refund held fees by default.\n addToBalanceOf(_projectId, _amount, _token, false, _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary, _projectId);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n bool _shouldRefundHeldFees,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.ETH) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance.\n _addToBalanceOf(_projectId, _amount, _shouldRefundHeldFees, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual {\n _from; // Prevents unused var compiler and natspec complaints.\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered if a transfer should be undone\n\n @param _to The address to which the transfer went.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _cancelTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\n {\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\n\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _forwardedAmount,\n _beneficiary,\n _memo,\n _metadata\n );\n\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\n\n emit DelegateDidRedeem(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n bytes calldata _metadata\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n }\n\n // Take the fee.\n _fee = _feeEligibleDistributionAmount != 0\n ? _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n )\n : 0;\n\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\n if (_leftoverDistributionAmount != 0) {\n // Subtract the fee from the net leftover amount.\n netLeftoverDistributionAmount =\n _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n\n // Transfer the amount to the project owner.\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes calldata _metadata\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n // The total percentage available to split\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = _split.percent == leftoverPercentage\n ? leftoverAmount\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\n\n // Decrement the leftover percentage.\n leftoverPercentage -= _split.percent;\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount = _distributeToPayoutSplit(\n _split,\n _projectId,\n _group,\n _payoutAmount,\n _feeDiscount\n );\n\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (_netPayoutAmount != 0 && _netPayoutAmount != _payoutAmount)\n feeEligibleDistributionAmount += _payoutAmount;\n\n if (_payoutAmount > 0) {\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _payoutAmount,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Pays out a split for a project's funding cycle configuration.\n \n @param _split The split to distribute payouts to.\n @param _amount The total amount being distributed to the split, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return netPayoutAmount The amount sent to the split after subtracting fees.\n */\n function _distributeToPayoutSplit(\n JBSplit memory _split,\n uint256 _projectId,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 netPayoutAmount) {\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_split.allocator)]\n )\n netPayoutAmount = _amount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\n }\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), netPayoutAmount);\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n uint256 _error;\n bytes memory _reason;\n\n if (\n ERC165Checker.supportsInterface(\n address(_split.allocator),\n type(IJBSplitAllocator).interfaceId\n )\n )\n // If this terminal's token is ETH, send it in msg.value.\n try _split.allocator.allocate{value: token == JBTokens.ETH ? netPayoutAmount : 0}(_data) {\n\n } catch (bytes memory reason) {\n _reason = reason;\n _error = 1;\n }\n else _error = 2;\n\n\n if (_error != 0) {\n // Trigger any inhereted post-transfer cancelation logic.\n _cancelTransferTo(address(_split.allocator), netPayoutAmount);\n\n // Set the net payout amount to 0 to signal the reversion.\n netPayoutAmount = 0;\n\n // Add undistributed amount back to project's balance.\n store.recordAddedBalanceFor(_projectId, _amount);\n\n emit PayoutReverted(_projectId, _split, _amount, _error == 1 ? _reason : abi.encode(\"IERC165 fail\"), msg.sender);\n }\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (\n _terminal == this ||\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\n isFeelessAddress[address(_terminal)]\n )\n netPayoutAmount = _amount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\n }\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), netPayoutAmount);\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n try\n _terminal.addToBalanceOf{value: token == JBTokens.ETH ? netPayoutAmount : 0}(\n _split.projectId,\n netPayoutAmount,\n token,\n '',\n _projectMetadata\n )\n {} catch (bytes memory reason) {\n // Trigger any inhereted post-transfer cancelation logic.\n _cancelTransferTo(address(_terminal), netPayoutAmount);\n\n // Set the net payout amount to 0 to signal the reversion.\n netPayoutAmount = 0;\n\n // Add undistributed amount back to project's balance.\n store.recordAddedBalanceFor(_projectId, _amount);\n\n emit PayoutReverted(_projectId, _split, _amount, reason, msg.sender);\n }\n else\n try\n _terminal.pay{value: token == JBTokens.ETH ? netPayoutAmount : 0}(\n _split.projectId,\n netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n )\n {} catch (bytes memory reason) {\n // Trigger any inhereted post-transfer cancelation logic.\n _cancelTransferTo(address(_terminal), netPayoutAmount);\n\n // Set the net payout amount to 0 to signal the reversion.\n netPayoutAmount = 0;\n\n // Add undistributed amount back to project's balance.\n store.recordAddedBalanceFor(_projectId, _amount);\n\n emit PayoutReverted(_projectId, _split, _amount, reason, msg.sender);\n }\n } else {\n // Keep a reference to the beneficiary.\n address payable _beneficiary = _split.beneficiary != address(0)\n ? _split.beneficiary\n : payable(msg.sender);\n\n // If there's a full discount, this distribution is not eligible for a fee.\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\n netPayoutAmount = _amount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\n else {\n unchecked {\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\n }\n }\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(address(this), _beneficiary, netPayoutAmount);\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary, _projectId); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n @param _from The project ID the fee is being paid from.\n */\n function _processFee(\n uint256 _amount,\n address _beneficiary,\n uint256 _from\n ) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _amount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_from));\n\n // Trigger any inherited pre-transfer logic if funds will be transferred.\n if (address(_terminal) != address(this)) _beforeTransferTo(address(_terminal), _amount);\n\n try\n // Send the fee.\n _terminal.pay{value: _payableValue}(\n _FEE_BENEFICIARY_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n _projectMetadata\n )\n {} catch (bytes memory reason) {\n // Trigger any inhereted post-transfer cancelation logic if the pre-transfer logic was triggered.\n if (address(_terminal) != address(this)) _cancelTransferTo(address(_terminal), _amount);\n\n // Add fee amount back to project's balance.\n store.recordAddedBalanceFor(_from, _amount);\n\n emit FeeReverted(_from, _FEE_BENEFICIARY_PROJECT_ID, _amount, reason, msg.sender);\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\n {\n JBPayDelegateAllocation[] memory _delegateAllocations;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n _forwardedAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n // Get a reference to the number of delegates to allocate to.\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\n\n emit DelegateDidPay(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n unchecked {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\n IJBPaymentTerminal(address(0))\n ) return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge != IJBFeeGauge(address(0)))\n // If the guage reverts, keep the discount at 0.\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n // If the fee discount is greater than the max, we ignore the return value\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\n } catch {\n return 0;\n }\n\n return 0;\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/utils/introspection/ERC165Checker.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal3_1.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBPayDelegateAllocation.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal3_1: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal3_1 is\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n IJBPayoutRedemptionPaymentTerminal3_1\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n @dev\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.GAS_CURRENCY)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.GAS_CURRENCY, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal3_1).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal3_1).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal3_1).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance.\n */\n function _balance() internal view virtual returns (uint256);\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n bytes calldata _metadata\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _metadata);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes calldata _metadata\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _useAllowanceOf(\n _projectId,\n _amount,\n _currency,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n // Do not refund held fees by default.\n addToBalanceOf(_projectId, _amount, _token, false, _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary, _projectId);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n bool _shouldRefundHeldFees,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.GAS_TOKEN) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance.\n _addToBalanceOf(_projectId, _amount, _shouldRefundHeldFees, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual {\n _from; // Prevents unused var compiler and natspec complaints.\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered if a transfer should be undone\n\n @param _to The address to which the transfer went.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _cancelTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\n {\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\n\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _forwardedAmount,\n _beneficiary,\n _memo,\n _metadata\n );\n\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\n\n emit DelegateDidRedeem(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n bytes calldata _metadata\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n }\n\n // Take the fee.\n _fee = _feeEligibleDistributionAmount != 0\n ? _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n )\n : 0;\n\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\n if (_leftoverDistributionAmount != 0) {\n // Subtract the fee from the net leftover amount.\n netLeftoverDistributionAmount =\n _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n\n // Transfer the amount to the project owner.\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes calldata _metadata\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n // The total percentage available to split\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = _split.percent == leftoverPercentage\n ? leftoverAmount\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\n\n // Decrement the leftover percentage.\n leftoverPercentage -= _split.percent;\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount = _distributeToPayoutSplit(\n _split,\n _projectId,\n _group,\n _payoutAmount,\n _feeDiscount\n );\n\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (_netPayoutAmount != 0 && _netPayoutAmount != _payoutAmount)\n feeEligibleDistributionAmount += _payoutAmount;\n\n if (_payoutAmount > 0) {\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _payoutAmount,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Pays out a split for a project's funding cycle configuration.\n \n @param _split The split to distribute payouts to.\n @param _amount The total amount being distributed to the split, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return netPayoutAmount The amount sent to the split after subtracting fees.\n */\n function _distributeToPayoutSplit(\n JBSplit memory _split,\n uint256 _projectId,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 netPayoutAmount) {\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_split.allocator)]\n )\n netPayoutAmount = _amount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\n }\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), netPayoutAmount);\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n uint256 _error;\n bytes memory _reason;\n\n if (\n ERC165Checker.supportsInterface(\n address(_split.allocator),\n type(IJBSplitAllocator).interfaceId\n )\n )\n // If this terminal's token is ETH, send it in msg.value.\n try _split.allocator.allocate{value: token == JBTokens.GAS_TOKEN ? netPayoutAmount : 0}(_data) {\n\n } catch (bytes memory reason) {\n _reason = reason;\n _error = 1;\n }\n else _error = 2;\n\n\n if (_error != 0) {\n // Trigger any inhereted post-transfer cancelation logic.\n _cancelTransferTo(address(_split.allocator), netPayoutAmount);\n\n // Set the net payout amount to 0 to signal the reversion.\n netPayoutAmount = 0;\n\n // Add undistributed amount back to project's balance.\n store.recordAddedBalanceFor(_projectId, _amount);\n\n emit PayoutReverted(_projectId, _split, _amount, _error == 1 ? _reason : abi.encode(\"IERC165 fail\"), msg.sender);\n }\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (\n _terminal == this ||\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\n isFeelessAddress[address(_terminal)]\n )\n netPayoutAmount = _amount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\n }\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), netPayoutAmount);\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n try\n _terminal.addToBalanceOf{value: token == JBTokens.GAS_TOKEN ? netPayoutAmount : 0}(\n _split.projectId,\n netPayoutAmount,\n token,\n '',\n _projectMetadata\n )\n {} catch (bytes memory reason) {\n // Trigger any inhereted post-transfer cancelation logic.\n _cancelTransferTo(address(_terminal), netPayoutAmount);\n\n // Set the net payout amount to 0 to signal the reversion.\n netPayoutAmount = 0;\n\n // Add undistributed amount back to project's balance.\n store.recordAddedBalanceFor(_projectId, _amount);\n\n emit PayoutReverted(_projectId, _split, _amount, reason, msg.sender);\n }\n else\n try\n _terminal.pay{value: token == JBTokens.GAS_TOKEN ? netPayoutAmount : 0}(\n _split.projectId,\n netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n )\n {} catch (bytes memory reason) {\n // Trigger any inhereted post-transfer cancelation logic.\n _cancelTransferTo(address(_terminal), netPayoutAmount);\n\n // Set the net payout amount to 0 to signal the reversion.\n netPayoutAmount = 0;\n\n // Add undistributed amount back to project's balance.\n store.recordAddedBalanceFor(_projectId, _amount);\n\n emit PayoutReverted(_projectId, _split, _amount, reason, msg.sender);\n }\n } else {\n // Keep a reference to the beneficiary.\n address payable _beneficiary = _split.beneficiary != address(0)\n ? _split.beneficiary\n : payable(msg.sender);\n\n // If there's a full discount, this distribution is not eligible for a fee.\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\n netPayoutAmount = _amount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\n else {\n unchecked {\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\n }\n }\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(address(this), _beneficiary, netPayoutAmount);\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary, _projectId); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n @param _from The project ID the fee is being paid from.\n */\n function _processFee(\n uint256 _amount,\n address _beneficiary,\n uint256 _from\n ) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_from));\n\n // Trigger any inherited pre-transfer logic if funds will be transferred.\n if (address(_terminal) != address(this)) _beforeTransferTo(address(_terminal), _amount);\n\n try\n // Send the fee.\n _terminal.pay{value: _payableValue}(\n _FEE_BENEFICIARY_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n _projectMetadata\n )\n {} catch (bytes memory reason) {\n // Trigger any inhereted post-transfer cancelation logic if the pre-transfer logic was triggered.\n if (address(_terminal) != address(this)) _cancelTransferTo(address(_terminal), _amount);\n\n // Add fee amount back to project's balance.\n store.recordAddedBalanceFor(_from, _amount);\n\n emit FeeReverted(_from, _FEE_BENEFICIARY_PROJECT_ID, _amount, reason, msg.sender);\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\n {\n JBPayDelegateAllocation[] memory _delegateAllocations;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n _forwardedAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n // Get a reference to the number of delegates to allocate to.\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\n\n emit DelegateDidPay(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n unchecked {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\n IJBPaymentTerminal(address(0))\n ) return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge != IJBFeeGauge(address(0)))\n // If the guage reverts, keep the discount at 0.\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n // If the fee discount is greater than the max, we ignore the return value\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\n } catch {\n return 0;\n }\n\n return 0;\n }\n}\n" }, "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165Checker.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Library used to query support of an interface declared via {IERC165}.\n *\n * Note that these functions return the actual result of the query: they do not\n * `revert` if an interface is not supported. It is up to the caller to decide\n * what to do in these cases.\n */\nlibrary ERC165Checker {\n // As per the EIP-165 spec, no interface should ever match 0xffffffff\n bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;\n\n /**\n * @dev Returns true if `account` supports the {IERC165} interface,\n */\n function supportsERC165(address account) internal view returns (bool) {\n // Any contract that implements ERC165 must explicitly indicate support of\n // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid\n return\n _supportsERC165Interface(account, type(IERC165).interfaceId) &&\n !_supportsERC165Interface(account, _INTERFACE_ID_INVALID);\n }\n\n /**\n * @dev Returns true if `account` supports the interface defined by\n * `interfaceId`. Support for {IERC165} itself is queried automatically.\n *\n * See {IERC165-supportsInterface}.\n */\n function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {\n // query support of both ERC165 as per the spec and support of _interfaceId\n return supportsERC165(account) && _supportsERC165Interface(account, interfaceId);\n }\n\n /**\n * @dev Returns a boolean array where each value corresponds to the\n * interfaces passed in and whether they're supported or not. This allows\n * you to batch check interfaces for a contract where your expectation\n * is that some interfaces may not be supported.\n *\n * See {IERC165-supportsInterface}.\n *\n * _Available since v3.4._\n */\n function getSupportedInterfaces(address account, bytes4[] memory interfaceIds)\n internal\n view\n returns (bool[] memory)\n {\n // an array of booleans corresponding to interfaceIds and whether they're supported or not\n bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);\n\n // query support of ERC165 itself\n if (supportsERC165(account)) {\n // query support of each interface in interfaceIds\n for (uint256 i = 0; i < interfaceIds.length; i++) {\n interfaceIdsSupported[i] = _supportsERC165Interface(account, interfaceIds[i]);\n }\n }\n\n return interfaceIdsSupported;\n }\n\n /**\n * @dev Returns true if `account` supports all the interfaces defined in\n * `interfaceIds`. Support for {IERC165} itself is queried automatically.\n *\n * Batch-querying can lead to gas savings by skipping repeated checks for\n * {IERC165} support.\n *\n * See {IERC165-supportsInterface}.\n */\n function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {\n // query support of ERC165 itself\n if (!supportsERC165(account)) {\n return false;\n }\n\n // query support of each interface in _interfaceIds\n for (uint256 i = 0; i < interfaceIds.length; i++) {\n if (!_supportsERC165Interface(account, interfaceIds[i])) {\n return false;\n }\n }\n\n // all interfaces supported\n return true;\n }\n\n /**\n * @notice Query if a contract implements an interface, does not check ERC165 support\n * @param account The address of the contract to query for support of an interface\n * @param interfaceId The interface identifier, as specified in ERC-165\n * @return true if the contract at account indicates support of the interface with\n * identifier interfaceId, false otherwise\n * @dev Assumes that account contains a contract that supports ERC165, otherwise\n * the behavior of this method is undefined. This precondition can be checked\n * with {supportsERC165}.\n * Interface identification is specified in ERC-165.\n */\n function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) {\n bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);\n (bool success, bytes memory result) = account.staticcall{gas: 30000}(encodedParams);\n if (result.length < 32) return false;\n return success && abi.decode(result, (bool));\n }\n}\n" @@ -316,32 +316,32 @@ "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n function safeTransfer(\n IERC20 token,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(\n IERC20 token,\n address from,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n uint256 newAllowance = token.allowance(address(this), spender) + value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n uint256 newAllowance = oldAllowance - value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) {\n // Return data is optional\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" }, - "contracts/JBETHERC20SplitsPayer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBSplitsPayer.sol';\nimport './interfaces/IJBSplitsStore.sol';\nimport './libraries/JBConstants.sol';\nimport './JBETHERC20ProjectPayer.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\n\n @dev\n Adheres to -\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBETHERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBETHERC20SplitsPayer is JBETHERC20ProjectPayer, ReentrancyGuard, IJBSplitsPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The ID of project for which the default splits are stored. \n */\n uint256 public override defaultSplitsProjectId;\n\n /**\n @notice\n The domain within which the default splits are stored. \n */\n uint256 public override defaultSplitsDomain;\n\n /**\n @notice\n The group within which the default splits are stored. \n */\n uint256 public override defaultSplitsGroup;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBETHERC20ProjectPayer, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n/**\n @param _splitsStore A contract that stores splits for each project.\n*/\n constructor(\n IJBSplitsStore _splitsStore\n )\n JBETHERC20ProjectPayer(\n _splitsStore.directory()\n )\n {\n splitsStore = _splitsStore;\n }\n /**\n @dev The re-initialize check is done in the inherited paroject payer\n \n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n function initialize(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external override {\n\n super.initialize(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _preferAddToBalance,\n _owner\n );\n\n defaultSplitsProjectId = _defaultSplitsProjectId;\n defaultSplitsDomain = _defaultSplitsDomain;\n defaultSplitsGroup = _defaultSplitsGroup;\n }\n\n\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default split group using the stored default properties.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override nonReentrant {\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n JBTokens.ETH,\n address(this).balance,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // If there is no leftover amount, nothing left to pay.\n if (_leftoverAmount == 0) return;\n\n // If there's a default project ID, try to pay it.\n if (defaultProjectId != 0)\n if (defaultPreferAddToBalance)\n // Pay the project by adding to its balance if prefered.\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.ETH,\n _leftoverAmount,\n 18, // decimals.\n defaultMemo,\n defaultMetadata\n );\n // Otherwise, issue a payment to the project.\n else\n _pay(\n defaultProjectId,\n JBTokens.ETH,\n _leftoverAmount,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n 0, // min returned tokens.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else\n Address.sendValue(\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(tx.origin),\n _leftoverAmount\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the splits in the splits store that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n @param _groupedSplits The split groups to set.\n */\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n JBGroupedSplits[] memory _groupedSplits\n ) external virtual override onlyOwner {\n // Set the splits in the store.\n splitsStore.set(_projectId, _domain, _groupedSplits);\n\n // Set the splits reference.\n setDefaultSplitsReference(_projectId, _domain, _group);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the location of the splits that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n */\n function setDefaultSplitsReference(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) public virtual override onlyOwner {\n // Set the default splits project ID if it's changing.\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\n\n // Set the default splits domain if it's changing.\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\n\n // Set the default splits group if it's changing.\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\n\n emit SetDefaultSplitsReference(_projectId, _domain, _group, msg.sender);\n }\n\n /** \n @notice \n Make a payment to the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Pay any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to pay it.\n if (_projectId != 0) {\n _pay(\n _projectId,\n _token,\n _leftoverAmount,\n _decimals,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? payable(_beneficiary) : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit Pay(\n _projectId,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event. \n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Distribute any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to add to its balance.\n if (_projectId != 0)\n // Add to the project's balance.\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\n\n // Otherwise, send a payment to the beneficiary.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit AddToBalance(\n _projectId,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splitsProjectId The ID of the project to which the splits belong.\n @param _splitsDomain The splits domain to which the group belongs.\n @param _splitsGroup The splits group to pay.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payToSplits(\n uint256 _splitsProjectId,\n uint256 _splitsDomain,\n uint256 _splitsGroup,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Pay the splits.\n leftoverAmount = _payTo(\n splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup),\n _token,\n _amount,\n _decimals,\n _defaultBeneficiary\n );\n emit DistributeToSplitGroup(_splitsProjectId, _splitsDomain, _splitsGroup, msg.sender);\n }\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splits The splits.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payTo(\n JBSplit[] memory _splits,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Set the leftover amount to the initial balance.\n leftoverAmount = _amount;\n\n // Settle between all splits.\n for (uint256 i; i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[i];\n\n // The amount to send towards the split.\n uint256 _splitAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n if (_splitAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n _token,\n _splitAmount,\n _decimals,\n defaultProjectId,\n 0,\n _split\n );\n\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\n if (_token != JBTokens.ETH)\n IERC20(_token).safeApprove(address(_split.allocator), _splitAmount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _splitAmount : 0;\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n if (_split.preferAddToBalance)\n _addToBalanceOf(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n 0,\n _split.preferClaimed,\n defaultMemo,\n defaultMetadata\n );\n } else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : payable(_defaultBeneficiary),\n _splitAmount\n );\n // Or, transfer the ERC20.\n else {\n IERC20(_token).safeTransfer(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n _splitAmount\n );\n }\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _splitAmount;\n }\n\n emit DistributeToSplit(_split, _splitAmount, _defaultBeneficiary, msg.sender);\n\n unchecked {\n ++i;\n }\n }\n }\n}\n" + "contracts/JBGasTokenERC20SplitsPayer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBSplitsPayer.sol';\nimport './interfaces/IJBSplitsStore.sol';\nimport './libraries/JBConstants.sol';\nimport './JBGasTokenERC20ProjectPayer.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\n\n @dev\n Adheres to -\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBGasTokenERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBGasTokenERC20SplitsPayer is JBGasTokenERC20ProjectPayer, ReentrancyGuard, IJBSplitsPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The ID of project for which the default splits are stored. \n */\n uint256 public override defaultSplitsProjectId;\n\n /**\n @notice\n The domain within which the default splits are stored. \n */\n uint256 public override defaultSplitsDomain;\n\n /**\n @notice\n The group within which the default splits are stored. \n */\n uint256 public override defaultSplitsGroup;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBGasTokenERC20ProjectPayer, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n/**\n @param _splitsStore A contract that stores splits for each project.\n*/\n constructor(\n IJBSplitsStore _splitsStore\n )\n JBGasTokenERC20ProjectPayer(\n _splitsStore.directory()\n )\n {\n splitsStore = _splitsStore;\n }\n /**\n @dev The re-initialize check is done in the inherited paroject payer\n \n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n function initialize(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external override {\n\n super.initialize(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _preferAddToBalance,\n _owner\n );\n\n defaultSplitsProjectId = _defaultSplitsProjectId;\n defaultSplitsDomain = _defaultSplitsDomain;\n defaultSplitsGroup = _defaultSplitsGroup;\n }\n\n\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default split group using the stored default properties.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override nonReentrant {\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // If there is no leftover amount, nothing left to pay.\n if (_leftoverAmount == 0) return;\n\n // If there's a default project ID, try to pay it.\n if (defaultProjectId != 0)\n if (defaultPreferAddToBalance)\n // Pay the project by adding to its balance if prefered.\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n _leftoverAmount,\n 18, // decimals.\n defaultMemo,\n defaultMetadata\n );\n // Otherwise, issue a payment to the project.\n else\n _pay(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n _leftoverAmount,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n 0, // min returned tokens.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else\n Address.sendValue(\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(tx.origin),\n _leftoverAmount\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the splits in the splits store that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n @param _groupedSplits The split groups to set.\n */\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n JBGroupedSplits[] memory _groupedSplits\n ) external virtual override onlyOwner {\n // Set the splits in the store.\n splitsStore.set(_projectId, _domain, _groupedSplits);\n\n // Set the splits reference.\n setDefaultSplitsReference(_projectId, _domain, _group);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the location of the splits that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n */\n function setDefaultSplitsReference(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) public virtual override onlyOwner {\n // Set the default splits project ID if it's changing.\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\n\n // Set the default splits domain if it's changing.\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\n\n // Set the default splits group if it's changing.\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\n\n emit SetDefaultSplitsReference(_projectId, _domain, _group, msg.sender);\n }\n\n /** \n @notice \n Make a payment to the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Pay any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to pay it.\n if (_projectId != 0) {\n _pay(\n _projectId,\n _token,\n _leftoverAmount,\n _decimals,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? payable(_beneficiary) : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit Pay(\n _projectId,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event. \n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Distribute any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to add to its balance.\n if (_projectId != 0)\n // Add to the project's balance.\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\n\n // Otherwise, send a payment to the beneficiary.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit AddToBalance(\n _projectId,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splitsProjectId The ID of the project to which the splits belong.\n @param _splitsDomain The splits domain to which the group belongs.\n @param _splitsGroup The splits group to pay.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payToSplits(\n uint256 _splitsProjectId,\n uint256 _splitsDomain,\n uint256 _splitsGroup,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Pay the splits.\n leftoverAmount = _payTo(\n splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup),\n _token,\n _amount,\n _decimals,\n _defaultBeneficiary\n );\n emit DistributeToSplitGroup(_splitsProjectId, _splitsDomain, _splitsGroup, msg.sender);\n }\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splits The splits.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payTo(\n JBSplit[] memory _splits,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Set the leftover amount to the initial balance.\n leftoverAmount = _amount;\n\n // Settle between all splits.\n for (uint256 i; i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[i];\n\n // The amount to send towards the split.\n uint256 _splitAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n if (_splitAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n _token,\n _splitAmount,\n _decimals,\n defaultProjectId,\n 0,\n _split\n );\n\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN)\n IERC20(_token).safeApprove(address(_split.allocator), _splitAmount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _splitAmount : 0;\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n if (_split.preferAddToBalance)\n _addToBalanceOf(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n 0,\n _split.preferClaimed,\n defaultMemo,\n defaultMetadata\n );\n } else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : payable(_defaultBeneficiary),\n _splitAmount\n );\n // Or, transfer the ERC20.\n else {\n IERC20(_token).safeTransfer(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n _splitAmount\n );\n }\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _splitAmount;\n }\n\n emit DistributeToSplit(_split, _splitAmount, _defaultBeneficiary, msg.sender);\n\n unchecked {\n ++i;\n }\n }\n }\n}\n" }, "contracts/interfaces/IJBSplitsPayer.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './../structs/JBSplit.sol';\nimport './../structs/JBGroupedSplits.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBSplitsPayer is IERC165 {\n event SetDefaultSplitsReference(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n address caller\n );\n event Pay(\n uint256 indexed projectId,\n address beneficiary,\n address token,\n uint256 amount,\n uint256 decimals,\n uint256 leftoverAmount,\n uint256 minReturnedTokens,\n bool preferClaimedTokens,\n string memo,\n bytes metadata,\n address caller\n );\n\n event AddToBalance(\n uint256 indexed projectId,\n address beneficiary,\n address token,\n uint256 amount,\n uint256 decimals,\n uint256 leftoverAmount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DistributeToSplitGroup(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n address caller\n );\n\n event DistributeToSplit(\n JBSplit split,\n uint256 amount,\n address defaultBeneficiary,\n address caller\n );\n\n function defaultSplitsProjectId() external view returns (uint256);\n\n function defaultSplitsDomain() external view returns (uint256);\n\n function defaultSplitsGroup() external view returns (uint256);\n\n function splitsStore() external view returns (IJBSplitsStore);\n\n function initialize(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external;\n\n function setDefaultSplitsReference(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) external;\n\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n JBGroupedSplits[] memory _splitsGroup\n ) external;\n}\n" }, - "contracts/JBETHERC20ProjectPayer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport './interfaces/IJBProjectPayer.sol';\nimport './libraries/JBTokens.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ERC165: Introspection on interface adherance. \n*/\ncontract JBETHERC20ProjectPayer is Ownable, ERC165, IJBProjectPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // -------------------------- custom errors -------------------------- //\n //*********************************************************************//\n error INCORRECT_DECIMAL_AMOUNT();\n error ALREADY_INITIALIZED();\n error NO_MSG_VALUE_ALLOWED();\n error TERMINAL_NOT_FOUND();\n\n //*********************************************************************//\n // ------------------- public immutable properties ------------------- //\n //*********************************************************************//\n\n /**\n @notice \n A contract storing directories of terminals and controllers for each project.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice \n The deployer associated with this implementation. Used to rule out double initialization.\n */\n address public immutable override projectPayerDeployer;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The ID of the project that should be used to forward this contract's received payments.\n */\n uint256 public override defaultProjectId;\n\n /** \n @notice \n The beneficiary that should be used in the payment made when this contract receives payments.\n */\n address payable public override defaultBeneficiary;\n\n /** \n @notice \n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\n */\n bool public override defaultPreferClaimedTokens;\n\n /** \n @notice \n The memo that should be used in the payment made when this contract receives payments.\n */\n string public override defaultMemo;\n\n /** \n @notice \n The metadata that should be used in the payment made when this contract receives payments.\n */\n bytes public override defaultMetadata;\n\n /**\n @notice \n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n bool public override defaultPreferAddToBalance;\n\n //*********************************************************************//\n // ------------------------- public views ---------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructors --------------------------- //\n //*********************************************************************//\n\n /**\n @dev This is the constructor of the implementation. The directory is shared between project payers and is\n immutable. If a new JBDirectory is needed, a new JBProjectPayerDeployer should be deployed.\n @param _directory A contract storing directories of terminals and controllers for each project.\n */\n constructor(IJBDirectory _directory) {\n directory = _directory;\n projectPayerDeployer = msg.sender;\n }\n\n /** \n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n function initialize(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) public {\n if(msg.sender != projectPayerDeployer) revert ALREADY_INITIALIZED();\n\n defaultProjectId = _defaultProjectId;\n defaultBeneficiary = _defaultBeneficiary;\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\n defaultMemo = _defaultMemo;\n defaultMetadata = _defaultMetadata;\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default project ID using the stored default properties.\n\n @dev\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override {\n if (defaultPreferAddToBalance)\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.ETH,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n defaultProjectId,\n JBTokens.ETH,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultBeneficiary == address(0) ? tx.origin : defaultBeneficiary,\n 0, // Can't determine expectation of returned tokens ahead of time.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\n\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _beneficiary The address that'll receive the project's tokens. \n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _memo The memo that'll be used. \n @param _metadata The metadata that'll be sent. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external virtual override onlyOwner {\n // Set the default project ID if it has changed.\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\n\n // Set the default beneficiary if it has changed.\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\n\n // Set the default claimed token preference if it has changed.\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\n defaultPreferClaimedTokens = _preferClaimedTokens;\n\n // Set the default memo if it has changed.\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\n defaultMemo = _memo;\n\n // Set the default metadata if it has changed.\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\n defaultMetadata = _metadata;\n\n // Set the add to balance preference if it has changed.\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n\n emit SetDefaultValues(\n _projectId,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata,\n _defaultPreferAddToBalance,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _pay(\n _projectId,\n _token,\n _amount,\n _decimals,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. \n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source and delegate, if provided.\n */\n function _pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.ETH) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\n\n // Send funds to the terminal.\n // If the token is ETH, send it in msg.value.\n _terminal.pay{value: _payableValue}(\n _projectId,\n _amount, // ignored if the token is JBTokens.ETH.\n _token,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.ETH) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\n\n // Add to balance so tokens don't get issued.\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\n }\n}\n" + "contracts/JBGasTokenERC20ProjectPayer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport './interfaces/IJBProjectPayer.sol';\nimport './libraries/JBTokens.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ERC165: Introspection on interface adherance. \n*/\ncontract JBGasTokenERC20ProjectPayer is Ownable, ERC165, IJBProjectPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // -------------------------- custom errors -------------------------- //\n //*********************************************************************//\n error INCORRECT_DECIMAL_AMOUNT();\n error ALREADY_INITIALIZED();\n error NO_MSG_VALUE_ALLOWED();\n error TERMINAL_NOT_FOUND();\n\n //*********************************************************************//\n // ------------------- public immutable properties ------------------- //\n //*********************************************************************//\n\n /**\n @notice \n A contract storing directories of terminals and controllers for each project.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice \n The deployer associated with this implementation. Used to rule out double initialization.\n */\n address public immutable override projectPayerDeployer;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The ID of the project that should be used to forward this contract's received payments.\n */\n uint256 public override defaultProjectId;\n\n /** \n @notice \n The beneficiary that should be used in the payment made when this contract receives payments.\n */\n address payable public override defaultBeneficiary;\n\n /** \n @notice \n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\n */\n bool public override defaultPreferClaimedTokens;\n\n /** \n @notice \n The memo that should be used in the payment made when this contract receives payments.\n */\n string public override defaultMemo;\n\n /** \n @notice \n The metadata that should be used in the payment made when this contract receives payments.\n */\n bytes public override defaultMetadata;\n\n /**\n @notice \n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n bool public override defaultPreferAddToBalance;\n\n //*********************************************************************//\n // ------------------------- public views ---------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructors --------------------------- //\n //*********************************************************************//\n\n /**\n @dev This is the constructor of the implementation. The directory is shared between project payers and is\n immutable. If a new JBDirectory is needed, a new JBProjectPayerDeployer should be deployed.\n @param _directory A contract storing directories of terminals and controllers for each project.\n */\n constructor(IJBDirectory _directory) {\n directory = _directory;\n projectPayerDeployer = msg.sender;\n }\n\n /** \n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n function initialize(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) public {\n if(msg.sender != projectPayerDeployer) revert ALREADY_INITIALIZED();\n\n defaultProjectId = _defaultProjectId;\n defaultBeneficiary = _defaultBeneficiary;\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\n defaultMemo = _defaultMemo;\n defaultMetadata = _defaultMetadata;\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default project ID using the stored default properties.\n\n @dev\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override {\n if (defaultPreferAddToBalance)\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultBeneficiary == address(0) ? tx.origin : defaultBeneficiary,\n 0, // Can't determine expectation of returned tokens ahead of time.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\n\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _beneficiary The address that'll receive the project's tokens. \n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _memo The memo that'll be used. \n @param _metadata The metadata that'll be sent. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external virtual override onlyOwner {\n // Set the default project ID if it has changed.\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\n\n // Set the default beneficiary if it has changed.\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\n\n // Set the default claimed token preference if it has changed.\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\n defaultPreferClaimedTokens = _preferClaimedTokens;\n\n // Set the default memo if it has changed.\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\n defaultMemo = _memo;\n\n // Set the default metadata if it has changed.\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\n defaultMetadata = _metadata;\n\n // Set the add to balance preference if it has changed.\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n\n emit SetDefaultValues(\n _projectId,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata,\n _defaultPreferAddToBalance,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _pay(\n _projectId,\n _token,\n _amount,\n _decimals,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. \n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source and delegate, if provided.\n */\n function _pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send funds to the terminal.\n // If the token is ETH, send it in msg.value.\n _terminal.pay{value: _payableValue}(\n _projectId,\n _amount, // ignored if the token is JBTokens.GAS_TOKEN.\n _token,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Add to balance so tokens don't get issued.\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\n }\n}\n" }, "contracts/interfaces/IJBProjectPayer.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './IJBDirectory.sol';\n\ninterface IJBProjectPayer is IERC165 {\n event SetDefaultValues(\n uint256 indexed projectId,\n address indexed beneficiary,\n bool preferClaimedTokens,\n string memo,\n bytes metadata,\n bool preferAddToBalance,\n address caller\n );\n\n function directory() external view returns (IJBDirectory);\n\n function projectPayerDeployer() external view returns (address);\n\n function defaultProjectId() external view returns (uint256);\n\n function defaultBeneficiary() external view returns (address payable);\n\n function defaultPreferClaimedTokens() external view returns (bool);\n\n function defaultMemo() external view returns (string memory);\n\n function defaultMetadata() external view returns (bytes memory);\n\n function defaultPreferAddToBalance() external view returns (bool);\n\n function initialize(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external;\n\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external;\n\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) external payable;\n\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) external payable;\n\n receive() external payable;\n}\n" }, - "contracts/JBETHERC20SplitsPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport { Clones } from '@openzeppelin/contracts/proxy/Clones.sol';\n\nimport './interfaces/IJBETHERC20SplitsPayerDeployer.sol';\nimport './structs/JBSplit.sol';\nimport './structs/JBGroupedSplits.sol';\nimport './JBETHERC20SplitsPayer.sol';\n\n/** \n @notice \n Deploys splits payer contracts.\n\n @dev\n Adheres to -\n IJBETHERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBETHERC20SplitsPayerDeployer is IJBETHERC20SplitsPayerDeployer {\n\n address immutable implementation;\n\n IJBSplitsStore immutable splitsStore;\n\n constructor(IJBSplitsStore _splitsStore) {\n implementation = address(new JBETHERC20SplitsPayer(_splitsStore));\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @dev\n This contract must have Operator permissions over the SET_SPLITS permission of the specified `_defaultSplitsProjectId`.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplits The splits to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBSplitsPayer splitsPayer) {\n // Use this contract's address as the domain.\n uint256 _domain = uint256(uint160(address(this)));\n\n // Create the random hash using data unique to this instance that'll be used as the storage domain.\n uint256 _group = uint256(keccak256(abi.encodePacked(msg.sender, block.number)));\n\n // Set the splits in the store.\n JBGroupedSplits[] memory _groupedSplits;\n _groupedSplits = new JBGroupedSplits[](1);\n _groupedSplits[0] = JBGroupedSplits(_group, _defaultSplits);\n _splitsStore.set(_defaultSplitsProjectId, _domain, _groupedSplits);\n\n return\n deploySplitsPayer(\n _defaultSplitsProjectId,\n _domain,\n _group,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n }\n\n //*********************************************************************//\n // ---------------------- public transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) public override returns (IJBSplitsPayer splitsPayer) {\n\n // Deploy the splits payer.\n splitsPayer = IJBSplitsPayer(payable(Clones.clone(implementation)));\n\n splitsPayer.initialize(\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeploySplitsPayer(\n splitsPayer,\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner,\n msg.sender\n );\n }\n}\n" + "contracts/JBGasTokenERC20SplitsPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport { Clones } from '@openzeppelin/contracts/proxy/Clones.sol';\n\nimport './interfaces/IJBGasTokenERC20SplitsPayerDeployer.sol';\nimport './structs/JBSplit.sol';\nimport './structs/JBGroupedSplits.sol';\nimport './JBGasTokenERC20SplitsPayer.sol';\n\n/** \n @notice \n Deploys splits payer contracts.\n\n @dev\n Adheres to -\n IJBGasTokenERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBGasTokenERC20SplitsPayerDeployer is IJBGasTokenERC20SplitsPayerDeployer {\n\n address immutable implementation;\n\n IJBSplitsStore immutable splitsStore;\n\n constructor(IJBSplitsStore _splitsStore) {\n implementation = address(new JBGasTokenERC20SplitsPayer(_splitsStore));\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @dev\n This contract must have Operator permissions over the SET_SPLITS permission of the specified `_defaultSplitsProjectId`.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplits The splits to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBSplitsPayer splitsPayer) {\n // Use this contract's address as the domain.\n uint256 _domain = uint256(uint160(address(this)));\n\n // Create the random hash using data unique to this instance that'll be used as the storage domain.\n uint256 _group = uint256(keccak256(abi.encodePacked(msg.sender, block.number)));\n\n // Set the splits in the store.\n JBGroupedSplits[] memory _groupedSplits;\n _groupedSplits = new JBGroupedSplits[](1);\n _groupedSplits[0] = JBGroupedSplits(_group, _defaultSplits);\n _splitsStore.set(_defaultSplitsProjectId, _domain, _groupedSplits);\n\n return\n deploySplitsPayer(\n _defaultSplitsProjectId,\n _domain,\n _group,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n }\n\n //*********************************************************************//\n // ---------------------- public transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) public override returns (IJBSplitsPayer splitsPayer) {\n\n // Deploy the splits payer.\n splitsPayer = IJBSplitsPayer(payable(Clones.clone(implementation)));\n\n splitsPayer.initialize(\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeploySplitsPayer(\n splitsPayer,\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner,\n msg.sender\n );\n }\n}\n" }, "@openzeppelin/contracts/proxy/Clones.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/Clones.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for\n * deploying minimal proxy contracts, also known as \"clones\".\n *\n * > To simply and cheaply clone contract functionality in an immutable way, this standard specifies\n * > a minimal bytecode implementation that delegates all calls to a known, fixed address.\n *\n * The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2`\n * (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the\n * deterministic method.\n *\n * _Available since v3.4._\n */\nlibrary Clones {\n /**\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.\n *\n * This function uses the create opcode, which should never revert.\n */\n function clone(address implementation) internal returns (address instance) {\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\n mstore(add(ptr, 0x14), shl(0x60, implementation))\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\n instance := create(0, ptr, 0x37)\n }\n require(instance != address(0), \"ERC1167: create failed\");\n }\n\n /**\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.\n *\n * This function uses the create2 opcode and a `salt` to deterministically deploy\n * the clone. Using the same `implementation` and `salt` multiple time will revert, since\n * the clones cannot be deployed twice at the same address.\n */\n function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) {\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\n mstore(add(ptr, 0x14), shl(0x60, implementation))\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\n instance := create2(0, ptr, 0x37, salt)\n }\n require(instance != address(0), \"ERC1167: create2 failed\");\n }\n\n /**\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\n */\n function predictDeterministicAddress(\n address implementation,\n bytes32 salt,\n address deployer\n ) internal pure returns (address predicted) {\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\n mstore(add(ptr, 0x14), shl(0x60, implementation))\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf3ff00000000000000000000000000000000)\n mstore(add(ptr, 0x38), shl(0x60, deployer))\n mstore(add(ptr, 0x4c), salt)\n mstore(add(ptr, 0x6c), keccak256(ptr, 0x37))\n predicted := keccak256(add(ptr, 0x37), 0x55)\n }\n }\n\n /**\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\n */\n function predictDeterministicAddress(address implementation, bytes32 salt)\n internal\n view\n returns (address predicted)\n {\n return predictDeterministicAddress(implementation, salt, address(this));\n }\n}\n" }, - "contracts/interfaces/IJBETHERC20SplitsPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBSplitsPayer.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBETHERC20SplitsPayerDeployer {\n event DeploySplitsPayer(\n IJBSplitsPayer indexed splitsPayer,\n uint256 defaultSplitsProjectId,\n uint256 defaultSplitsDomain,\n uint256 defaultSplitsGroup,\n IJBSplitsStore splitsStore,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n address owner,\n address caller\n );\n\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string calldata _defaultMemo,\n bytes calldata _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n}\n" + "contracts/interfaces/IJBGasTokenERC20SplitsPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBSplitsPayer.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBGasTokenERC20SplitsPayerDeployer {\n event DeploySplitsPayer(\n IJBSplitsPayer indexed splitsPayer,\n uint256 defaultSplitsProjectId,\n uint256 defaultSplitsDomain,\n uint256 defaultSplitsGroup,\n IJBSplitsStore splitsStore,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n address owner,\n address caller\n );\n\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string calldata _defaultMemo,\n bytes calldata _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n}\n" }, - "contracts/JBETHERC20ProjectPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport { Clones } from '@openzeppelin/contracts/proxy/Clones.sol';\n\nimport './interfaces/IJBETHERC20ProjectPayerDeployer.sol';\nimport './JBETHERC20ProjectPayer.sol';\n\n/** \n @notice \n Deploys project payer contracts.\n\n @dev\n Adheres to -\n IJBETHERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBETHERC20ProjectPayerDeployer is IJBETHERC20ProjectPayerDeployer {\n\n address immutable implementation;\n\n IJBDirectory immutable directory;\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n */\n constructor(IJBDirectory _directory) {\n implementation = address(new JBETHERC20ProjectPayer(_directory));\n directory = _directory;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new project payer contract.\n\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the project payer contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the project payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the project payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the project payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the project payer.\n\n @return projectPayer The project payer contract.\n */\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBProjectPayer projectPayer) {\n // Deploy the project payer.\n projectPayer = IJBProjectPayer(payable(Clones.clone(implementation)));\n\n // Initialize the project payer.\n projectPayer.initialize(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeployProjectPayer(\n projectPayer,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n directory,\n _owner,\n msg.sender\n );\n }\n}\n" + "contracts/JBGasTokenERC20ProjectPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport { Clones } from '@openzeppelin/contracts/proxy/Clones.sol';\n\nimport './interfaces/IJBGasTokenERC20ProjectPayerDeployer.sol';\nimport './JBGasTokenERC20ProjectPayer.sol';\n\n/** \n @notice \n Deploys project payer contracts.\n\n @dev\n Adheres to -\n IJBGasTokenERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBGasTokenERC20ProjectPayerDeployer is IJBGasTokenERC20ProjectPayerDeployer {\n\n address immutable implementation;\n\n IJBDirectory immutable directory;\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n */\n constructor(IJBDirectory _directory) {\n implementation = address(new JBGasTokenERC20ProjectPayer(_directory));\n directory = _directory;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new project payer contract.\n\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the project payer contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the project payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the project payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the project payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the project payer.\n\n @return projectPayer The project payer contract.\n */\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBProjectPayer projectPayer) {\n // Deploy the project payer.\n projectPayer = IJBProjectPayer(payable(Clones.clone(implementation)));\n\n // Initialize the project payer.\n projectPayer.initialize(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeployProjectPayer(\n projectPayer,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n directory,\n _owner,\n msg.sender\n );\n }\n}\n" }, - "contracts/interfaces/IJBETHERC20ProjectPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBDirectory.sol';\nimport './IJBProjectPayer.sol';\n\ninterface IJBETHERC20ProjectPayerDeployer {\n event DeployProjectPayer(\n IJBProjectPayer indexed projectPayer,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n IJBDirectory directory,\n address owner,\n address caller\n );\n\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBProjectPayer projectPayer);\n}\n" + "contracts/interfaces/IJBGasTokenERC20ProjectPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBDirectory.sol';\nimport './IJBProjectPayer.sol';\n\ninterface IJBGasTokenERC20ProjectPayerDeployer {\n event DeployProjectPayer(\n IJBProjectPayer indexed projectPayer,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n IJBDirectory directory,\n address owner,\n address caller\n );\n\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBProjectPayer projectPayer);\n}\n" }, "contracts/JBDirectory.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport './abstract/JBOperatable.sol';\nimport './interfaces/IJBDirectory.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './libraries/JBOperations.sol';\n\n/**\n @notice\n Keeps a reference of which terminal contracts each project is currently accepting funds through, and which controller contract is managing each project's tokens and funding cycles.\n\n @dev\n Adheres to -\n IJBDirectory: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\ncontract JBDirectory is JBOperatable, Ownable, IJBDirectory {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error DUPLICATE_TERMINALS();\n error INVALID_PROJECT_ID_IN_DIRECTORY();\n error SET_CONTROLLER_NOT_ALLOWED();\n error SET_TERMINALS_NOT_ALLOWED();\n error TOKEN_NOT_ACCEPTED();\n\n //*********************************************************************//\n // --------------------- private stored properties ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n For each project ID, the terminals that are currently managing its funds.\n\n _projectId The ID of the project to get terminals of.\n */\n mapping(uint256 => IJBPaymentTerminal[]) private _terminalsOf;\n\n /**\n @notice\n The project's primary terminal for a token.\n\n _projectId The ID of the project to get the primary terminal of.\n _token The token to get the project's primary terminal of.\n */\n mapping(uint256 => mapping(address => IJBPaymentTerminal)) private _primaryTerminalOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n For each project ID, the controller that manages how terminals interact with tokens and funding cycles.\n\n _projectId The ID of the project to get the controller of.\n */\n mapping(uint256 => address) public override controllerOf;\n\n /**\n @notice\n Addresses that can set a project's first controller on their behalf. These addresses/contracts have been vetted and verified by this contract's owner.\n\n _address The address that is either allowed or not.\n */\n mapping(address => bool) public override isAllowedToSetFirstController;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n For each project ID, the terminals that are currently managing its funds.\n\n @param _projectId The ID of the project to get terminals of.\n\n @return An array of terminal addresses.\n */\n function terminalsOf(uint256 _projectId)\n external\n view\n override\n returns (IJBPaymentTerminal[] memory)\n {\n return _terminalsOf[_projectId];\n }\n\n /**\n @notice\n The primary terminal that is managing funds for a project for a specified token.\n\n @dev\n The zero address is returned if a terminal isn't found for the specified token.\n\n @param _projectId The ID of the project to get a terminal for.\n @param _token The token the terminal accepts.\n\n @return The primary terminal for the project for the specified token.\n */\n function primaryTerminalOf(uint256 _projectId, address _token)\n external\n view\n override\n returns (IJBPaymentTerminal)\n {\n // Keep a reference to the primary terminal for the provided project ID and token.\n IJBPaymentTerminal _primaryTerminal = _primaryTerminalOf[_projectId][_token];\n\n // If a primary terminal for the token was specifically set and it's one of the project's terminals, return it.\n if (\n _primaryTerminal != IJBPaymentTerminal(address(0)) &&\n isTerminalOf(_projectId, _primaryTerminal)\n ) return _primaryTerminal;\n\n // Keep a reference to the number of terminals the project has.\n uint256 _numberOfTerminals = _terminalsOf[_projectId].length;\n\n // Return the first terminal which accepts the specified token.\n for (uint256 _i; _i < _numberOfTerminals; ) {\n // Keep a reference to the terminal being iterated on.\n IJBPaymentTerminal _terminal = _terminalsOf[_projectId][_i];\n\n // If the terminal accepts the specified token, return it.\n if (_terminal.acceptsToken(_token, _projectId)) return _terminal;\n\n unchecked {\n ++_i;\n }\n }\n\n // Not found.\n return IJBPaymentTerminal(address(0));\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Whether or not a specified terminal is a terminal of the specified project.\n\n @param _projectId The ID of the project to check within.\n @param _terminal The address of the terminal to check for.\n\n @return A flag indicating whether or not the specified terminal is a terminal of the specified project.\n */\n function isTerminalOf(uint256 _projectId, IJBPaymentTerminal _terminal)\n public\n view\n override\n returns (bool)\n {\n // Keep a reference to the number of terminals the project has.\n uint256 _numberOfTerminals = _terminalsOf[_projectId].length;\n\n // Loop through and return true if the terminal is contained.\n for (uint256 _i; _i < _numberOfTerminals; ) {\n // If the terminal being iterated on matches the provided terminal, return true.\n if (_terminalsOf[_projectId][_i] == _terminal) return true;\n\n unchecked {\n ++_i;\n }\n }\n\n // Otherwise, return false.\n return false;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _owner The address that will own the contract.\n */\n constructor(\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBFundingCycleStore _fundingCycleStore,\n address _owner\n ) JBOperatable(_operatorStore) {\n projects = _projects;\n fundingCycleStore = _fundingCycleStore;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Update the controller that manages how terminals interact with the ecosystem.\n\n @dev\n A controller can be set if:\n - the message sender is the project owner or an operator having the correct authorization.\n - the message sender is the project's current controller.\n - or, an allowedlisted address is setting a controller for a project that doesn't already have a controller.\n\n @param _projectId The ID of the project to set a new controller for.\n @param _controller The new controller to set.\n */\n function setControllerOf(uint256 _projectId, address _controller)\n external\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.SET_CONTROLLER,\n (msg.sender == address(controllerOf[_projectId]) ||\n (isAllowedToSetFirstController[msg.sender] && controllerOf[_projectId] == address(0)))\n )\n {\n // The project must exist.\n if (projects.count() < _projectId) revert INVALID_PROJECT_ID_IN_DIRECTORY();\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Setting controller is allowed if called from the current controller, or if the project doesn't have a current controller, or if the project's funding cycle allows setting the controller. Revert otherwise.\n if (\n msg.sender != address(controllerOf[_projectId]) &&\n controllerOf[_projectId] != address(0) &&\n !_fundingCycle.global().allowSetController\n ) revert SET_CONTROLLER_NOT_ALLOWED();\n\n // Set the new controller.\n controllerOf[_projectId] = _controller;\n\n emit SetController(_projectId, _controller, msg.sender);\n }\n\n /** \n @notice \n Set a project's terminals.\n\n @dev\n Only a project owner, an operator, or its controller can set its terminals.\n\n @param _projectId The ID of the project having terminals set.\n @param _terminals The terminal to set.\n */\n function setTerminalsOf(uint256 _projectId, IJBPaymentTerminal[] calldata _terminals)\n external\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.SET_TERMINALS,\n msg.sender == address(controllerOf[_projectId])\n )\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Setting terminals must be allowed if not called from the current controller.\n if (\n msg.sender != address(controllerOf[_projectId]) && !_fundingCycle.global().allowSetTerminals\n ) revert SET_TERMINALS_NOT_ALLOWED();\n\n // Set the stored terminals for the project.\n _terminalsOf[_projectId] = _terminals;\n\n // Make sure duplicates were not added.\n if (_terminals.length > 1) {\n for (uint256 _i; _i < _terminals.length; ) {\n for (uint256 _j = _i + 1; _j < _terminals.length; ) {\n if (_terminals[_i] == _terminals[_j]) revert DUPLICATE_TERMINALS();\n\n unchecked {\n ++_j;\n }\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n emit SetTerminals(_projectId, _terminals, msg.sender);\n }\n\n /**\n @notice\n Project's can set which terminal should be their primary for a particular token.\n This is useful in case a project has several terminals connected for a particular token.\n\n @dev\n The terminal will be set as the primary terminal where ecosystem contracts should route tokens.\n\n @dev\n If setting a newly added terminal and the funding cycle doesn't allow new terminals, the caller must be the current controller.\n\n @param _projectId The ID of the project for which a primary token is being set.\n @param _token The token to set the primary terminal of.\n @param _terminal The terminal to make primary.\n */\n function setPrimaryTerminalOf(\n uint256 _projectId,\n address _token,\n IJBPaymentTerminal _terminal\n )\n external\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.SET_PRIMARY_TERMINAL)\n {\n // Can't set the primary terminal for a token if it doesn't accept the token.\n if (!_terminal.acceptsToken(_token, _projectId)) revert TOKEN_NOT_ACCEPTED();\n\n // Add the terminal to the project if it hasn't been already.\n _addTerminalIfNeeded(_projectId, _terminal);\n\n // Store the terminal as the primary for the particular token.\n _primaryTerminalOf[_projectId][_token] = _terminal;\n\n emit SetPrimaryTerminal(_projectId, _token, _terminal, msg.sender);\n }\n\n /** \n @notice\t\n Set a contract to the list of trusted addresses that can set a first controller for any project.\t\n\n @dev\n The owner can add addresses which are allowed to change projects' first controllers. \n These addresses are known and vetted controllers as well as contracts designed to launch new projects. \n A project can set its own controller without it being on the allow list.\n\n @dev\n If you would like an address/contract allowlisted, please reach out to the contract owner.\n\n @param _address The address to allow or revoke allowance from.\n @param _flag Whether allowance is being added or revoked.\n */\n function setIsAllowedToSetFirstController(address _address, bool _flag)\n external\n override\n onlyOwner\n {\n // Set the flag in the allowlist.\n isAllowedToSetFirstController[_address] = _flag;\n\n emit SetIsAllowedToSetFirstController(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Add a terminal to a project's list of terminals if it hasn't been already.\n\n @param _projectId The ID of the project having a terminal added.\n @param _terminal The terminal to add.\n */\n function _addTerminalIfNeeded(uint256 _projectId, IJBPaymentTerminal _terminal) private {\n // Check that the terminal has not already been added.\n if (isTerminalOf(_projectId, _terminal)) return;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Setting terminals must be allowed if not called from the current controller.\n if (\n msg.sender != address(controllerOf[_projectId]) && !_fundingCycle.global().allowSetTerminals\n ) revert SET_TERMINALS_NOT_ALLOWED();\n\n // Add the new terminal.\n _terminalsOf[_projectId].push(_terminal);\n\n emit AddTerminal(_projectId, _terminal, msg.sender);\n }\n}\n" @@ -365,10 +365,10 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './interfaces/IJBOperatorStore.sol';\n\n/** \n @notice\n Stores operator permissions for all addresses. Addresses can give permissions to any other address to take specific indexed actions on their behalf.\n\n @dev\n Adheres to -\n IJBOperatorStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBOperatorStore is IJBOperatorStore {\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error PERMISSION_INDEX_OUT_OF_BOUNDS();\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice\n The permissions that an operator has been given to operate on a specific domain.\n \n @dev\n An account can give an operator permissions that only pertain to a specific domain namespace.\n There is no domain with a value of 0 – accounts can use the 0 domain to give an operator\n permissions to all domains on their behalf.\n\n @dev\n Permissions are stored in a packed `uint256`. Each 256 bits represents the on/off state of a permission. Applications can specify the significance of each index.\n\n _operator The address of the operator.\n _account The address of the account being operated.\n _domain The domain within which the permissions apply. Applications can use the domain namespace as they wish.\n */\n mapping(address => mapping(address => mapping(uint256 => uint256))) public override permissionsOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Whether or not an operator has the permission to take a certain action pertaining to the specified domain.\n\n @param _operator The operator to check.\n @param _account The account that has given out permissions to the operator.\n @param _domain The domain that the operator has been given permissions to operate.\n @param _permissionIndex The permission index to check for.\n\n @return A flag indicating whether the operator has the specified permission.\n */\n function hasPermission(\n address _operator,\n address _account,\n uint256 _domain,\n uint256 _permissionIndex\n ) external view override returns (bool) {\n if (_permissionIndex > 255) revert PERMISSION_INDEX_OUT_OF_BOUNDS();\n\n return (((permissionsOf[_operator][_account][_domain] >> _permissionIndex) & 1) == 1);\n }\n\n /** \n @notice \n Whether or not an operator has the permission to take certain actions pertaining to the specified domain.\n\n @param _operator The operator to check.\n @param _account The account that has given out permissions to the operator.\n @param _domain The domain that the operator has been given permissions to operate.\n @param _permissionIndexes An array of permission indexes to check for.\n\n @return A flag indicating whether the operator has all specified permissions.\n */\n function hasPermissions(\n address _operator,\n address _account,\n uint256 _domain,\n uint256[] calldata _permissionIndexes\n ) external view override returns (bool) {\n for (uint256 _i; _i < _permissionIndexes.length; ) {\n uint256 _permissionIndex = _permissionIndexes[_i];\n\n if (_permissionIndex > 255) revert PERMISSION_INDEX_OUT_OF_BOUNDS();\n\n if (((permissionsOf[_operator][_account][_domain] >> _permissionIndex) & 1) == 0)\n return false;\n\n unchecked {\n ++_i;\n }\n }\n return true;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Sets permissions for an operators.\n\n @dev\n Only an address can set its own operators.\n\n @param _operatorData The data that specifies the params for the operator being set.\n */\n function setOperator(JBOperatorData calldata _operatorData) external override {\n // Pack the indexes into a uint256.\n uint256 _packed = _packedPermissions(_operatorData.permissionIndexes);\n\n // Store the new value.\n permissionsOf[_operatorData.operator][msg.sender][_operatorData.domain] = _packed;\n\n emit SetOperator(\n _operatorData.operator,\n msg.sender,\n _operatorData.domain,\n _operatorData.permissionIndexes,\n _packed\n );\n }\n\n /**\n @notice\n Sets permissions for many operators.\n\n @dev\n Only an address can set its own operators.\n\n @param _operatorData The data that specify the params for each operator being set.\n */\n function setOperators(JBOperatorData[] calldata _operatorData) external override {\n for (uint256 _i; _i < _operatorData.length; ) {\n // Pack the indexes into a uint256.\n uint256 _packed = _packedPermissions(_operatorData[_i].permissionIndexes);\n\n // Store the new value.\n permissionsOf[_operatorData[_i].operator][msg.sender][_operatorData[_i].domain] = _packed;\n\n emit SetOperator(\n _operatorData[_i].operator,\n msg.sender,\n _operatorData[_i].domain,\n _operatorData[_i].permissionIndexes,\n _packed\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Converts an array of permission indexes to a packed `uint256`.\n\n @param _indexes The indexes of the permissions to pack.\n\n @return packed The packed value.\n */\n function _packedPermissions(uint256[] calldata _indexes) private pure returns (uint256 packed) {\n for (uint256 _i; _i < _indexes.length; ) {\n uint256 _index = _indexes[_i];\n\n if (_index > 255) revert PERMISSION_INDEX_OUT_OF_BOUNDS();\n\n // Turn the bit at the index on.\n packed |= 1 << _index;\n\n unchecked {\n ++_i;\n }\n }\n }\n}\n" }, "contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBPayDelegateAllocation.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal is\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n IJBPayoutRedemptionPaymentTerminal\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n @dev\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.ETH)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.ETH, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance.\n */\n function _balance() internal view virtual returns (uint256);\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.ETH) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual {\n _from; // Prevents unused var compiler and natspec complaints.\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\n {\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\n\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _forwardedAmount,\n _beneficiary,\n _memo,\n _metadata\n );\n\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\n\n emit DelegateDidRedeem(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n }\n\n // Take the fee.\n _fee = _feeEligibleDistributionAmount != 0\n ? _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n )\n : 0;\n\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\n if (_leftoverDistributionAmount != 0) {\n // Subtract the fee from the net leftover amount.\n netLeftoverDistributionAmount =\n _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n\n // Transfer the amount to the project owner.\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n // The total percentage available to split\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = _split.percent == leftoverPercentage\n ? leftoverAmount\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\n\n // Decrement the leftover percentage.\n leftoverPercentage -= _split.percent;\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount;\n\n if (_payoutAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\n isFeelessAddress[address(_split.allocator)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n _netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n // If this terminal's token is ETH, send it in msg.value.\n _split.allocator.allocate{value: token == JBTokens.ETH ? _netPayoutAmount : 0}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // Save gas if this contract is being used as the terminal.\n if (_terminal == this) {\n // This distribution does not incur a fee.\n _netPayoutAmount = _payoutAmount;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\n else\n _pay(\n _netPayoutAmount,\n address(this),\n _split.projectId,\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n } else {\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_terminal)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _netPayoutAmount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _terminal.addToBalanceOf{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n '',\n _projectMetadata\n );\n else\n _terminal.pay{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n }\n } else {\n // Keep a reference to the beneficiary.\n address payable _beneficiary = _split.beneficiary != address(0)\n ? _split.beneficiary\n : payable(msg.sender);\n\n // If there's a full discount, this distribution is not eligible for a fee.\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(address(this), _beneficiary, _netPayoutAmount);\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n */\n function _processFee(uint256 _amount, address _beneficiary) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\n\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\n if (_terminal == this)\n _pay(\n _amount,\n address(this),\n _FEE_BENEFICIARY_PROJECT_ID,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the local pay call.\n else {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _amount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _amount : 0;\n\n // Send the payment.\n _terminal.pay{value: _payableValue}(\n _FEE_BENEFICIARY_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the external pay call of the correct terminal.\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\n {\n JBPayDelegateAllocation[] memory _delegateAllocations;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n _forwardedAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n // Get a reference to the number of delegates to allocate to.\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\n\n emit DelegateDidPay(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n unchecked {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\n IJBPaymentTerminal(address(0))\n ) return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge != IJBFeeGauge(address(0)))\n // If the guage reverts, keep the discount at 0.\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n // If the fee discount is greater than the max, we ignore the return value\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\n } catch {\n return 0;\n }\n\n return 0;\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBPayDelegateAllocation.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal is\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n IJBPayoutRedemptionPaymentTerminal\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n @dev\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.GAS_CURRENCY)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.GAS_CURRENCY, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance.\n */\n function _balance() internal view virtual returns (uint256);\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.GAS_TOKEN) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual {\n _from; // Prevents unused var compiler and natspec complaints.\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\n {\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\n\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _forwardedAmount,\n _beneficiary,\n _memo,\n _metadata\n );\n\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\n\n emit DelegateDidRedeem(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n }\n\n // Take the fee.\n _fee = _feeEligibleDistributionAmount != 0\n ? _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n )\n : 0;\n\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\n if (_leftoverDistributionAmount != 0) {\n // Subtract the fee from the net leftover amount.\n netLeftoverDistributionAmount =\n _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n\n // Transfer the amount to the project owner.\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n // The total percentage available to split\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = _split.percent == leftoverPercentage\n ? leftoverAmount\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\n\n // Decrement the leftover percentage.\n leftoverPercentage -= _split.percent;\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount;\n\n if (_payoutAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\n isFeelessAddress[address(_split.allocator)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n _netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n // If this terminal's token is ETH, send it in msg.value.\n _split.allocator.allocate{value: token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // Save gas if this contract is being used as the terminal.\n if (_terminal == this) {\n // This distribution does not incur a fee.\n _netPayoutAmount = _payoutAmount;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\n else\n _pay(\n _netPayoutAmount,\n address(this),\n _split.projectId,\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n } else {\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_terminal)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _terminal.addToBalanceOf{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n '',\n _projectMetadata\n );\n else\n _terminal.pay{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n }\n } else {\n // Keep a reference to the beneficiary.\n address payable _beneficiary = _split.beneficiary != address(0)\n ? _split.beneficiary\n : payable(msg.sender);\n\n // If there's a full discount, this distribution is not eligible for a fee.\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(address(this), _beneficiary, _netPayoutAmount);\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n */\n function _processFee(uint256 _amount, address _beneficiary) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\n\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\n if (_terminal == this)\n _pay(\n _amount,\n address(this),\n _FEE_BENEFICIARY_PROJECT_ID,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the local pay call.\n else {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _amount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send the payment.\n _terminal.pay{value: _payableValue}(\n _FEE_BENEFICIARY_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the external pay call of the correct terminal.\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\n {\n JBPayDelegateAllocation[] memory _delegateAllocations;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n _forwardedAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n // Get a reference to the number of delegates to allocate to.\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\n\n emit DelegateDidPay(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n unchecked {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\n IJBPaymentTerminal(address(0))\n ) return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge != IJBFeeGauge(address(0)))\n // If the guage reverts, keep the discount at 0.\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n // If the fee discount is greater than the max, we ignore the return value\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\n } catch {\n return 0;\n }\n\n return 0;\n }\n}\n" }, "contracts/JBETHPaymentTerminal.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\nimport './libraries/JBSplitsGroups.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return address(this).balance;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n JBTokens.ETH,\n 18, // 18 decimals.\n JBCurrencies.ETH,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\nimport './libraries/JBSplitsGroups.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return address(this).balance;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n JBTokens.GAS_TOKEN,\n 18, // 18 decimals.\n JBCurrencies.GAS_CURRENCY,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n}\n" }, "contracts/JBERC20PaymentTerminal.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\n\n/** \n @notice \n Manages the inflows and outflows of an ERC-20 token.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\ncontract JBERC20PaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return IERC20(token).balanceOf(address(this));\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n IERC20Metadata _token,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n address(_token),\n _token.decimals(),\n _currency,\n _baseWeightCurrency,\n _payoutSplitsGroup,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from == address(this)\n ? IERC20(token).safeTransfer(_to, _amount)\n : IERC20(token).safeTransferFrom(_from, _to, _amount);\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal override {\n IERC20(token).safeApprove(_to, _amount);\n }\n}\n" diff --git a/deployments/goerli/solcInputs/ed590828cf2d3bd8e9fe992c4f52dc83.json b/deployments/goerli/solcInputs/ed590828cf2d3bd8e9fe992c4f52dc83.json index 4f93930ae..ca1a732f6 100644 --- a/deployments/goerli/solcInputs/ed590828cf2d3bd8e9fe992c4f52dc83.json +++ b/deployments/goerli/solcInputs/ed590828cf2d3bd8e9fe992c4f52dc83.json @@ -101,10 +101,10 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './../interfaces/IJBOperatable.sol';\n\n/** \n @notice\n Modifiers to allow access to functions based on the message sender's operator status.\n\n @dev\n Adheres to -\n IJBOperatable: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\nabstract contract JBOperatable is IJBOperatable {\n //*********************************************************************//\n // --------------------------- custom errors -------------------------- //\n //*********************************************************************//\n error UNAUTHORIZED();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Only allows the speficied account or an operator of the account to proceed. \n\n @param _account The account to check for.\n @param _domain The domain namespace to look for an operator within. \n @param _permissionIndex The index of the permission to check for. \n */\n modifier requirePermission(\n address _account,\n uint256 _domain,\n uint256 _permissionIndex\n ) {\n _requirePermission(_account, _domain, _permissionIndex);\n _;\n }\n\n /** \n @notice\n Only allows the speficied account, an operator of the account to proceed, or a truthy override flag. \n\n @param _account The account to check for.\n @param _domain The domain namespace to look for an operator within. \n @param _permissionIndex The index of the permission to check for. \n @param _override A condition to force allowance for.\n */\n modifier requirePermissionAllowingOverride(\n address _account,\n uint256 _domain,\n uint256 _permissionIndex,\n bool _override\n ) {\n _requirePermissionAllowingOverride(_account, _domain, _permissionIndex, _override);\n _;\n }\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /** \n @notice \n A contract storing operator assignments.\n */\n IJBOperatorStore public immutable override operatorStore;\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _operatorStore A contract storing operator assignments.\n */\n constructor(IJBOperatorStore _operatorStore) {\n operatorStore = _operatorStore;\n }\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Require the message sender is either the account or has the specified permission.\n\n @param _account The account to allow.\n @param _domain The domain namespace within which the permission index will be checked.\n @param _permissionIndex The permission index that an operator must have within the specified domain to be allowed.\n */\n function _requirePermission(\n address _account,\n uint256 _domain,\n uint256 _permissionIndex\n ) internal view {\n if (\n msg.sender != _account &&\n !operatorStore.hasPermission(msg.sender, _account, _domain, _permissionIndex) &&\n !operatorStore.hasPermission(msg.sender, _account, 0, _permissionIndex)\n ) revert UNAUTHORIZED();\n }\n\n /** \n @notice\n Require the message sender is either the account, has the specified permission, or the override condition is true.\n\n @param _account The account to allow.\n @param _domain The domain namespace within which the permission index will be checked.\n @param _domain The permission index that an operator must have within the specified domain to be allowed.\n @param _override The override condition to allow.\n */\n function _requirePermissionAllowingOverride(\n address _account,\n uint256 _domain,\n uint256 _permissionIndex,\n bool _override\n ) internal view {\n if (\n !_override &&\n msg.sender != _account &&\n !operatorStore.hasPermission(msg.sender, _account, _domain, _permissionIndex) &&\n !operatorStore.hasPermission(msg.sender, _account, 0, _permissionIndex)\n ) revert UNAUTHORIZED();\n }\n}\n" }, "contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBPayDelegateAllocation.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal is\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n IJBPayoutRedemptionPaymentTerminal\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n @dev\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.ETH)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.ETH, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance.\n */\n function _balance() internal view virtual returns (uint256);\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.ETH) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual {\n _from; // Prevents unused var compiler and natspec complaints.\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\n {\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\n\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _forwardedAmount,\n _beneficiary,\n _memo,\n _metadata\n );\n\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\n\n emit DelegateDidRedeem(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n }\n\n // Take the fee.\n _fee = _feeEligibleDistributionAmount != 0\n ? _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n )\n : 0;\n\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\n if (_leftoverDistributionAmount != 0) {\n // Subtract the fee from the net leftover amount.\n netLeftoverDistributionAmount =\n _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n\n // Transfer the amount to the project owner.\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n // The total percentage available to split\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = _split.percent == leftoverPercentage\n ? leftoverAmount\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\n\n // Decrement the leftover percentage.\n leftoverPercentage -= _split.percent;\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount;\n\n if (_payoutAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\n isFeelessAddress[address(_split.allocator)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n _netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n // If this terminal's token is ETH, send it in msg.value.\n _split.allocator.allocate{value: token == JBTokens.ETH ? _netPayoutAmount : 0}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // Save gas if this contract is being used as the terminal.\n if (_terminal == this) {\n // This distribution does not incur a fee.\n _netPayoutAmount = _payoutAmount;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\n else\n _pay(\n _netPayoutAmount,\n address(this),\n _split.projectId,\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n } else {\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_terminal)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _netPayoutAmount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _terminal.addToBalanceOf{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n '',\n _projectMetadata\n );\n else\n _terminal.pay{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n }\n } else {\n // Keep a reference to the beneficiary.\n address payable _beneficiary = _split.beneficiary != address(0)\n ? _split.beneficiary\n : payable(msg.sender);\n\n // If there's a full discount, this distribution is not eligible for a fee.\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(address(this), _beneficiary, _netPayoutAmount);\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n */\n function _processFee(uint256 _amount, address _beneficiary) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\n\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\n if (_terminal == this)\n _pay(\n _amount,\n address(this),\n _FEE_BENEFICIARY_PROJECT_ID,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the local pay call.\n else {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _amount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _amount : 0;\n\n // Send the payment.\n _terminal.pay{value: _payableValue}(\n _FEE_BENEFICIARY_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the external pay call of the correct terminal.\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\n {\n JBPayDelegateAllocation[] memory _delegateAllocations;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n _forwardedAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n // Get a reference to the number of delegates to allocate to.\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\n\n emit DelegateDidPay(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n unchecked {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\n IJBPaymentTerminal(address(0))\n ) return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge != IJBFeeGauge(address(0)))\n // If the guage reverts, keep the discount at 0.\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n // If the fee discount is greater than the max, we ignore the return value\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\n } catch {\n return 0;\n }\n\n return 0;\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBPayDelegateAllocation.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal is\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n IJBPayoutRedemptionPaymentTerminal\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n @dev\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.GAS_CURRENCY)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.GAS_CURRENCY, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance.\n */\n function _balance() internal view virtual returns (uint256);\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.GAS_TOKEN) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual {\n _from; // Prevents unused var compiler and natspec complaints.\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\n {\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\n\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _forwardedAmount,\n _beneficiary,\n _memo,\n _metadata\n );\n\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\n\n emit DelegateDidRedeem(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n }\n\n // Take the fee.\n _fee = _feeEligibleDistributionAmount != 0\n ? _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n )\n : 0;\n\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\n if (_leftoverDistributionAmount != 0) {\n // Subtract the fee from the net leftover amount.\n netLeftoverDistributionAmount =\n _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n\n // Transfer the amount to the project owner.\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n // The total percentage available to split\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = _split.percent == leftoverPercentage\n ? leftoverAmount\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\n\n // Decrement the leftover percentage.\n leftoverPercentage -= _split.percent;\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount;\n\n if (_payoutAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\n isFeelessAddress[address(_split.allocator)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n _netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n // If this terminal's token is ETH, send it in msg.value.\n _split.allocator.allocate{value: token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // Save gas if this contract is being used as the terminal.\n if (_terminal == this) {\n // This distribution does not incur a fee.\n _netPayoutAmount = _payoutAmount;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\n else\n _pay(\n _netPayoutAmount,\n address(this),\n _split.projectId,\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n } else {\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_terminal)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _terminal.addToBalanceOf{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n '',\n _projectMetadata\n );\n else\n _terminal.pay{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n }\n } else {\n // Keep a reference to the beneficiary.\n address payable _beneficiary = _split.beneficiary != address(0)\n ? _split.beneficiary\n : payable(msg.sender);\n\n // If there's a full discount, this distribution is not eligible for a fee.\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(address(this), _beneficiary, _netPayoutAmount);\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n */\n function _processFee(uint256 _amount, address _beneficiary) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\n\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\n if (_terminal == this)\n _pay(\n _amount,\n address(this),\n _FEE_BENEFICIARY_PROJECT_ID,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the local pay call.\n else {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _amount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send the payment.\n _terminal.pay{value: _payableValue}(\n _FEE_BENEFICIARY_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the external pay call of the correct terminal.\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\n {\n JBPayDelegateAllocation[] memory _delegateAllocations;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n _forwardedAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n // Get a reference to the number of delegates to allocate to.\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\n\n emit DelegateDidPay(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n unchecked {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\n IJBPaymentTerminal(address(0))\n ) return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge != IJBFeeGauge(address(0)))\n // If the guage reverts, keep the discount at 0.\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n // If the fee discount is greater than the max, we ignore the return value\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\n } catch {\n return 0;\n }\n\n return 0;\n }\n}\n" }, "contracts/abstract/JBPayoutRedemptionPaymentTerminal3_1.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/utils/introspection/ERC165Checker.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal3_1.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBPayDelegateAllocation.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal3_1: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal3_1 is\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n IJBPayoutRedemptionPaymentTerminal3_1\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n @dev\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.ETH)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.ETH, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal3_1).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal3_1).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal3_1).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance.\n */\n function _balance() internal view virtual returns (uint256);\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n bytes calldata _metadata\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _metadata);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes calldata _metadata\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _useAllowanceOf(\n _projectId,\n _amount,\n _currency,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n // Do not refund held fees by default.\n addToBalanceOf(_projectId, _amount, _token, false, _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary, _projectId);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n bool _shouldRefundHeldFees,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.ETH) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance.\n _addToBalanceOf(_projectId, _amount, _shouldRefundHeldFees, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual {\n _from; // Prevents unused var compiler and natspec complaints.\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered if a transfer should be undone\n\n @param _to The address to which the transfer went.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _cancelTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\n {\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\n\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _forwardedAmount,\n _beneficiary,\n _memo,\n _metadata\n );\n\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\n\n emit DelegateDidRedeem(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n bytes calldata _metadata\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n }\n\n // Take the fee.\n _fee = _feeEligibleDistributionAmount != 0\n ? _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n )\n : 0;\n\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\n if (_leftoverDistributionAmount != 0) {\n // Subtract the fee from the net leftover amount.\n netLeftoverDistributionAmount =\n _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n\n // Transfer the amount to the project owner.\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes calldata _metadata\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n // The total percentage available to split\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = _split.percent == leftoverPercentage\n ? leftoverAmount\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\n\n // Decrement the leftover percentage.\n leftoverPercentage -= _split.percent;\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount = _distributeToPayoutSplit(\n _split,\n _projectId,\n _group,\n _payoutAmount,\n _feeDiscount\n );\n\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (_netPayoutAmount != 0 && _netPayoutAmount != _payoutAmount)\n feeEligibleDistributionAmount += _payoutAmount;\n\n if (_payoutAmount > 0) {\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _payoutAmount,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Pays out a split for a project's funding cycle configuration.\n \n @param _split The split to distribute payouts to.\n @param _amount The total amount being distributed to the split, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return netPayoutAmount The amount sent to the split after subtracting fees.\n */\n function _distributeToPayoutSplit(\n JBSplit memory _split,\n uint256 _projectId,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 netPayoutAmount) {\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_split.allocator)]\n )\n netPayoutAmount = _amount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\n }\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), netPayoutAmount);\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n uint256 _error;\n bytes memory _reason;\n\n if (\n ERC165Checker.supportsInterface(\n address(_split.allocator),\n type(IJBSplitAllocator).interfaceId\n )\n )\n // If this terminal's token is ETH, send it in msg.value.\n try _split.allocator.allocate{value: token == JBTokens.ETH ? netPayoutAmount : 0}(_data) {\n\n } catch (bytes memory reason) {\n _reason = reason;\n _error = 1;\n }\n else _error = 2;\n\n\n if (_error != 0) {\n // Trigger any inhereted post-transfer cancelation logic.\n _cancelTransferTo(address(_split.allocator), netPayoutAmount);\n\n // Set the net payout amount to 0 to signal the reversion.\n netPayoutAmount = 0;\n\n // Add undistributed amount back to project's balance.\n store.recordAddedBalanceFor(_projectId, _amount);\n\n emit PayoutReverted(_projectId, _split, _amount, _error == 1 ? _reason : abi.encode(\"IERC165 fail\"), msg.sender);\n }\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (\n _terminal == this ||\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\n isFeelessAddress[address(_terminal)]\n )\n netPayoutAmount = _amount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\n }\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), netPayoutAmount);\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n try\n _terminal.addToBalanceOf{value: token == JBTokens.ETH ? netPayoutAmount : 0}(\n _split.projectId,\n netPayoutAmount,\n token,\n '',\n _projectMetadata\n )\n {} catch (bytes memory reason) {\n // Trigger any inhereted post-transfer cancelation logic.\n _cancelTransferTo(address(_terminal), netPayoutAmount);\n\n // Set the net payout amount to 0 to signal the reversion.\n netPayoutAmount = 0;\n\n // Add undistributed amount back to project's balance.\n store.recordAddedBalanceFor(_projectId, _amount);\n\n emit PayoutReverted(_projectId, _split, _amount, reason, msg.sender);\n }\n else\n try\n _terminal.pay{value: token == JBTokens.ETH ? netPayoutAmount : 0}(\n _split.projectId,\n netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n )\n {} catch (bytes memory reason) {\n // Trigger any inhereted post-transfer cancelation logic.\n _cancelTransferTo(address(_terminal), netPayoutAmount);\n\n // Set the net payout amount to 0 to signal the reversion.\n netPayoutAmount = 0;\n\n // Add undistributed amount back to project's balance.\n store.recordAddedBalanceFor(_projectId, _amount);\n\n emit PayoutReverted(_projectId, _split, _amount, reason, msg.sender);\n }\n } else {\n // Keep a reference to the beneficiary.\n address payable _beneficiary = _split.beneficiary != address(0)\n ? _split.beneficiary\n : payable(msg.sender);\n\n // If there's a full discount, this distribution is not eligible for a fee.\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\n netPayoutAmount = _amount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\n else {\n unchecked {\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\n }\n }\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(address(this), _beneficiary, netPayoutAmount);\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary, _projectId); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n @param _from The project ID the fee is being paid from.\n */\n function _processFee(\n uint256 _amount,\n address _beneficiary,\n uint256 _from\n ) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _amount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_from));\n\n // Trigger any inherited pre-transfer logic if funds will be transferred.\n if (address(_terminal) != address(this)) _beforeTransferTo(address(_terminal), _amount);\n\n try\n // Send the fee.\n _terminal.pay{value: _payableValue}(\n _FEE_BENEFICIARY_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n _projectMetadata\n )\n {} catch (bytes memory reason) {\n // Trigger any inhereted post-transfer cancelation logic if the pre-transfer logic was triggered.\n if (address(_terminal) != address(this)) _cancelTransferTo(address(_terminal), _amount);\n\n // Add fee amount back to project's balance.\n store.recordAddedBalanceFor(_from, _amount);\n\n emit FeeReverted(_from, _FEE_BENEFICIARY_PROJECT_ID, _amount, reason, msg.sender);\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\n {\n JBPayDelegateAllocation[] memory _delegateAllocations;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n _forwardedAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n // Get a reference to the number of delegates to allocate to.\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\n\n emit DelegateDidPay(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n unchecked {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\n IJBPaymentTerminal(address(0))\n ) return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge != IJBFeeGauge(address(0)))\n // If the guage reverts, keep the discount at 0.\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n // If the fee discount is greater than the max, we ignore the return value\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\n } catch {\n return 0;\n }\n\n return 0;\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/utils/introspection/ERC165Checker.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal3_1.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBPayDelegateAllocation.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal3_1: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal3_1 is\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n IJBPayoutRedemptionPaymentTerminal3_1\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n @dev\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.GAS_CURRENCY)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.GAS_CURRENCY, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal3_1).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal3_1).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal3_1).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance.\n */\n function _balance() internal view virtual returns (uint256);\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n bytes calldata _metadata\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _metadata);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes calldata _metadata\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _useAllowanceOf(\n _projectId,\n _amount,\n _currency,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n // Do not refund held fees by default.\n addToBalanceOf(_projectId, _amount, _token, false, _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary, _projectId);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n bool _shouldRefundHeldFees,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.GAS_TOKEN) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance.\n _addToBalanceOf(_projectId, _amount, _shouldRefundHeldFees, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual {\n _from; // Prevents unused var compiler and natspec complaints.\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered if a transfer should be undone\n\n @param _to The address to which the transfer went.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _cancelTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\n {\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\n\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _forwardedAmount,\n _beneficiary,\n _memo,\n _metadata\n );\n\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\n\n emit DelegateDidRedeem(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n bytes calldata _metadata\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n }\n\n // Take the fee.\n _fee = _feeEligibleDistributionAmount != 0\n ? _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n )\n : 0;\n\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\n if (_leftoverDistributionAmount != 0) {\n // Subtract the fee from the net leftover amount.\n netLeftoverDistributionAmount =\n _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n\n // Transfer the amount to the project owner.\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes calldata _metadata\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n // The total percentage available to split\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = _split.percent == leftoverPercentage\n ? leftoverAmount\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\n\n // Decrement the leftover percentage.\n leftoverPercentage -= _split.percent;\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount = _distributeToPayoutSplit(\n _split,\n _projectId,\n _group,\n _payoutAmount,\n _feeDiscount\n );\n\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (_netPayoutAmount != 0 && _netPayoutAmount != _payoutAmount)\n feeEligibleDistributionAmount += _payoutAmount;\n\n if (_payoutAmount > 0) {\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _payoutAmount,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Pays out a split for a project's funding cycle configuration.\n \n @param _split The split to distribute payouts to.\n @param _amount The total amount being distributed to the split, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return netPayoutAmount The amount sent to the split after subtracting fees.\n */\n function _distributeToPayoutSplit(\n JBSplit memory _split,\n uint256 _projectId,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 netPayoutAmount) {\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_split.allocator)]\n )\n netPayoutAmount = _amount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\n }\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), netPayoutAmount);\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n uint256 _error;\n bytes memory _reason;\n\n if (\n ERC165Checker.supportsInterface(\n address(_split.allocator),\n type(IJBSplitAllocator).interfaceId\n )\n )\n // If this terminal's token is ETH, send it in msg.value.\n try _split.allocator.allocate{value: token == JBTokens.GAS_TOKEN ? netPayoutAmount : 0}(_data) {\n\n } catch (bytes memory reason) {\n _reason = reason;\n _error = 1;\n }\n else _error = 2;\n\n\n if (_error != 0) {\n // Trigger any inhereted post-transfer cancelation logic.\n _cancelTransferTo(address(_split.allocator), netPayoutAmount);\n\n // Set the net payout amount to 0 to signal the reversion.\n netPayoutAmount = 0;\n\n // Add undistributed amount back to project's balance.\n store.recordAddedBalanceFor(_projectId, _amount);\n\n emit PayoutReverted(_projectId, _split, _amount, _error == 1 ? _reason : abi.encode(\"IERC165 fail\"), msg.sender);\n }\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (\n _terminal == this ||\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\n isFeelessAddress[address(_terminal)]\n )\n netPayoutAmount = _amount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\n }\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), netPayoutAmount);\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n try\n _terminal.addToBalanceOf{value: token == JBTokens.GAS_TOKEN ? netPayoutAmount : 0}(\n _split.projectId,\n netPayoutAmount,\n token,\n '',\n _projectMetadata\n )\n {} catch (bytes memory reason) {\n // Trigger any inhereted post-transfer cancelation logic.\n _cancelTransferTo(address(_terminal), netPayoutAmount);\n\n // Set the net payout amount to 0 to signal the reversion.\n netPayoutAmount = 0;\n\n // Add undistributed amount back to project's balance.\n store.recordAddedBalanceFor(_projectId, _amount);\n\n emit PayoutReverted(_projectId, _split, _amount, reason, msg.sender);\n }\n else\n try\n _terminal.pay{value: token == JBTokens.GAS_TOKEN ? netPayoutAmount : 0}(\n _split.projectId,\n netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n )\n {} catch (bytes memory reason) {\n // Trigger any inhereted post-transfer cancelation logic.\n _cancelTransferTo(address(_terminal), netPayoutAmount);\n\n // Set the net payout amount to 0 to signal the reversion.\n netPayoutAmount = 0;\n\n // Add undistributed amount back to project's balance.\n store.recordAddedBalanceFor(_projectId, _amount);\n\n emit PayoutReverted(_projectId, _split, _amount, reason, msg.sender);\n }\n } else {\n // Keep a reference to the beneficiary.\n address payable _beneficiary = _split.beneficiary != address(0)\n ? _split.beneficiary\n : payable(msg.sender);\n\n // If there's a full discount, this distribution is not eligible for a fee.\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\n netPayoutAmount = _amount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\n else {\n unchecked {\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\n }\n }\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(address(this), _beneficiary, netPayoutAmount);\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary, _projectId); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n @param _from The project ID the fee is being paid from.\n */\n function _processFee(\n uint256 _amount,\n address _beneficiary,\n uint256 _from\n ) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_from));\n\n // Trigger any inherited pre-transfer logic if funds will be transferred.\n if (address(_terminal) != address(this)) _beforeTransferTo(address(_terminal), _amount);\n\n try\n // Send the fee.\n _terminal.pay{value: _payableValue}(\n _FEE_BENEFICIARY_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n _projectMetadata\n )\n {} catch (bytes memory reason) {\n // Trigger any inhereted post-transfer cancelation logic if the pre-transfer logic was triggered.\n if (address(_terminal) != address(this)) _cancelTransferTo(address(_terminal), _amount);\n\n // Add fee amount back to project's balance.\n store.recordAddedBalanceFor(_from, _amount);\n\n emit FeeReverted(_from, _FEE_BENEFICIARY_PROJECT_ID, _amount, reason, msg.sender);\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\n {\n JBPayDelegateAllocation[] memory _delegateAllocations;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n _forwardedAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n // Get a reference to the number of delegates to allocate to.\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\n\n emit DelegateDidPay(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n unchecked {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\n IJBPaymentTerminal(address(0))\n ) return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge != IJBFeeGauge(address(0)))\n // If the guage reverts, keep the discount at 0.\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n // If the fee discount is greater than the max, we ignore the return value\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\n } catch {\n return 0;\n }\n\n return 0;\n }\n}\n" }, "contracts/abstract/JBSingleTokenPaymentTerminal.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport './../interfaces/IJBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n\n @dev\n Adheres to -\n IJBSingleTokenPaymentTerminals: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ERC165: Introspection on interface adherance. \n*/\nabstract contract JBSingleTokenPaymentTerminal is ERC165, IJBSingleTokenPaymentTerminal {\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The token that this terminal accepts.\n */\n address public immutable override token;\n\n /**\n @notice\n The number of decimals the token fixed point amounts are expected to have.\n */\n uint256 public immutable override decimals;\n\n /**\n @notice\n The currency to use when resolving price feeds for this terminal.\n */\n uint256 public immutable override currency;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n A flag indicating if this terminal accepts the specified token.\n\n @param _token The token to check if this terminal accepts or not.\n @param _projectId The project ID to check for token acceptance.\n\n @return The flag.\n */\n function acceptsToken(address _token, uint256 _projectId) external view override returns (bool) {\n _projectId; // Prevents unused var compiler and natspec complaints.\n\n return _token == token;\n }\n\n /** \n @notice\n The decimals that should be used in fixed number accounting for the specified token.\n\n @param _token The token to check for the decimals of.\n\n @return The number of decimals for the token.\n */\n function decimalsForToken(address _token) external view override returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return decimals;\n }\n\n /** \n @notice\n The currency that should be used for the specified token.\n\n @param _token The token to check for the currency of.\n\n @return The currency index.\n */\n function currencyForToken(address _token) external view override returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return currency;\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPaymentTerminal).interfaceId ||\n _interfaceId == type(IJBSingleTokenPaymentTerminal).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n */\n constructor(\n address _token,\n uint256 _decimals,\n uint256 _currency\n ) {\n token = _token;\n decimals = _decimals;\n currency = _currency;\n }\n}\n" @@ -133,11 +133,11 @@ "contracts/interfaces/IJBDirectory.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBFundingCycleStore.sol';\nimport './IJBPaymentTerminal.sol';\nimport './IJBProjects.sol';\n\ninterface IJBDirectory {\n event SetController(uint256 indexed projectId, address indexed controller, address caller);\n\n event AddTerminal(uint256 indexed projectId, IJBPaymentTerminal indexed terminal, address caller);\n\n event SetTerminals(uint256 indexed projectId, IJBPaymentTerminal[] terminals, address caller);\n\n event SetPrimaryTerminal(\n uint256 indexed projectId,\n address indexed token,\n IJBPaymentTerminal indexed terminal,\n address caller\n );\n\n event SetIsAllowedToSetFirstController(address indexed addr, bool indexed flag, address caller);\n\n function projects() external view returns (IJBProjects);\n\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\n\n function controllerOf(uint256 _projectId) external view returns (address);\n\n function isAllowedToSetFirstController(address _address) external view returns (bool);\n\n function terminalsOf(uint256 _projectId) external view returns (IJBPaymentTerminal[] memory);\n\n function isTerminalOf(uint256 _projectId, IJBPaymentTerminal _terminal)\n external\n view\n returns (bool);\n\n function primaryTerminalOf(uint256 _projectId, address _token)\n external\n view\n returns (IJBPaymentTerminal);\n\n function setControllerOf(uint256 _projectId, address _controller) external;\n\n function setTerminalsOf(uint256 _projectId, IJBPaymentTerminal[] calldata _terminals) external;\n\n function setPrimaryTerminalOf(\n uint256 _projectId,\n address _token,\n IJBPaymentTerminal _terminal\n ) external;\n\n function setIsAllowedToSetFirstController(address _address, bool _flag) external;\n}\n" }, - "contracts/interfaces/IJBETHERC20ProjectPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBDirectory.sol';\nimport './IJBProjectPayer.sol';\n\ninterface IJBETHERC20ProjectPayerDeployer {\n event DeployProjectPayer(\n IJBProjectPayer indexed projectPayer,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n IJBDirectory directory,\n address owner,\n address caller\n );\n\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external returns (IJBProjectPayer projectPayer);\n}\n" + "contracts/interfaces/IJBGasTokenERC20ProjectPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBDirectory.sol';\nimport './IJBProjectPayer.sol';\n\ninterface IJBGasTokenERC20ProjectPayerDeployer {\n event DeployProjectPayer(\n IJBProjectPayer indexed projectPayer,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n IJBDirectory directory,\n address owner,\n address caller\n );\n\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external returns (IJBProjectPayer projectPayer);\n}\n" }, - "contracts/interfaces/IJBETHERC20SplitsPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBSplitsPayer.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBETHERC20SplitsPayerDeployer {\n event DeploySplitsPayer(\n IJBSplitsPayer indexed splitsPayer,\n uint256 defaultSplitsProjectId,\n uint256 defaultSplitsDomain,\n uint256 defaultSplitsGroup,\n IJBSplitsStore splitsStore,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n address owner,\n address caller\n );\n\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string calldata _defaultMemo,\n bytes calldata _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n}\n" + "contracts/interfaces/IJBGasTokenERC20SplitsPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBSplitsPayer.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBGasTokenERC20SplitsPayerDeployer {\n event DeploySplitsPayer(\n IJBSplitsPayer indexed splitsPayer,\n uint256 defaultSplitsProjectId,\n uint256 defaultSplitsDomain,\n uint256 defaultSplitsGroup,\n IJBSplitsStore splitsStore,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n address owner,\n address caller\n );\n\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string calldata _defaultMemo,\n bytes calldata _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n}\n" }, "contracts/interfaces/IJBFeeGauge.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IJBFeeGauge {\n function currentDiscountFor(uint256 _projectId) external view returns (uint256);\n}\n" @@ -250,23 +250,23 @@ "contracts/JBERC20PaymentTerminal3_1.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal3_1.sol';\n\n/** \n @notice \n Manages the inflows and outflows of an ERC-20 token.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\ncontract JBERC20PaymentTerminal3_1 is JBPayoutRedemptionPaymentTerminal3_1 {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return IERC20(token).balanceOf(address(this));\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n IERC20Metadata _token,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal3_1(\n address(_token),\n _token.decimals(),\n _currency,\n _baseWeightCurrency,\n _payoutSplitsGroup,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from == address(this)\n ? IERC20(token).safeTransfer(_to, _amount)\n : IERC20(token).safeTransferFrom(_from, _to, _amount);\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal override {\n IERC20(token).safeIncreaseAllowance(_to, _amount);\n }\n\n /** \n @notice\n Logic to be triggered if a transfer should be undone\n\n @param _to The address to which the transfer went.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _cancelTransferTo(address _to, uint256 _amount) internal override {\n IERC20(token).safeDecreaseAllowance(_to, _amount);\n }\n}\n" }, - "contracts/JBETHERC20ProjectPayer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport './interfaces/IJBProjectPayer.sol';\nimport './libraries/JBTokens.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ERC165: Introspection on interface adherance. \n*/\ncontract JBETHERC20ProjectPayer is Ownable, ERC165, IJBProjectPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // -------------------------- custom errors -------------------------- //\n //*********************************************************************//\n error INCORRECT_DECIMAL_AMOUNT();\n error NO_MSG_VALUE_ALLOWED();\n error TERMINAL_NOT_FOUND();\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice \n A contract storing directories of terminals and controllers for each project.\n */\n IJBDirectory public immutable override directory;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The ID of the project that should be used to forward this contract's received payments.\n */\n uint256 public override defaultProjectId;\n\n /** \n @notice \n The beneficiary that should be used in the payment made when this contract receives payments.\n */\n address payable public override defaultBeneficiary;\n\n /** \n @notice \n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\n */\n bool public override defaultPreferClaimedTokens;\n\n /** \n @notice \n The memo that should be used in the payment made when this contract receives payments.\n */\n string public override defaultMemo;\n\n /** \n @notice \n The metadata that should be used in the payment made when this contract receives payments.\n */\n bytes public override defaultMetadata;\n\n /**\n @notice \n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n bool public override defaultPreferAddToBalance;\n\n //*********************************************************************//\n // ------------------------- public views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) {\n defaultProjectId = _defaultProjectId;\n defaultBeneficiary = _defaultBeneficiary;\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\n defaultMemo = _defaultMemo;\n defaultMetadata = _defaultMetadata;\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n directory = _directory;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default project ID using the stored default properties.\n\n @dev\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override {\n if (defaultPreferAddToBalance)\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.ETH,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n defaultProjectId,\n JBTokens.ETH,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultBeneficiary == address(0) ? tx.origin : defaultBeneficiary,\n 0, // Can't determine expectation of returned tokens ahead of time.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\n\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _beneficiary The address that'll receive the project's tokens. \n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _memo The memo that'll be used. \n @param _metadata The metadata that'll be sent. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external virtual override onlyOwner {\n // Set the default project ID if it has changed.\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\n\n // Set the default beneficiary if it has changed.\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\n\n // Set the default claimed token preference if it has changed.\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\n defaultPreferClaimedTokens = _preferClaimedTokens;\n\n // Set the default memo if it has changed.\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\n defaultMemo = _memo;\n\n // Set the default metadata if it has changed.\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\n defaultMetadata = _metadata;\n\n // Set the add to balance preference if it has changed.\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n\n emit SetDefaultValues(\n _projectId,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata,\n _defaultPreferAddToBalance,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _pay(\n _projectId,\n _token,\n _amount,\n _decimals,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. \n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source and delegate, if provided.\n */\n function _pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.ETH) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\n\n // Send funds to the terminal.\n // If the token is ETH, send it in msg.value.\n _terminal.pay{value: _payableValue}(\n _projectId,\n _amount, // ignored if the token is JBTokens.ETH.\n _token,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.ETH) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\n\n // Add to balance so tokens don't get issued.\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\n }\n}\n" + "contracts/JBGasTokenERC20ProjectPayer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport './interfaces/IJBProjectPayer.sol';\nimport './libraries/JBTokens.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ERC165: Introspection on interface adherance. \n*/\ncontract JBGasTokenERC20ProjectPayer is Ownable, ERC165, IJBProjectPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // -------------------------- custom errors -------------------------- //\n //*********************************************************************//\n error INCORRECT_DECIMAL_AMOUNT();\n error NO_MSG_VALUE_ALLOWED();\n error TERMINAL_NOT_FOUND();\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice \n A contract storing directories of terminals and controllers for each project.\n */\n IJBDirectory public immutable override directory;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The ID of the project that should be used to forward this contract's received payments.\n */\n uint256 public override defaultProjectId;\n\n /** \n @notice \n The beneficiary that should be used in the payment made when this contract receives payments.\n */\n address payable public override defaultBeneficiary;\n\n /** \n @notice \n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\n */\n bool public override defaultPreferClaimedTokens;\n\n /** \n @notice \n The memo that should be used in the payment made when this contract receives payments.\n */\n string public override defaultMemo;\n\n /** \n @notice \n The metadata that should be used in the payment made when this contract receives payments.\n */\n bytes public override defaultMetadata;\n\n /**\n @notice \n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n bool public override defaultPreferAddToBalance;\n\n //*********************************************************************//\n // ------------------------- public views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) {\n defaultProjectId = _defaultProjectId;\n defaultBeneficiary = _defaultBeneficiary;\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\n defaultMemo = _defaultMemo;\n defaultMetadata = _defaultMetadata;\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n directory = _directory;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default project ID using the stored default properties.\n\n @dev\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override {\n if (defaultPreferAddToBalance)\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultBeneficiary == address(0) ? tx.origin : defaultBeneficiary,\n 0, // Can't determine expectation of returned tokens ahead of time.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\n\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _beneficiary The address that'll receive the project's tokens. \n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _memo The memo that'll be used. \n @param _metadata The metadata that'll be sent. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external virtual override onlyOwner {\n // Set the default project ID if it has changed.\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\n\n // Set the default beneficiary if it has changed.\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\n\n // Set the default claimed token preference if it has changed.\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\n defaultPreferClaimedTokens = _preferClaimedTokens;\n\n // Set the default memo if it has changed.\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\n defaultMemo = _memo;\n\n // Set the default metadata if it has changed.\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\n defaultMetadata = _metadata;\n\n // Set the add to balance preference if it has changed.\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n\n emit SetDefaultValues(\n _projectId,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata,\n _defaultPreferAddToBalance,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _pay(\n _projectId,\n _token,\n _amount,\n _decimals,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. \n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source and delegate, if provided.\n */\n function _pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send funds to the terminal.\n // If the token is ETH, send it in msg.value.\n _terminal.pay{value: _payableValue}(\n _projectId,\n _amount, // ignored if the token is JBTokens.GAS_TOKEN.\n _token,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Add to balance so tokens don't get issued.\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\n }\n}\n" }, - "contracts/JBETHERC20ProjectPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './interfaces/IJBETHERC20ProjectPayerDeployer.sol';\nimport './JBETHERC20ProjectPayer.sol';\n\n/** \n @notice \n Deploys project payer contracts.\n\n @dev\n Adheres to -\n IJBETHERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBETHERC20ProjectPayerDeployer is IJBETHERC20ProjectPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new project payer contract.\n\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the project payer contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the project payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the project payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the project payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the project payer.\n\n @return projectPayer The project payer contract.\n */\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external override returns (IJBProjectPayer projectPayer) {\n // Deploy the project payer.\n projectPayer = new JBETHERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner\n );\n\n emit DeployProjectPayer(\n projectPayer,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner,\n msg.sender\n );\n }\n}\n" + "contracts/JBGasTokenERC20ProjectPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './interfaces/IJBGasTokenERC20ProjectPayerDeployer.sol';\nimport './JBGasTokenERC20ProjectPayer.sol';\n\n/** \n @notice \n Deploys project payer contracts.\n\n @dev\n Adheres to -\n IJBGasTokenERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBGasTokenERC20ProjectPayerDeployer is IJBGasTokenERC20ProjectPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new project payer contract.\n\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the project payer contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the project payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the project payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the project payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the project payer.\n\n @return projectPayer The project payer contract.\n */\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external override returns (IJBProjectPayer projectPayer) {\n // Deploy the project payer.\n projectPayer = new JBGasTokenERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner\n );\n\n emit DeployProjectPayer(\n projectPayer,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner,\n msg.sender\n );\n }\n}\n" }, - "contracts/JBETHERC20SplitsPayer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBSplitsPayer.sol';\nimport './interfaces/IJBSplitsStore.sol';\nimport './libraries/JBConstants.sol';\nimport './JBETHERC20ProjectPayer.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\n\n @dev\n Adheres to -\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBETHERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBETHERC20SplitsPayer is JBETHERC20ProjectPayer, ReentrancyGuard, IJBSplitsPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The ID of project for which the default splits are stored. \n */\n uint256 public override defaultSplitsProjectId;\n\n /**\n @notice\n The domain within which the default splits are stored. \n */\n uint256 public override defaultSplitsDomain;\n\n /**\n @notice\n The group within which the default splits are stored. \n */\n uint256 public override defaultSplitsGroup;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBETHERC20ProjectPayer, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n )\n JBETHERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _preferAddToBalance,\n _splitsStore.directory(),\n _owner\n )\n {\n defaultSplitsProjectId = _defaultSplitsProjectId;\n defaultSplitsDomain = _defaultSplitsDomain;\n defaultSplitsGroup = _defaultSplitsGroup;\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default split group using the stored default properties.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override nonReentrant {\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n JBTokens.ETH,\n address(this).balance,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // If there is no leftover amount, nothing left to pay.\n if (_leftoverAmount == 0) return;\n\n // If there's a default project ID, try to pay it.\n if (defaultProjectId != 0)\n if (defaultPreferAddToBalance)\n // Pay the project by adding to its balance if prefered.\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.ETH,\n _leftoverAmount,\n 18, // decimals.\n defaultMemo,\n defaultMetadata\n );\n // Otherwise, issue a payment to the project.\n else\n _pay(\n defaultProjectId,\n JBTokens.ETH,\n _leftoverAmount,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n 0, // min returned tokens.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else\n Address.sendValue(\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(tx.origin),\n _leftoverAmount\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the splits in the splits store that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n @param _groupedSplits The split groups to set.\n */\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n JBGroupedSplits[] memory _groupedSplits\n ) external virtual override onlyOwner {\n // Set the splits in the store.\n splitsStore.set(_projectId, _domain, _groupedSplits);\n\n // Set the splits reference.\n setDefaultSplitsReference(_projectId, _domain, _group);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the location of the splits that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n */\n function setDefaultSplitsReference(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) public virtual override onlyOwner {\n // Set the default splits project ID if it's changing.\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\n\n // Set the default splits domain if it's changing.\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\n\n // Set the default splits group if it's changing.\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\n\n emit SetDefaultSplitsReference(_projectId, _domain, _group, msg.sender);\n }\n\n /** \n @notice \n Make a payment to the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Pay any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to pay it.\n if (_projectId != 0) {\n _pay(\n _projectId,\n _token,\n _leftoverAmount,\n _decimals,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? payable(_beneficiary) : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit Pay(\n _projectId,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event. \n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Distribute any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to add to its balance.\n if (_projectId != 0)\n // Add to the project's balance.\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\n\n // Otherwise, send a payment to the beneficiary.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit AddToBalance(\n _projectId,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splitsProjectId The ID of the project to which the splits belong.\n @param _splitsDomain The splits domain to which the group belongs.\n @param _splitsGroup The splits group to pay.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payToSplits(\n uint256 _splitsProjectId,\n uint256 _splitsDomain,\n uint256 _splitsGroup,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Pay the splits.\n leftoverAmount = _payTo(\n splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup),\n _token,\n _amount,\n _decimals,\n _defaultBeneficiary\n );\n emit DistributeToSplitGroup(_splitsProjectId, _splitsDomain, _splitsGroup, msg.sender);\n }\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splits The splits.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payTo(\n JBSplit[] memory _splits,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Set the leftover amount to the initial balance.\n leftoverAmount = _amount;\n\n // Settle between all splits.\n for (uint256 i; i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[i];\n\n // The amount to send towards the split.\n uint256 _splitAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n if (_splitAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n _token,\n _splitAmount,\n _decimals,\n defaultProjectId,\n 0,\n _split\n );\n\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\n if (_token != JBTokens.ETH)\n IERC20(_token).safeApprove(address(_split.allocator), _splitAmount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _splitAmount : 0;\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n if (_split.preferAddToBalance)\n _addToBalanceOf(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n 0,\n _split.preferClaimed,\n defaultMemo,\n defaultMetadata\n );\n } else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : payable(_defaultBeneficiary),\n _splitAmount\n );\n // Or, transfer the ERC20.\n else {\n IERC20(_token).safeTransfer(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n _splitAmount\n );\n }\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _splitAmount;\n }\n\n emit DistributeToSplit(_split, _splitAmount, _defaultBeneficiary, msg.sender);\n\n unchecked {\n ++i;\n }\n }\n }\n}\n" + "contracts/JBGasTokenERC20SplitsPayer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBSplitsPayer.sol';\nimport './interfaces/IJBSplitsStore.sol';\nimport './libraries/JBConstants.sol';\nimport './JBGasTokenERC20ProjectPayer.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\n\n @dev\n Adheres to -\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBGasTokenERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBGasTokenERC20SplitsPayer is JBGasTokenERC20ProjectPayer, ReentrancyGuard, IJBSplitsPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The ID of project for which the default splits are stored. \n */\n uint256 public override defaultSplitsProjectId;\n\n /**\n @notice\n The domain within which the default splits are stored. \n */\n uint256 public override defaultSplitsDomain;\n\n /**\n @notice\n The group within which the default splits are stored. \n */\n uint256 public override defaultSplitsGroup;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBGasTokenERC20ProjectPayer, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n )\n JBGasTokenERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _preferAddToBalance,\n _splitsStore.directory(),\n _owner\n )\n {\n defaultSplitsProjectId = _defaultSplitsProjectId;\n defaultSplitsDomain = _defaultSplitsDomain;\n defaultSplitsGroup = _defaultSplitsGroup;\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default split group using the stored default properties.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override nonReentrant {\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // If there is no leftover amount, nothing left to pay.\n if (_leftoverAmount == 0) return;\n\n // If there's a default project ID, try to pay it.\n if (defaultProjectId != 0)\n if (defaultPreferAddToBalance)\n // Pay the project by adding to its balance if prefered.\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n _leftoverAmount,\n 18, // decimals.\n defaultMemo,\n defaultMetadata\n );\n // Otherwise, issue a payment to the project.\n else\n _pay(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n _leftoverAmount,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n 0, // min returned tokens.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else\n Address.sendValue(\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(tx.origin),\n _leftoverAmount\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the splits in the splits store that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n @param _groupedSplits The split groups to set.\n */\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n JBGroupedSplits[] memory _groupedSplits\n ) external virtual override onlyOwner {\n // Set the splits in the store.\n splitsStore.set(_projectId, _domain, _groupedSplits);\n\n // Set the splits reference.\n setDefaultSplitsReference(_projectId, _domain, _group);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the location of the splits that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n */\n function setDefaultSplitsReference(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) public virtual override onlyOwner {\n // Set the default splits project ID if it's changing.\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\n\n // Set the default splits domain if it's changing.\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\n\n // Set the default splits group if it's changing.\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\n\n emit SetDefaultSplitsReference(_projectId, _domain, _group, msg.sender);\n }\n\n /** \n @notice \n Make a payment to the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Pay any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to pay it.\n if (_projectId != 0) {\n _pay(\n _projectId,\n _token,\n _leftoverAmount,\n _decimals,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? payable(_beneficiary) : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit Pay(\n _projectId,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event. \n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Distribute any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to add to its balance.\n if (_projectId != 0)\n // Add to the project's balance.\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\n\n // Otherwise, send a payment to the beneficiary.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit AddToBalance(\n _projectId,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splitsProjectId The ID of the project to which the splits belong.\n @param _splitsDomain The splits domain to which the group belongs.\n @param _splitsGroup The splits group to pay.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payToSplits(\n uint256 _splitsProjectId,\n uint256 _splitsDomain,\n uint256 _splitsGroup,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Pay the splits.\n leftoverAmount = _payTo(\n splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup),\n _token,\n _amount,\n _decimals,\n _defaultBeneficiary\n );\n emit DistributeToSplitGroup(_splitsProjectId, _splitsDomain, _splitsGroup, msg.sender);\n }\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splits The splits.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payTo(\n JBSplit[] memory _splits,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Set the leftover amount to the initial balance.\n leftoverAmount = _amount;\n\n // Settle between all splits.\n for (uint256 i; i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[i];\n\n // The amount to send towards the split.\n uint256 _splitAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n if (_splitAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n _token,\n _splitAmount,\n _decimals,\n defaultProjectId,\n 0,\n _split\n );\n\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN)\n IERC20(_token).safeApprove(address(_split.allocator), _splitAmount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _splitAmount : 0;\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n if (_split.preferAddToBalance)\n _addToBalanceOf(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n 0,\n _split.preferClaimed,\n defaultMemo,\n defaultMetadata\n );\n } else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : payable(_defaultBeneficiary),\n _splitAmount\n );\n // Or, transfer the ERC20.\n else {\n IERC20(_token).safeTransfer(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n _splitAmount\n );\n }\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _splitAmount;\n }\n\n emit DistributeToSplit(_split, _splitAmount, _defaultBeneficiary, msg.sender);\n\n unchecked {\n ++i;\n }\n }\n }\n}\n" }, - "contracts/JBETHERC20SplitsPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './interfaces/IJBETHERC20SplitsPayerDeployer.sol';\nimport './structs/JBSplit.sol';\nimport './structs/JBGroupedSplits.sol';\nimport './JBETHERC20SplitsPayer.sol';\n\n/** \n @notice \n Deploys splits payer contracts.\n\n @dev\n Adheres to -\n IJBETHERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBETHERC20SplitsPayerDeployer is IJBETHERC20SplitsPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @dev\n This contract must have Operator permissions over the SET_SPLITS permission of the specified `_defaultSplitsProjectId`.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplits The splits to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBSplitsPayer splitsPayer) {\n // Use this contract's address as the domain.\n uint256 _domain = uint256(uint160(address(this)));\n\n // Create the random hash using data unique to this instance that'll be used as the storage domain.\n uint256 _group = uint256(keccak256(abi.encodePacked(msg.sender, block.number)));\n\n // Set the splits in the store.\n JBGroupedSplits[] memory _groupedSplits;\n _groupedSplits = new JBGroupedSplits[](1);\n _groupedSplits[0] = JBGroupedSplits(_group, _defaultSplits);\n _splitsStore.set(_defaultSplitsProjectId, _domain, _groupedSplits);\n\n return\n deploySplitsPayer(\n _defaultSplitsProjectId,\n _domain,\n _group,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n }\n\n //*********************************************************************//\n // ---------------------- public transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) public override returns (IJBSplitsPayer splitsPayer) {\n // Deploy the splits payer.\n splitsPayer = new JBETHERC20SplitsPayer(\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeploySplitsPayer(\n splitsPayer,\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner,\n msg.sender\n );\n }\n}\n" + "contracts/JBGasTokenERC20SplitsPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './interfaces/IJBGasTokenERC20SplitsPayerDeployer.sol';\nimport './structs/JBSplit.sol';\nimport './structs/JBGroupedSplits.sol';\nimport './JBGasTokenERC20SplitsPayer.sol';\n\n/** \n @notice \n Deploys splits payer contracts.\n\n @dev\n Adheres to -\n IJBGasTokenERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBGasTokenERC20SplitsPayerDeployer is IJBGasTokenERC20SplitsPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @dev\n This contract must have Operator permissions over the SET_SPLITS permission of the specified `_defaultSplitsProjectId`.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplits The splits to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBSplitsPayer splitsPayer) {\n // Use this contract's address as the domain.\n uint256 _domain = uint256(uint160(address(this)));\n\n // Create the random hash using data unique to this instance that'll be used as the storage domain.\n uint256 _group = uint256(keccak256(abi.encodePacked(msg.sender, block.number)));\n\n // Set the splits in the store.\n JBGroupedSplits[] memory _groupedSplits;\n _groupedSplits = new JBGroupedSplits[](1);\n _groupedSplits[0] = JBGroupedSplits(_group, _defaultSplits);\n _splitsStore.set(_defaultSplitsProjectId, _domain, _groupedSplits);\n\n return\n deploySplitsPayer(\n _defaultSplitsProjectId,\n _domain,\n _group,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n }\n\n //*********************************************************************//\n // ---------------------- public transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) public override returns (IJBSplitsPayer splitsPayer) {\n // Deploy the splits payer.\n splitsPayer = new JBGasTokenERC20SplitsPayer(\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeploySplitsPayer(\n splitsPayer,\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner,\n msg.sender\n );\n }\n}\n" }, "contracts/JBETHPaymentTerminal.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\nimport './libraries/JBSplitsGroups.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return address(this).balance;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n JBTokens.ETH,\n 18, // 18 decimals.\n JBCurrencies.ETH,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\nimport './libraries/JBSplitsGroups.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return address(this).balance;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n JBTokens.GAS_TOKEN,\n 18, // 18 decimals.\n JBCurrencies.GAS_CURRENCY,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n}\n" }, "contracts/JBETHPaymentTerminal3_1.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal3_1.sol';\nimport './libraries/JBSplitsGroups.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal3_1: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal3_1 is JBPayoutRedemptionPaymentTerminal3_1 {\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return address(this).balance;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal3_1(\n JBTokens.ETH,\n 18, // 18 decimals.\n JBCurrencies.ETH,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal3_1.sol';\nimport './libraries/JBSplitsGroups.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal3_1: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal3_1 is JBPayoutRedemptionPaymentTerminal3_1 {\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return address(this).balance;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal3_1(\n JBTokens.GAS_TOKEN,\n 18, // 18 decimals.\n JBCurrencies.GAS_CURRENCY,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n}\n" }, "contracts/JBFundAccessConstraintsStore.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport './abstract/JBControllerUtility.sol';\nimport './interfaces/IJBFundAccessConstraintsStore.sol';\n\n/**\n @notice\n Information pertaining to how much funds can be accessed by a project from each payment terminal.\n \n @dev\n Adheres to -\n IJBFundAccessConstraintsStore: General interface for the generic controller methods in this contract that interacts with funding cycles and tokens according to the protocol's rules.\n\n @dev\n Inherits from -\n JBControllerUtility: Several functions in this contract can only be accessed by a project owner, or an address that has been preconfifigured to be an operator of the project.\n ERC165: Introspection on interface adherance. \n*/\ncontract JBFundAccessConstraintsStore is\n JBControllerUtility,\n ERC165,\n IJBFundAccessConstraintsStore\n{\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n\n error INVALID_DISTRIBUTION_LIMIT();\n error INVALID_DISTRIBUTION_LIMIT_CURRENCY();\n error INVALID_OVERFLOW_ALLOWANCE();\n error INVALID_OVERFLOW_ALLOWANCE_CURRENCY();\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Data regarding the distribution limit of a project during a configuration.\n\n @dev\n bits 0-231: The amount of token that a project can distribute per funding cycle.\n\n @dev\n bits 232-255: The currency of amount that a project can distribute.\n\n _projectId The ID of the project to get the packed distribution limit data of.\n _configuration The configuration during which the packed distribution limit data applies.\n _terminal The terminal from which distributions are being limited.\n _token The token for which distributions are being limited.\n */\n mapping(uint256 => mapping(uint256 => mapping(IJBPaymentTerminal => mapping(address => uint256))))\n internal _packedDistributionLimitDataOf;\n\n /**\n @notice\n Data regarding the overflow allowance of a project during a configuration.\n\n @dev\n bits 0-231: The amount of overflow that a project is allowed to tap into on-demand throughout the configuration.\n\n @dev\n bits 232-255: The currency of the amount of overflow that a project is allowed to tap.\n\n _projectId The ID of the project to get the packed overflow allowance data of.\n _configuration The configuration during which the packed overflow allowance data applies.\n _terminal The terminal managing the overflow.\n _token The token for which overflow is being allowed.\n */\n mapping(uint256 => mapping(uint256 => mapping(IJBPaymentTerminal => mapping(address => uint256))))\n internal _packedOverflowAllowanceDataOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of token that a project can distribute per funding cycle, and the currency it's in terms of.\n\n @dev\n The number of decimals in the returned fixed point amount is the same as that of the specified terminal. \n\n @param _projectId The ID of the project to get the distribution limit of.\n @param _configuration The configuration during which the distribution limit applies.\n @param _terminal The terminal from which distributions are being limited.\n @param _token The token for which the distribution limit applies.\n\n @return The distribution limit, as a fixed point number with the same number of decimals as the provided terminal.\n @return The currency of the distribution limit.\n */\n function distributionLimitOf(\n uint256 _projectId,\n uint256 _configuration,\n IJBPaymentTerminal _terminal,\n address _token\n ) external view override returns (uint256, uint256) {\n // Get a reference to the packed data.\n uint256 _data = _packedDistributionLimitDataOf[_projectId][_configuration][_terminal][_token];\n\n // The limit is in bits 0-231. The currency is in bits 232-255.\n return (uint256(uint232(_data)), _data >> 232);\n }\n\n /**\n @notice\n The amount of overflow that a project is allowed to tap into on-demand throughout a configuration, and the currency it's in terms of.\n\n @dev\n The number of decimals in the returned fixed point amount is the same as that of the specified terminal. \n\n @param _projectId The ID of the project to get the overflow allowance of.\n @param _configuration The configuration of the during which the allowance applies.\n @param _terminal The terminal managing the overflow.\n @param _token The token for which the overflow allowance applies.\n\n @return The overflow allowance, as a fixed point number with the same number of decimals as the provided terminal.\n @return The currency of the overflow allowance.\n */\n function overflowAllowanceOf(\n uint256 _projectId,\n uint256 _configuration,\n IJBPaymentTerminal _terminal,\n address _token\n ) external view override returns (uint256, uint256) {\n // Get a reference to the packed data.\n uint256 _data = _packedOverflowAllowanceDataOf[_projectId][_configuration][_terminal][_token];\n\n // The allowance is in bits 0-231. The currency is in bits 232-255.\n return (uint256(uint232(_data)), _data >> 232);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _directory A contract storing directories of terminals and controllers for each project.\n */\n // solhint-disable-next-line no-empty-blocks\n constructor(IJBDirectory _directory) JBControllerUtility(_directory) {}\n\n //*********************************************************************//\n // --------------------- external transactions ----------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Sets a project's constraints for accessing treasury funds.\n\n @dev\n Only a project's current controller can set its fund access constraints.\n\n @param _projectId The ID of the project whose fund access constraints are being set.\n @param _configuration The funding cycle configuration the constraints apply within.\n @param _fundAccessConstraints An array containing amounts that a project can use from its treasury for each payment terminal. Amounts are fixed point numbers using the same number of decimals as the accompanying terminal. The `_distributionLimit` and `_overflowAllowance` parameters must fit in a `uint232`.\n */\n function setFor(\n uint256 _projectId,\n uint256 _configuration,\n JBFundAccessConstraints[] calldata _fundAccessConstraints\n ) external override onlyController(_projectId) {\n // Save the number of constraints.\n uint256 _numberOfFundAccessConstraints = _fundAccessConstraints.length;\n\n // Set distribution limits if there are any.\n for (uint256 _i; _i < _numberOfFundAccessConstraints; ) {\n // If distribution limit value is larger than 232 bits, revert.\n if (_fundAccessConstraints[_i].distributionLimit > type(uint232).max) revert INVALID_DISTRIBUTION_LIMIT();\n\n // If distribution limit currency value is larger than 24 bits, revert.\n if (_fundAccessConstraints[_i].distributionLimitCurrency > type(uint24).max)\n revert INVALID_DISTRIBUTION_LIMIT_CURRENCY();\n\n // If overflow allowance value is larger than 232 bits, revert.\n if (_fundAccessConstraints[_i].overflowAllowance > type(uint232).max) revert INVALID_OVERFLOW_ALLOWANCE();\n\n // If overflow allowance currency value is larger than 24 bits, revert.\n if (_fundAccessConstraints[_i].overflowAllowanceCurrency > type(uint24).max)\n revert INVALID_OVERFLOW_ALLOWANCE_CURRENCY();\n\n // Set the distribution limit if there is one.\n if (_fundAccessConstraints[_i].distributionLimit > 0)\n _packedDistributionLimitDataOf[_projectId][_configuration][_fundAccessConstraints[_i].terminal][\n _fundAccessConstraints[_i].token\n ] = _fundAccessConstraints[_i].distributionLimit | (_fundAccessConstraints[_i].distributionLimitCurrency << 232);\n\n // Set the overflow allowance if there is one.\n if (_fundAccessConstraints[_i].overflowAllowance > 0)\n _packedOverflowAllowanceDataOf[_projectId][_configuration][_fundAccessConstraints[_i].terminal][\n _fundAccessConstraints[_i].token\n ] = _fundAccessConstraints[_i].overflowAllowance | (_fundAccessConstraints[_i].overflowAllowanceCurrency << 232);\n\n emit SetFundAccessConstraints(_configuration, _projectId, _fundAccessConstraints[_i], msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n}\n" @@ -290,10 +290,10 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport './interfaces/IJBFundingCycleBallot.sol';\nimport './structs/JBFundingCycle.sol';\n\n/** \n @notice \n Manages approving funding cycle reconfigurations automatically after a buffer period.\n\n @dev\n Adheres to -\n IJBFundingCycleBallot: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ERC165: Introspection on interface adherance. \n*/\ncontract JBReconfigurationBufferBallot is ERC165, IJBFundingCycleBallot {\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice \n The number of seconds that must pass for a funding cycle reconfiguration to become either `Approved` or `Failed`.\n */\n uint256 public immutable override duration;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice \n The approval state of a particular funding cycle.\n\n @param _projectId The ID of the project to which the funding cycle being checked belongs.\n @param _configured The configuration of the funding cycle to check the state of.\n @param _start The start timestamp of the funding cycle to check the state of.\n\n @return The state of the provided ballot. \n */\n function stateOf(\n uint256 _projectId,\n uint256 _configured,\n uint256 _start\n ) public view override returns (JBBallotState) {\n _projectId; // Prevents unused var compiler and natspec complaints.\n\n // If the provided configured timestamp is after the start timestamp, the ballot is Failed.\n if (_configured > _start) return JBBallotState.Failed;\n\n unchecked {\n // If there was sufficient time between configuration and the start of the cycle, it is approved. Otherwise, it is failed.\n return (_start - _configured < duration) ? JBBallotState.Failed : JBBallotState.Approved;\n }\n }\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBFundingCycleBallot).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _duration The number of seconds to wait until a reconfiguration can be either `Approved` or `Failed`.\n */\n constructor(uint256 _duration) {\n duration = _duration;\n }\n}\n" }, "contracts/JBSingleTokenPaymentTerminalStore.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController.sol';\nimport './interfaces/IJBFundingCycleDataSource.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './structs/JBPayDelegateAllocation.sol';\nimport './structs/JBPayParamsData.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBSingleTokenPaymentTerminalStore is ReentrancyGuard, IJBSingleTokenPaymentTerminalStore {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n JBPayDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .payParams(_data);\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\n {\n // Keep a reference to the amount that should be added to the project's balance.\n uint256 _balanceDiff = _amount.value;\n\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\n if (delegateAllocations.length != 0) {\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0) {\n // Can't delegate more than was paid.\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\n\n // Decrement the total amount being added to the balance.\n _balanceDiff = _balanceDiff - _delegatedAmount;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Add the correct balance difference to the token balance of the project.\n if (_balanceDiff != 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _balanceDiff;\n }\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\n _projectId,\n fundingCycle.reservedRate()\n );\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow != 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\n {\n // Get a reference to the ballot state.\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\n\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n _state == JBBallotState.Active\n ? fundingCycle.ballotRedemptionRate()\n : fundingCycle.redemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\n fundingCycle.dataSource()\n ).redeemParams(_data);\n }\n } else {\n memo = _memo;\n }\n }\n\n // Keep a reference to the amount that should be subtracted from the project's balance.\n uint256 _balanceDiff = reclaimAmount;\n\n if (delegateAllocations.length != 0) {\n // Validate all delegated amounts.\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0)\n // Increment the total amount being subtracted from the balance.\n _balanceDiff = _balanceDiff + _delegatedAmount;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (_balanceDiff != 0) {\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n _balanceDiff;\n }\n }\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n unchecked {\n return\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i; _i < _terminals.length; ) {\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n unchecked {\n ++_i;\n }\n }\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.ETH\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.ETH, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController.sol';\nimport './interfaces/IJBFundingCycleDataSource.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './structs/JBPayDelegateAllocation.sol';\nimport './structs/JBPayParamsData.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBSingleTokenPaymentTerminalStore is ReentrancyGuard, IJBSingleTokenPaymentTerminalStore {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n JBPayDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .payParams(_data);\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\n {\n // Keep a reference to the amount that should be added to the project's balance.\n uint256 _balanceDiff = _amount.value;\n\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\n if (delegateAllocations.length != 0) {\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0) {\n // Can't delegate more than was paid.\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\n\n // Decrement the total amount being added to the balance.\n _balanceDiff = _balanceDiff - _delegatedAmount;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Add the correct balance difference to the token balance of the project.\n if (_balanceDiff != 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _balanceDiff;\n }\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\n _projectId,\n fundingCycle.reservedRate()\n );\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow != 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\n {\n // Get a reference to the ballot state.\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\n\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n _state == JBBallotState.Active\n ? fundingCycle.ballotRedemptionRate()\n : fundingCycle.redemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\n fundingCycle.dataSource()\n ).redeemParams(_data);\n }\n } else {\n memo = _memo;\n }\n }\n\n // Keep a reference to the amount that should be subtracted from the project's balance.\n uint256 _balanceDiff = reclaimAmount;\n\n if (delegateAllocations.length != 0) {\n // Validate all delegated amounts.\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0)\n // Increment the total amount being subtracted from the balance.\n _balanceDiff = _balanceDiff + _delegatedAmount;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (_balanceDiff != 0) {\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n _balanceDiff;\n }\n }\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n unchecked {\n return\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i; _i < _terminals.length; ) {\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n unchecked {\n ++_i;\n }\n }\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.GAS_CURRENCY\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.GAS_CURRENCY, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" }, "contracts/JBSingleTokenPaymentTerminalStore3_1.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController3_1.sol';\nimport './interfaces/IJBFundingCycleDataSource.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './structs/JBPayDelegateAllocation.sol';\nimport './structs/JBPayParamsData.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n\n @dev\n This Store expects a project's controller to be an IJBController3_1. This is the only difference between this version and the original.\n*/\ncontract JBSingleTokenPaymentTerminalStore3_1 is\n ReentrancyGuard,\n IJBSingleTokenPaymentTerminalStore\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId);\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n JBPayDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .payParams(_data);\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\n {\n // Keep a reference to the amount that should be added to the project's balance.\n uint256 _balanceDiff = _amount.value;\n\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\n if (delegateAllocations.length != 0) {\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0) {\n // Can't delegate more than was paid.\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\n\n // Decrement the total amount being added to the balance.\n _balanceDiff = _balanceDiff - _delegatedAmount;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Add the correct balance difference to the token balance of the project.\n if (_balanceDiff != 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _balanceDiff;\n }\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId);\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow != 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\n {\n // Get a reference to the ballot state.\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\n\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n _state == JBBallotState.Active\n ? fundingCycle.ballotRedemptionRate()\n : fundingCycle.redemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\n fundingCycle.dataSource()\n ).redeemParams(_data);\n }\n } else {\n memo = _memo;\n }\n }\n\n // Keep a reference to the amount that should be subtracted from the project's balance.\n uint256 _balanceDiff = reclaimAmount;\n\n if (delegateAllocations.length != 0) {\n // Validate all delegated amounts.\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0)\n // Increment the total amount being subtracted from the balance.\n _balanceDiff = _balanceDiff + _delegatedAmount;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (_balanceDiff != 0) {\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n _balanceDiff;\n }\n }\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).fundAccessConstraintsStore().distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).fundAccessConstraintsStore().overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).fundAccessConstraintsStore().distributionLimitOf(\n _projectId,\n _fundingCycle.configuration,\n _terminal,\n _terminal.token()\n );\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n unchecked {\n return\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i; _i < _terminals.length; ) {\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n unchecked {\n ++_i;\n }\n }\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.ETH\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.ETH, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController3_1.sol';\nimport './interfaces/IJBFundingCycleDataSource.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './structs/JBPayDelegateAllocation.sol';\nimport './structs/JBPayParamsData.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n\n @dev\n This Store expects a project's controller to be an IJBController3_1. This is the only difference between this version and the original.\n*/\ncontract JBSingleTokenPaymentTerminalStore3_1 is\n ReentrancyGuard,\n IJBSingleTokenPaymentTerminalStore\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId);\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n JBPayDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .payParams(_data);\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\n {\n // Keep a reference to the amount that should be added to the project's balance.\n uint256 _balanceDiff = _amount.value;\n\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\n if (delegateAllocations.length != 0) {\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0) {\n // Can't delegate more than was paid.\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\n\n // Decrement the total amount being added to the balance.\n _balanceDiff = _balanceDiff - _delegatedAmount;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Add the correct balance difference to the token balance of the project.\n if (_balanceDiff != 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _balanceDiff;\n }\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId);\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow != 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\n {\n // Get a reference to the ballot state.\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\n\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n _state == JBBallotState.Active\n ? fundingCycle.ballotRedemptionRate()\n : fundingCycle.redemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\n fundingCycle.dataSource()\n ).redeemParams(_data);\n }\n } else {\n memo = _memo;\n }\n }\n\n // Keep a reference to the amount that should be subtracted from the project's balance.\n uint256 _balanceDiff = reclaimAmount;\n\n if (delegateAllocations.length != 0) {\n // Validate all delegated amounts.\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0)\n // Increment the total amount being subtracted from the balance.\n _balanceDiff = _balanceDiff + _delegatedAmount;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (_balanceDiff != 0) {\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n _balanceDiff;\n }\n }\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).fundAccessConstraintsStore().distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).fundAccessConstraintsStore().overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).fundAccessConstraintsStore().distributionLimitOf(\n _projectId,\n _fundingCycle.configuration,\n _terminal,\n _terminal.token()\n );\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n unchecked {\n return\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i; _i < _terminals.length; ) {\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n unchecked {\n ++_i;\n }\n }\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.GAS_CURRENCY\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.GAS_CURRENCY, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" }, "contracts/JBSplitsStore.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './abstract/JBOperatable.sol';\nimport './interfaces/IJBDirectory.sol';\nimport './interfaces/IJBSplitsStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBOperations.sol';\n\n/**\n @notice\n Stores splits for each project.\n\n @dev\n Adheres to -\n IJBSplitsStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\ncontract JBSplitsStore is JBOperatable, IJBSplitsStore {\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_LOCKED_UNTIL();\n error INVALID_PROJECT_ID();\n error INVALID_SPLIT_PERCENT();\n error INVALID_TOTAL_PERCENT();\n error PREVIOUS_LOCKED_SPLITS_NOT_INCLUDED();\n\n //*********************************************************************//\n // --------------------- private stored properties ------------------- //\n //*********************************************************************//\n\n /** \n @notice\n The number of splits currently set for each project ID's configurations.\n\n _projectId The ID of the project to get the split count for.\n _domain An identifier within which the returned splits should be considered active.\n _group The identifying group of the splits.\n */\n mapping(uint256 => mapping(uint256 => mapping(uint256 => uint256))) private _splitCountOf;\n\n /** \n @notice\n Packed data of splits for each project ID's configurations.\n\n _projectId The ID of the project to get packed splits data for.\n _domain An identifier within which the returned splits should be considered active.\n _group The identifying group of the splits.\n _index The indexed order that the split was set at.\n */\n mapping(uint256 => mapping(uint256 => mapping(uint256 => mapping(uint256 => uint256))))\n private _packedSplitParts1Of;\n\n /** \n @notice\n More packed data of splits for each project ID's configurations.\n\n @dev\n This packed data is often 0.\n\n _projectId The ID of the project to get packed splits data for.\n _domain An identifier within which the returned splits should be considered active.\n _group The identifying group of the splits.\n _index The indexed order that the split was set at.\n */\n mapping(uint256 => mapping(uint256 => mapping(uint256 => mapping(uint256 => uint256))))\n private _packedSplitParts2Of;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /** \n @notice \n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /** \n @notice \n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice \n Get all splits for the specified project ID, within the specified domain, for the specified group.\n\n @param _projectId The ID of the project to get splits for.\n @param _domain An identifier within which the returned splits should be considered active.\n @param _group The identifying group of the splits.\n\n @return An array of all splits for the project.\n*/\n function splitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) external view override returns (JBSplit[] memory) {\n return _getStructsFor(_projectId, _domain, _group);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n */\n constructor(\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory\n ) JBOperatable(_operatorStore) {\n projects = _projects;\n directory = _directory;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets a project's splits.\n\n @dev\n Only the owner or operator of a project, or the current controller contract of the project, can set its splits.\n\n @dev\n The new splits must include any currently set splits that are locked.\n\n @param _projectId The ID of the project for which splits are being added.\n @param _domain An identifier within which the splits should be considered active.\n @param _groupedSplits An array of splits to set for any number of groups. \n */\n function set(\n uint256 _projectId,\n uint256 _domain,\n JBGroupedSplits[] calldata _groupedSplits\n )\n external\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.SET_SPLITS,\n address(directory.controllerOf(_projectId)) == msg.sender\n )\n {\n // Push array length in stack\n uint256 _groupedSplitsLength = _groupedSplits.length;\n\n // Set each grouped splits.\n for (uint256 _i; _i < _groupedSplitsLength; ) {\n // Get a reference to the grouped split being iterated on.\n JBGroupedSplits memory _groupedSplit = _groupedSplits[_i];\n\n // Set the splits for the group.\n _set(_projectId, _domain, _groupedSplit.group, _groupedSplit.splits);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets a project's splits.\n\n @dev\n The new splits must include any currently set splits that are locked.\n\n @param _projectId The ID of the project for which splits are being added.\n @param _domain An identifier within which the splits should be considered active.\n @param _group An identifier between of splits being set. All splits within this _group must add up to within 100%.\n @param _splits The splits to set.\n */\n function _set(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n JBSplit[] memory _splits\n ) internal {\n // Get a reference to the project's current splits.\n JBSplit[] memory _currentSplits = _getStructsFor(_projectId, _domain, _group);\n\n // Keep a reference to the number of splits.\n uint256 _currentSplitsLength = _currentSplits.length;\n\n // Check to see if all locked splits are included.\n for (uint256 _i; _i < _currentSplitsLength; ) {\n // If not locked, continue.\n if (\n block.timestamp < _currentSplits[_i].lockedUntil &&\n !_includesLocked(_splits, _currentSplits[_i])\n ) revert PREVIOUS_LOCKED_SPLITS_NOT_INCLUDED();\n\n unchecked {\n ++_i;\n }\n }\n\n // Add up all the percents to make sure they cumulatively are under 100%.\n uint256 _percentTotal;\n\n // Keep a reference to the number of splits.\n uint256 _splitsLength = _splits.length;\n\n for (uint256 _i; _i < _splitsLength; ) {\n // The percent should be greater than 0.\n if (_splits[_i].percent == 0) revert INVALID_SPLIT_PERCENT();\n\n // ProjectId should be within a uint56\n if (_splits[_i].projectId > type(uint56).max) revert INVALID_PROJECT_ID();\n\n // Add to the total percents.\n _percentTotal = _percentTotal + _splits[_i].percent;\n\n // Validate the total does not exceed the expected value.\n if (_percentTotal > JBConstants.SPLITS_TOTAL_PERCENT) revert INVALID_TOTAL_PERCENT();\n\n uint256 _packedSplitParts1;\n\n // prefer claimed in bit 0.\n if (_splits[_i].preferClaimed) _packedSplitParts1 = 1;\n // prefer add to balance in bit 1.\n if (_splits[_i].preferAddToBalance) _packedSplitParts1 |= 1 << 1;\n // percent in bits 2-33.\n _packedSplitParts1 |= _splits[_i].percent << 2;\n // projectId in bits 32-89.\n _packedSplitParts1 |= _splits[_i].projectId << 34;\n // beneficiary in bits 90-249.\n _packedSplitParts1 |= uint256(uint160(address(_splits[_i].beneficiary))) << 90;\n\n // Store the first split part.\n _packedSplitParts1Of[_projectId][_domain][_group][_i] = _packedSplitParts1;\n\n // If there's data to store in the second packed split part, pack and store.\n if (_splits[_i].lockedUntil > 0 || _splits[_i].allocator != IJBSplitAllocator(address(0))) {\n // Locked until should be within a uint48\n if (_splits[_i].lockedUntil > type(uint48).max) revert INVALID_LOCKED_UNTIL();\n\n // lockedUntil in bits 0-47.\n uint256 _packedSplitParts2 = uint48(_splits[_i].lockedUntil);\n // allocator in bits 48-207.\n _packedSplitParts2 |= uint256(uint160(address(_splits[_i].allocator))) << 48;\n\n // Store the second split part.\n _packedSplitParts2Of[_projectId][_domain][_group][_i] = _packedSplitParts2;\n\n // Otherwise if there's a value stored in the indexed position, delete it.\n } else if (_packedSplitParts2Of[_projectId][_domain][_group][_i] > 0)\n delete _packedSplitParts2Of[_projectId][_domain][_group][_i];\n\n emit SetSplit(_projectId, _domain, _group, _splits[_i], msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n\n // Set the new length of the splits.\n _splitCountOf[_projectId][_domain][_group] = _splitsLength;\n }\n\n /** \n @notice\n A flag indiciating if the provided splits array includes the locked split. \n\n @param _splits The array of splits to check within.\n @param _lockedSplit The locked split.\n\n @return A flag indicating if the `_lockedSplit` is contained in the `_splits`.\n */\n function _includesLocked(JBSplit[] memory _splits, JBSplit memory _lockedSplit)\n private\n pure\n returns (bool)\n {\n // Keep a reference to the number of splits.\n uint256 _numberOfSplits = _splits.length;\n\n for (uint256 _i; _i < _numberOfSplits; ) {\n // Check for sameness.\n if (\n _splits[_i].percent == _lockedSplit.percent &&\n _splits[_i].beneficiary == _lockedSplit.beneficiary &&\n _splits[_i].allocator == _lockedSplit.allocator &&\n _splits[_i].projectId == _lockedSplit.projectId &&\n _splits[_i].preferClaimed == _lockedSplit.preferClaimed &&\n _splits[_i].preferAddToBalance == _lockedSplit.preferAddToBalance &&\n // Allow lock extention.\n _splits[_i].lockedUntil >= _lockedSplit.lockedUntil\n ) return true;\n\n unchecked {\n ++_i;\n }\n }\n\n return false;\n }\n\n /**\n @notice \n Unpack splits' packed stored values into easy-to-work-with split structs.\n\n @param _projectId The ID of the project to which the split belongs.\n @param _domain The identifier within which the returned splits should be considered active.\n @param _group The identifying group of the splits.\n\n @return splits The split structs.\n */\n function _getStructsFor(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) private view returns (JBSplit[] memory) {\n // Get a reference to the number of splits that need to be added to the returned array.\n uint256 _splitCount = _splitCountOf[_projectId][_domain][_group];\n\n // Initialize an array to be returned that has the set length.\n JBSplit[] memory _splits = new JBSplit[](_splitCount);\n\n // Loop through each split and unpack the values into structs.\n for (uint256 _i; _i < _splitCount; ) {\n // Get a reference to the fist packed data.\n uint256 _packedSplitPart1 = _packedSplitParts1Of[_projectId][_domain][_group][_i];\n\n // Populate the split struct.\n JBSplit memory _split;\n\n // prefer claimed in bit 0.\n _split.preferClaimed = _packedSplitPart1 & 1 == 1;\n // prefer add to balance in bit 1.\n _split.preferAddToBalance = (_packedSplitPart1 >> 1) & 1 == 1;\n // percent in bits 2-33.\n _split.percent = uint256(uint32(_packedSplitPart1 >> 2));\n // projectId in bits 32-89.\n _split.projectId = uint256(uint56(_packedSplitPart1 >> 34));\n // beneficiary in bits 90-249.\n _split.beneficiary = payable(address(uint160(_packedSplitPart1 >> 90)));\n\n // Get a reference to the second packed data.\n uint256 _packedSplitPart2 = _packedSplitParts2Of[_projectId][_domain][_group][_i];\n\n // If there's anything in it, unpack.\n if (_packedSplitPart2 > 0) {\n // lockedUntil in bits 0-47.\n _split.lockedUntil = uint256(uint48(_packedSplitPart2));\n // allocator in bits 48-207.\n _split.allocator = IJBSplitAllocator(address(uint160(_packedSplitPart2 >> 48)));\n }\n\n // Add the split to the value being returned.\n _splits[_i] = _split;\n\n unchecked {\n ++_i;\n }\n }\n\n return _splits;\n }\n}\n" diff --git a/deployments/mainnet/JBETHERC20ProjectPayerDeployer.json b/deployments/mainnet/JBETHERC20ProjectPayerDeployer.json index 2ebfbc5e7..e7f8fed78 100644 --- a/deployments/mainnet/JBETHERC20ProjectPayerDeployer.json +++ b/deployments/mainnet/JBETHERC20ProjectPayerDeployer.json @@ -165,11 +165,11 @@ ], "numDeployments": 1, "solcInputHash": "e87fd161fb98793b8dd4dcaee81afb88", - "metadata": "{\"compiler\":{\"version\":\"0.8.16+commit.07a7930e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IJBDirectory\",\"name\":\"_directory\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IJBProjectPayer\",\"name\":\"projectPayer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"defaultProjectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"defaultBeneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"defaultPreferClaimedTokens\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"defaultMemo\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"defaultMetadata\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"preferAddToBalance\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"contract IJBDirectory\",\"name\":\"directory\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"DeployProjectPayer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_defaultProjectId\",\"type\":\"uint256\"},{\"internalType\":\"address payable\",\"name\":\"_defaultBeneficiary\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_defaultPreferClaimedTokens\",\"type\":\"bool\"},{\"internalType\":\"string\",\"name\":\"_defaultMemo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_defaultMetadata\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"_defaultPreferAddToBalance\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"deployProjectPayer\",\"outputs\":[{\"internalType\":\"contract IJBProjectPayer\",\"name\":\"projectPayer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Adheres to - IJBETHERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_directory\":\"A contract storing directories of terminals and controllers for each project.\"}},\"deployProjectPayer(uint256,address,bool,string,bytes,bool,address)\":{\"params\":{\"_defaultBeneficiary\":\"The address that'll receive the project's tokens when the project payer receives payments. \",\"_defaultMemo\":\"The memo that'll be forwarded with the project payer's received payments. \",\"_defaultMetadata\":\"The metadata that'll be forwarded with the project payer's received payments. \",\"_defaultPreferAddToBalance\":\"A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\",\"_defaultPreferClaimedTokens\":\"A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \",\"_defaultProjectId\":\"The ID of the project whose treasury should be forwarded the project payer contract's received payments.\",\"_owner\":\"The address that will own the project payer.\"},\"returns\":{\"projectPayer\":\"The project payer contract.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"deployProjectPayer(uint256,address,bool,string,bytes,bool,address)\":{\"notice\":\" Allows anyone to deploy a new project payer contract.\"}},\"notice\":\" Deploys project payer contracts.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/JBETHERC20ProjectPayerDeployer.sol\":\"JBETHERC20ProjectPayerDeployer\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0x24e0364e503a9bbde94c715d26573a76f14cd2a202d45f96f52134ab806b67b9\",\"license\":\"MIT\"},\"@openzeppelin/contracts/proxy/Clones.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/Clones.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for\\n * deploying minimal proxy contracts, also known as \\\"clones\\\".\\n *\\n * > To simply and cheaply clone contract functionality in an immutable way, this standard specifies\\n * > a minimal bytecode implementation that delegates all calls to a known, fixed address.\\n *\\n * The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2`\\n * (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the\\n * deterministic method.\\n *\\n * _Available since v3.4._\\n */\\nlibrary Clones {\\n /**\\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.\\n *\\n * This function uses the create opcode, which should never revert.\\n */\\n function clone(address implementation) internal returns (address instance) {\\n assembly {\\n let ptr := mload(0x40)\\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\\n mstore(add(ptr, 0x14), shl(0x60, implementation))\\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\\n instance := create(0, ptr, 0x37)\\n }\\n require(instance != address(0), \\\"ERC1167: create failed\\\");\\n }\\n\\n /**\\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.\\n *\\n * This function uses the create2 opcode and a `salt` to deterministically deploy\\n * the clone. Using the same `implementation` and `salt` multiple time will revert, since\\n * the clones cannot be deployed twice at the same address.\\n */\\n function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) {\\n assembly {\\n let ptr := mload(0x40)\\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\\n mstore(add(ptr, 0x14), shl(0x60, implementation))\\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\\n instance := create2(0, ptr, 0x37, salt)\\n }\\n require(instance != address(0), \\\"ERC1167: create2 failed\\\");\\n }\\n\\n /**\\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\\n */\\n function predictDeterministicAddress(\\n address implementation,\\n bytes32 salt,\\n address deployer\\n ) internal pure returns (address predicted) {\\n assembly {\\n let ptr := mload(0x40)\\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\\n mstore(add(ptr, 0x14), shl(0x60, implementation))\\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf3ff00000000000000000000000000000000)\\n mstore(add(ptr, 0x38), shl(0x60, deployer))\\n mstore(add(ptr, 0x4c), salt)\\n mstore(add(ptr, 0x6c), keccak256(ptr, 0x37))\\n predicted := keccak256(add(ptr, 0x37), 0x55)\\n }\\n }\\n\\n /**\\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\\n */\\n function predictDeterministicAddress(address implementation, bytes32 salt)\\n internal\\n view\\n returns (address predicted)\\n {\\n return predictDeterministicAddress(implementation, salt, address(this));\\n }\\n}\\n\",\"keccak256\":\"0x1cc0efb01cbf008b768fd7b334786a6e358809198bb7e67f1c530af4957c6a21\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address sender,\\n address recipient,\\n uint256 amount\\n ) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0x61437cb513a887a1bbad006e7b1c8b414478427d33de47c5600af3c748f108da\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(\\n IERC20 token,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(\\n IERC20 token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) {\\n // Return data is optional\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xc3d946432c0ddbb1f846a0d3985be71299df331b91d06732152117f62f0be2b5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool _approved) external;\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x516a22876c1fab47f49b1bc22b4614491cd05338af8bd2e7b382da090a079990\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3777e696b62134e6177440dbe6e6601c0c156a443f57167194b67e75527439de\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"contracts/JBETHERC20ProjectPayer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport '@openzeppelin/contracts/access/Ownable.sol';\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\\nimport './interfaces/IJBProjectPayer.sol';\\nimport './libraries/JBTokens.sol';\\n\\n/** \\n @notice \\n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\\n\\n @dev\\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\\n\\n @dev\\n Adheres to -\\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n\\n @dev\\n Inherits from -\\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\\n ERC165: Introspection on interface adherance. \\n*/\\ncontract JBETHERC20ProjectPayer is Ownable, ERC165, IJBProjectPayer {\\n using SafeERC20 for IERC20;\\n\\n //*********************************************************************//\\n // -------------------------- custom errors -------------------------- //\\n //*********************************************************************//\\n error INCORRECT_DECIMAL_AMOUNT();\\n error ALREADY_INITIALIZED();\\n error NO_MSG_VALUE_ALLOWED();\\n error TERMINAL_NOT_FOUND();\\n\\n //*********************************************************************//\\n // ------------------- public immutable properties ------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice \\n A contract storing directories of terminals and controllers for each project.\\n */\\n IJBDirectory public immutable override directory;\\n\\n /**\\n @notice \\n The deployer associated with this implementation. Used to rule out double initialization.\\n */\\n address public immutable override projectPayerDeployer;\\n\\n //*********************************************************************//\\n // --------------------- public stored properties -------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n The ID of the project that should be used to forward this contract's received payments.\\n */\\n uint256 public override defaultProjectId;\\n\\n /** \\n @notice \\n The beneficiary that should be used in the payment made when this contract receives payments.\\n */\\n address payable public override defaultBeneficiary;\\n\\n /** \\n @notice \\n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\\n */\\n bool public override defaultPreferClaimedTokens;\\n\\n /** \\n @notice \\n The memo that should be used in the payment made when this contract receives payments.\\n */\\n string public override defaultMemo;\\n\\n /** \\n @notice \\n The metadata that should be used in the payment made when this contract receives payments.\\n */\\n bytes public override defaultMetadata;\\n\\n /**\\n @notice \\n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\\n */\\n bool public override defaultPreferAddToBalance;\\n\\n //*********************************************************************//\\n // ------------------------- public views ---------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Indicates if this contract adheres to the specified interface.\\n\\n @dev \\n See {IERC165-supportsInterface}.\\n\\n @param _interfaceId The ID of the interface to check for adherance to.\\n */\\n function supportsInterface(bytes4 _interfaceId)\\n public\\n view\\n virtual\\n override(ERC165, IERC165)\\n returns (bool)\\n {\\n return\\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\\n }\\n\\n //*********************************************************************//\\n // -------------------------- constructors --------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @dev This is the constructor of the implementation. The directory is shared between project payers and is\\n immutable. If a new JBDirectory is needed, a new JBProjectPayerDeployer should be deployed.\\n @param _directory A contract storing directories of terminals and controllers for each project.\\n */\\n constructor(IJBDirectory _directory) {\\n directory = _directory;\\n projectPayerDeployer = msg.sender;\\n }\\n\\n /** \\n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\\n @param _defaultBeneficiary The address that'll receive the project's tokens. \\n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \\n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\\n @param _owner The address that will own the contract.\\n */\\n function initialize(\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string memory _defaultMemo,\\n bytes memory _defaultMetadata,\\n bool _defaultPreferAddToBalance,\\n address _owner\\n ) public {\\n if(msg.sender != projectPayerDeployer) revert ALREADY_INITIALIZED();\\n\\n defaultProjectId = _defaultProjectId;\\n defaultBeneficiary = _defaultBeneficiary;\\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\\n defaultMemo = _defaultMemo;\\n defaultMetadata = _defaultMetadata;\\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\\n _transferOwnership(_owner);\\n }\\n\\n //*********************************************************************//\\n // ------------------------- default receive ------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Received funds are paid to the default project ID using the stored default properties.\\n\\n @dev\\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\\n\\n @dev\\n This function is called automatically when the contract receives an ETH payment.\\n */\\n receive() external payable virtual override {\\n if (defaultPreferAddToBalance)\\n _addToBalanceOf(\\n defaultProjectId,\\n JBTokens.ETH,\\n address(this).balance,\\n 18, // balance is a fixed point number with 18 decimals.\\n defaultMemo,\\n defaultMetadata\\n );\\n else\\n _pay(\\n defaultProjectId,\\n JBTokens.ETH,\\n address(this).balance,\\n 18, // balance is a fixed point number with 18 decimals.\\n defaultBeneficiary == address(0) ? tx.origin : defaultBeneficiary,\\n 0, // Can't determine expectation of returned tokens ahead of time.\\n defaultPreferClaimedTokens,\\n defaultMemo,\\n defaultMetadata\\n );\\n }\\n\\n //*********************************************************************//\\n // ---------------------- external transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\\n\\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\\n @param _beneficiary The address that'll receive the project's tokens. \\n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \\n @param _memo The memo that'll be used. \\n @param _metadata The metadata that'll be sent. \\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\\n */\\n function setDefaultValues(\\n uint256 _projectId,\\n address payable _beneficiary,\\n bool _preferClaimedTokens,\\n string memory _memo,\\n bytes memory _metadata,\\n bool _defaultPreferAddToBalance\\n ) external virtual override onlyOwner {\\n // Set the default project ID if it has changed.\\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\\n\\n // Set the default beneficiary if it has changed.\\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\\n\\n // Set the default claimed token preference if it has changed.\\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\\n defaultPreferClaimedTokens = _preferClaimedTokens;\\n\\n // Set the default memo if it has changed.\\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\\n defaultMemo = _memo;\\n\\n // Set the default metadata if it has changed.\\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\\n defaultMetadata = _metadata;\\n\\n // Set the add to balance preference if it has changed.\\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\\n\\n emit SetDefaultValues(\\n _projectId,\\n _beneficiary,\\n _preferClaimedTokens,\\n _memo,\\n _metadata,\\n _defaultPreferAddToBalance,\\n msg.sender\\n );\\n }\\n\\n //*********************************************************************//\\n // ----------------------- public transactions ----------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n Make a payment to the specified project.\\n\\n @param _projectId The ID of the project that is being paid.\\n @param _token The token being paid in.\\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\\n @param _beneficiary The address who will receive tokens from the payment.\\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\\n */\\n function pay(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) public payable virtual override {\\n // ETH shouldn't be sent if the token isn't ETH.\\n if (address(_token) != JBTokens.ETH) {\\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\\n\\n // Get a reference to the balance before receiving tokens.\\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\\n\\n // Transfer tokens to this contract from the msg sender.\\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\\n\\n // The amount should reflect the change in balance.\\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\\n } else {\\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\\n _amount = msg.value;\\n _decimals = 18;\\n }\\n\\n _pay(\\n _projectId,\\n _token,\\n _amount,\\n _decimals,\\n _beneficiary,\\n _minReturnedTokens,\\n _preferClaimedTokens,\\n _memo,\\n _metadata\\n );\\n }\\n\\n /** \\n @notice \\n Add to the balance of the specified project.\\n\\n @param _projectId The ID of the project that is being paid.\\n @param _token The token being paid in.\\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Extra data to pass along to the terminal.\\n */\\n function addToBalanceOf(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) public payable virtual override {\\n // ETH shouldn't be sent if the token isn't ETH.\\n if (address(_token) != JBTokens.ETH) {\\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\\n\\n // Get a reference to the balance before receiving tokens.\\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\\n\\n // Transfer tokens to this contract from the msg sender.\\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\\n\\n // The amount should reflect the change in balance.\\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\\n } else {\\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\\n _amount = msg.value;\\n _decimals = 18;\\n }\\n\\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\\n }\\n\\n //*********************************************************************//\\n // ---------------------- internal transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n Make a payment to the specified project.\\n\\n @param _projectId The ID of the project that is being paid.\\n @param _token The token being paid in.\\n @param _amount The amount of tokens being paid, as a fixed point number. \\n @param _decimals The number of decimals in the `_amount` fixed point number. \\n @param _beneficiary The address who will receive tokens from the payment.\\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _metadata Bytes to send along to the data source and delegate, if provided.\\n */\\n function _pay(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string memory _memo,\\n bytes memory _metadata\\n ) internal virtual {\\n // Find the terminal for the specified project.\\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\\n\\n // There must be a terminal.\\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\\n\\n // The amount's decimals must match the terminal's expected decimals.\\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\\n\\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\\n if (_token != JBTokens.ETH) IERC20(_token).safeApprove(address(_terminal), _amount);\\n\\n // If the token is ETH, send it in msg.value.\\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\\n\\n // Send funds to the terminal.\\n // If the token is ETH, send it in msg.value.\\n _terminal.pay{value: _payableValue}(\\n _projectId,\\n _amount, // ignored if the token is JBTokens.ETH.\\n _token,\\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\\n ? defaultBeneficiary\\n : tx.origin,\\n _minReturnedTokens,\\n _preferClaimedTokens,\\n _memo,\\n _metadata\\n );\\n }\\n\\n /** \\n @notice \\n Add to the balance of the specified project.\\n\\n @param _projectId The ID of the project that is being paid.\\n @param _token The token being paid in.\\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Extra data to pass along to the terminal.\\n */\\n function _addToBalanceOf(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n string memory _memo,\\n bytes memory _metadata\\n ) internal virtual {\\n // Find the terminal for the specified project.\\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\\n\\n // There must be a terminal.\\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\\n\\n // The amount's decimals must match the terminal's expected decimals.\\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\\n\\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\\n if (_token != JBTokens.ETH) IERC20(_token).safeApprove(address(_terminal), _amount);\\n\\n // If the token is ETH, send it in msg.value.\\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\\n\\n // Add to balance so tokens don't get issued.\\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\\n }\\n}\\n\",\"keccak256\":\"0xcbadf8e217bb9c43d18161ce576235277834988ea7cb51d58b5a794914e9156c\",\"license\":\"MIT\"},\"contracts/JBETHERC20ProjectPayerDeployer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport { Clones } from '@openzeppelin/contracts/proxy/Clones.sol';\\n\\nimport './interfaces/IJBETHERC20ProjectPayerDeployer.sol';\\nimport './JBETHERC20ProjectPayer.sol';\\n\\n/** \\n @notice \\n Deploys project payer contracts.\\n\\n @dev\\n Adheres to -\\n IJBETHERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n*/\\ncontract JBETHERC20ProjectPayerDeployer is IJBETHERC20ProjectPayerDeployer {\\n\\n address immutable implementation;\\n\\n IJBDirectory immutable directory;\\n\\n /**\\n @param _directory A contract storing directories of terminals and controllers for each project.\\n */\\n constructor(IJBDirectory _directory) {\\n implementation = address(new JBETHERC20ProjectPayer(_directory));\\n directory = _directory;\\n }\\n\\n //*********************************************************************//\\n // ---------------------- external transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n Allows anyone to deploy a new project payer contract.\\n\\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the project payer contract's received payments.\\n @param _defaultBeneficiary The address that'll receive the project's tokens when the project payer receives payments. \\n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \\n @param _defaultMemo The memo that'll be forwarded with the project payer's received payments. \\n @param _defaultMetadata The metadata that'll be forwarded with the project payer's received payments. \\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\\n @param _owner The address that will own the project payer.\\n\\n @return projectPayer The project payer contract.\\n */\\n function deployProjectPayer(\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string memory _defaultMemo,\\n bytes memory _defaultMetadata,\\n bool _defaultPreferAddToBalance,\\n address _owner\\n ) external override returns (IJBProjectPayer projectPayer) {\\n // Deploy the project payer.\\n projectPayer = IJBProjectPayer(payable(Clones.clone(implementation)));\\n\\n // Initialize the project payer.\\n projectPayer.initialize(\\n _defaultProjectId,\\n _defaultBeneficiary,\\n _defaultPreferClaimedTokens,\\n _defaultMemo,\\n _defaultMetadata,\\n _defaultPreferAddToBalance,\\n _owner\\n );\\n\\n emit DeployProjectPayer(\\n projectPayer,\\n _defaultProjectId,\\n _defaultBeneficiary,\\n _defaultPreferClaimedTokens,\\n _defaultMemo,\\n _defaultMetadata,\\n _defaultPreferAddToBalance,\\n directory,\\n _owner,\\n msg.sender\\n );\\n }\\n}\\n\",\"keccak256\":\"0xe8aac15e115cad48d4a84437f4415e8e6852855bba9062a1d2eff6848b83c44f\",\"license\":\"MIT\"},\"contracts/enums/JBBallotState.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nenum JBBallotState {\\n Active,\\n Approved,\\n Failed\\n}\\n\",\"keccak256\":\"0x891fcac63470398b3a11239da7feba6b07d640809fcefd2404303b823d7378f8\",\"license\":\"MIT\"},\"contracts/interfaces/IJBDirectory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBProjects.sol';\\n\\ninterface IJBDirectory {\\n event SetController(uint256 indexed projectId, address indexed controller, address caller);\\n\\n event AddTerminal(uint256 indexed projectId, IJBPaymentTerminal indexed terminal, address caller);\\n\\n event SetTerminals(uint256 indexed projectId, IJBPaymentTerminal[] terminals, address caller);\\n\\n event SetPrimaryTerminal(\\n uint256 indexed projectId,\\n address indexed token,\\n IJBPaymentTerminal indexed terminal,\\n address caller\\n );\\n\\n event SetIsAllowedToSetFirstController(address indexed addr, bool indexed flag, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function controllerOf(uint256 _projectId) external view returns (address);\\n\\n function isAllowedToSetFirstController(address _address) external view returns (bool);\\n\\n function terminalsOf(uint256 _projectId) external view returns (IJBPaymentTerminal[] memory);\\n\\n function isTerminalOf(uint256 _projectId, IJBPaymentTerminal _terminal)\\n external\\n view\\n returns (bool);\\n\\n function primaryTerminalOf(uint256 _projectId, address _token)\\n external\\n view\\n returns (IJBPaymentTerminal);\\n\\n function setControllerOf(uint256 _projectId, address _controller) external;\\n\\n function setTerminalsOf(uint256 _projectId, IJBPaymentTerminal[] calldata _terminals) external;\\n\\n function setPrimaryTerminalOf(\\n uint256 _projectId,\\n address _token,\\n IJBPaymentTerminal _terminal\\n ) external;\\n\\n function setIsAllowedToSetFirstController(address _address, bool _flag) external;\\n}\\n\",\"keccak256\":\"0x715321646db00514d1355ed43c40cd3f01e94959552fd07797b315d9c49cdb1d\",\"license\":\"MIT\"},\"contracts/interfaces/IJBETHERC20ProjectPayerDeployer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBDirectory.sol';\\nimport './IJBProjectPayer.sol';\\n\\ninterface IJBETHERC20ProjectPayerDeployer {\\n event DeployProjectPayer(\\n IJBProjectPayer indexed projectPayer,\\n uint256 defaultProjectId,\\n address defaultBeneficiary,\\n bool defaultPreferClaimedTokens,\\n string defaultMemo,\\n bytes defaultMetadata,\\n bool preferAddToBalance,\\n IJBDirectory directory,\\n address owner,\\n address caller\\n );\\n\\n function deployProjectPayer(\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string memory _defaultMemo,\\n bytes memory _defaultMetadata,\\n bool _preferAddToBalance,\\n address _owner\\n ) external returns (IJBProjectPayer projectPayer);\\n}\\n\",\"keccak256\":\"0x69b364b5e637bc641d453d30aa66b8b8a8f024e0117c892246367344a1d12e64\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleBallot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../enums/JBBallotState.sol';\\n\\ninterface IJBFundingCycleBallot is IERC165 {\\n function duration() external view returns (uint256);\\n\\n function stateOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n uint256 _start\\n ) external view returns (JBBallotState);\\n}\\n\",\"keccak256\":\"0x49553a56209237846bc400cf27f260824a6bd06fd8094a7eb5abb9de75779598\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../enums/JBBallotState.sol';\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBFundingCycleData.sol';\\n\\ninterface IJBFundingCycleStore {\\n event Configure(\\n uint256 indexed configuration,\\n uint256 indexed projectId,\\n JBFundingCycleData data,\\n uint256 metadata,\\n uint256 mustStartAtOrAfter,\\n address caller\\n );\\n\\n event Init(uint256 indexed configuration, uint256 indexed projectId, uint256 indexed basedOn);\\n\\n function latestConfigurationOf(uint256 _projectId) external view returns (uint256);\\n\\n function get(uint256 _projectId, uint256 _configuration)\\n external\\n view\\n returns (JBFundingCycle memory);\\n\\n function latestConfiguredOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBBallotState ballotState);\\n\\n function queuedOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentBallotStateOf(uint256 _projectId) external view returns (JBBallotState);\\n\\n function configureFor(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n uint256 _metadata,\\n uint256 _mustStartAtOrAfter\\n ) external returns (JBFundingCycle memory fundingCycle);\\n}\\n\",\"keccak256\":\"0xaead823851433be0c2ddc8f8086813e6cd647de3a1bc0f7570a5d6b38c378b5a\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\n\\ninterface IJBPaymentTerminal is IERC165 {\\n function acceptsToken(address _token, uint256 _projectId) external view returns (bool);\\n\\n function currencyForToken(address _token) external view returns (uint256);\\n\\n function decimalsForToken(address _token) external view returns (uint256);\\n\\n // Return value must be a fixed point number with 18 decimals.\\n function currentEthOverflowOf(uint256 _projectId) external view returns (uint256);\\n\\n function pay(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable returns (uint256 beneficiaryTokenCount);\\n\\n function addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable;\\n}\\n\",\"keccak256\":\"0xb7826f5ed609359ce322c09e83236c47ba385df1c3cad3607e56fd0a2e00eee2\",\"license\":\"MIT\"},\"contracts/interfaces/IJBProjectPayer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './IJBDirectory.sol';\\n\\ninterface IJBProjectPayer is IERC165 {\\n event SetDefaultValues(\\n uint256 indexed projectId,\\n address indexed beneficiary,\\n bool preferClaimedTokens,\\n string memo,\\n bytes metadata,\\n bool preferAddToBalance,\\n address caller\\n );\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function projectPayerDeployer() external view returns (address);\\n\\n function defaultProjectId() external view returns (uint256);\\n\\n function defaultBeneficiary() external view returns (address payable);\\n\\n function defaultPreferClaimedTokens() external view returns (bool);\\n\\n function defaultMemo() external view returns (string memory);\\n\\n function defaultMetadata() external view returns (bytes memory);\\n\\n function defaultPreferAddToBalance() external view returns (bool);\\n\\n function initialize(\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string memory _defaultMemo,\\n bytes memory _defaultMetadata,\\n bool _defaultPreferAddToBalance,\\n address _owner\\n ) external;\\n\\n function setDefaultValues(\\n uint256 _projectId,\\n address payable _beneficiary,\\n bool _preferClaimedTokens,\\n string memory _memo,\\n bytes memory _metadata,\\n bool _defaultPreferAddToBalance\\n ) external;\\n\\n function pay(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string memory _memo,\\n bytes memory _metadata\\n ) external payable;\\n\\n function addToBalanceOf(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n string memory _memo,\\n bytes memory _metadata\\n ) external payable;\\n\\n receive() external payable;\\n}\\n\",\"keccak256\":\"0x85f4cbd5482e26618994f742c149a5bd3cb3dc39dbeba85b21c36b3215007df6\",\"license\":\"MIT\"},\"contracts/interfaces/IJBProjects.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBTokenUriResolver.sol';\\n\\ninterface IJBProjects is IERC721 {\\n event Create(\\n uint256 indexed projectId,\\n address indexed owner,\\n JBProjectMetadata metadata,\\n address caller\\n );\\n\\n event SetMetadata(uint256 indexed projectId, JBProjectMetadata metadata, address caller);\\n\\n event SetTokenUriResolver(IJBTokenUriResolver indexed resolver, address caller);\\n\\n function count() external view returns (uint256);\\n\\n function metadataContentOf(uint256 _projectId, uint256 _domain)\\n external\\n view\\n returns (string memory);\\n\\n function tokenUriResolver() external view returns (IJBTokenUriResolver);\\n\\n function createFor(address _owner, JBProjectMetadata calldata _metadata)\\n external\\n returns (uint256 projectId);\\n\\n function setMetadataOf(uint256 _projectId, JBProjectMetadata calldata _metadata) external;\\n\\n function setTokenUriResolver(IJBTokenUriResolver _newResolver) external;\\n}\\n\",\"keccak256\":\"0x7cfc021d0bd7e73b1ba8f4845d7d35e3419d6a14d3d25ca3a8010e7f91062fe4\",\"license\":\"MIT\"},\"contracts/interfaces/IJBTokenUriResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBTokenUriResolver {\\n function getUri(uint256 _projectId) external view returns (string memory tokenUri);\\n}\\n\",\"keccak256\":\"0xd267fd8ca7c21c2c71794acdb9a98314c33a35fc559e0bf0897a6686d196d174\",\"license\":\"MIT\"},\"contracts/libraries/JBTokens.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBTokens {\\n /** \\n @notice \\n The ETH token address in Juicebox is represented by 0x000000000000000000000000000000000000EEEe.\\n */\\n address public constant ETH = address(0x000000000000000000000000000000000000EEEe);\\n}\\n\",\"keccak256\":\"0xecf82992f7b827766aa55f16872517a646521eef414d8cc9786617ea377e5463\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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.\\n @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.\\n @member basedOn The `configuration` of the funding cycle that was active when this cycle was created.\\n @member start The timestamp marking the moment from which the funding cycle is considered active. It is a unix timestamp measured in seconds.\\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n @member metadata Extra data that can be associated with a funding cycle.\\n*/\\nstruct JBFundingCycle {\\n uint256 number;\\n uint256 configuration;\\n uint256 basedOn;\\n uint256 start;\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n uint256 metadata;\\n}\\n\",\"keccak256\":\"0xcdd3ac9b6fa67e62ada88d09b73bc35ade1cd77d43db712289266a788928b4c2\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycleData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n*/\\nstruct JBFundingCycleData {\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n}\\n\",\"keccak256\":\"0x2aa6368bf4dfc5797e8b02a978293de0c777fae2658de2c825a103587240f3b0\",\"license\":\"MIT\"},\"contracts/structs/JBProjectMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member content The metadata content.\\n @member domain The domain within which the metadata applies.\\n*/\\nstruct JBProjectMetadata {\\n string content;\\n uint256 domain;\\n}\\n\",\"keccak256\":\"0x90ad7b1014c0a9f945fe7a2efde9d5de41e40574fa27969070b1d2ff52033ea0\",\"license\":\"MIT\"}},\"version\":1}", + "metadata": "{\"compiler\":{\"version\":\"0.8.16+commit.07a7930e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IJBDirectory\",\"name\":\"_directory\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IJBProjectPayer\",\"name\":\"projectPayer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"defaultProjectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"defaultBeneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"defaultPreferClaimedTokens\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"defaultMemo\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"defaultMetadata\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"preferAddToBalance\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"contract IJBDirectory\",\"name\":\"directory\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"DeployProjectPayer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_defaultProjectId\",\"type\":\"uint256\"},{\"internalType\":\"address payable\",\"name\":\"_defaultBeneficiary\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_defaultPreferClaimedTokens\",\"type\":\"bool\"},{\"internalType\":\"string\",\"name\":\"_defaultMemo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_defaultMetadata\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"_defaultPreferAddToBalance\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"deployProjectPayer\",\"outputs\":[{\"internalType\":\"contract IJBProjectPayer\",\"name\":\"projectPayer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Adheres to - IJBGasTokenERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_directory\":\"A contract storing directories of terminals and controllers for each project.\"}},\"deployProjectPayer(uint256,address,bool,string,bytes,bool,address)\":{\"params\":{\"_defaultBeneficiary\":\"The address that'll receive the project's tokens when the project payer receives payments. \",\"_defaultMemo\":\"The memo that'll be forwarded with the project payer's received payments. \",\"_defaultMetadata\":\"The metadata that'll be forwarded with the project payer's received payments. \",\"_defaultPreferAddToBalance\":\"A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\",\"_defaultPreferClaimedTokens\":\"A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \",\"_defaultProjectId\":\"The ID of the project whose treasury should be forwarded the project payer contract's received payments.\",\"_owner\":\"The address that will own the project payer.\"},\"returns\":{\"projectPayer\":\"The project payer contract.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"deployProjectPayer(uint256,address,bool,string,bytes,bool,address)\":{\"notice\":\" Allows anyone to deploy a new project payer contract.\"}},\"notice\":\" Deploys project payer contracts.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/JBGasTokenERC20ProjectPayerDeployer.sol\":\"JBGasTokenERC20ProjectPayerDeployer\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0x24e0364e503a9bbde94c715d26573a76f14cd2a202d45f96f52134ab806b67b9\",\"license\":\"MIT\"},\"@openzeppelin/contracts/proxy/Clones.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/Clones.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for\\n * deploying minimal proxy contracts, also known as \\\"clones\\\".\\n *\\n * > To simply and cheaply clone contract functionality in an immutable way, this standard specifies\\n * > a minimal bytecode implementation that delegates all calls to a known, fixed address.\\n *\\n * The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2`\\n * (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the\\n * deterministic method.\\n *\\n * _Available since v3.4._\\n */\\nlibrary Clones {\\n /**\\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.\\n *\\n * This function uses the create opcode, which should never revert.\\n */\\n function clone(address implementation) internal returns (address instance) {\\n assembly {\\n let ptr := mload(0x40)\\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\\n mstore(add(ptr, 0x14), shl(0x60, implementation))\\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\\n instance := create(0, ptr, 0x37)\\n }\\n require(instance != address(0), \\\"ERC1167: create failed\\\");\\n }\\n\\n /**\\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.\\n *\\n * This function uses the create2 opcode and a `salt` to deterministically deploy\\n * the clone. Using the same `implementation` and `salt` multiple time will revert, since\\n * the clones cannot be deployed twice at the same address.\\n */\\n function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) {\\n assembly {\\n let ptr := mload(0x40)\\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\\n mstore(add(ptr, 0x14), shl(0x60, implementation))\\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\\n instance := create2(0, ptr, 0x37, salt)\\n }\\n require(instance != address(0), \\\"ERC1167: create2 failed\\\");\\n }\\n\\n /**\\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\\n */\\n function predictDeterministicAddress(\\n address implementation,\\n bytes32 salt,\\n address deployer\\n ) internal pure returns (address predicted) {\\n assembly {\\n let ptr := mload(0x40)\\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\\n mstore(add(ptr, 0x14), shl(0x60, implementation))\\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf3ff00000000000000000000000000000000)\\n mstore(add(ptr, 0x38), shl(0x60, deployer))\\n mstore(add(ptr, 0x4c), salt)\\n mstore(add(ptr, 0x6c), keccak256(ptr, 0x37))\\n predicted := keccak256(add(ptr, 0x37), 0x55)\\n }\\n }\\n\\n /**\\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\\n */\\n function predictDeterministicAddress(address implementation, bytes32 salt)\\n internal\\n view\\n returns (address predicted)\\n {\\n return predictDeterministicAddress(implementation, salt, address(this));\\n }\\n}\\n\",\"keccak256\":\"0x1cc0efb01cbf008b768fd7b334786a6e358809198bb7e67f1c530af4957c6a21\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address sender,\\n address recipient,\\n uint256 amount\\n ) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0x61437cb513a887a1bbad006e7b1c8b414478427d33de47c5600af3c748f108da\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(\\n IERC20 token,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(\\n IERC20 token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) {\\n // Return data is optional\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xc3d946432c0ddbb1f846a0d3985be71299df331b91d06732152117f62f0be2b5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool _approved) external;\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x516a22876c1fab47f49b1bc22b4614491cd05338af8bd2e7b382da090a079990\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3777e696b62134e6177440dbe6e6601c0c156a443f57167194b67e75527439de\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"contracts/JBGasTokenERC20ProjectPayer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport '@openzeppelin/contracts/access/Ownable.sol';\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\\nimport './interfaces/IJBProjectPayer.sol';\\nimport './libraries/JBTokens.sol';\\n\\n/** \\n @notice \\n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\\n\\n @dev\\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\\n\\n @dev\\n Adheres to -\\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n\\n @dev\\n Inherits from -\\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\\n ERC165: Introspection on interface adherance. \\n*/\\ncontract JBGasTokenERC20ProjectPayer is Ownable, ERC165, IJBProjectPayer {\\n using SafeERC20 for IERC20;\\n\\n //*********************************************************************//\\n // -------------------------- custom errors -------------------------- //\\n //*********************************************************************//\\n error INCORRECT_DECIMAL_AMOUNT();\\n error ALREADY_INITIALIZED();\\n error NO_MSG_VALUE_ALLOWED();\\n error TERMINAL_NOT_FOUND();\\n\\n //*********************************************************************//\\n // ------------------- public immutable properties ------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice \\n A contract storing directories of terminals and controllers for each project.\\n */\\n IJBDirectory public immutable override directory;\\n\\n /**\\n @notice \\n The deployer associated with this implementation. Used to rule out double initialization.\\n */\\n address public immutable override projectPayerDeployer;\\n\\n //*********************************************************************//\\n // --------------------- public stored properties -------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n The ID of the project that should be used to forward this contract's received payments.\\n */\\n uint256 public override defaultProjectId;\\n\\n /** \\n @notice \\n The beneficiary that should be used in the payment made when this contract receives payments.\\n */\\n address payable public override defaultBeneficiary;\\n\\n /** \\n @notice \\n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\\n */\\n bool public override defaultPreferClaimedTokens;\\n\\n /** \\n @notice \\n The memo that should be used in the payment made when this contract receives payments.\\n */\\n string public override defaultMemo;\\n\\n /** \\n @notice \\n The metadata that should be used in the payment made when this contract receives payments.\\n */\\n bytes public override defaultMetadata;\\n\\n /**\\n @notice \\n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\\n */\\n bool public override defaultPreferAddToBalance;\\n\\n //*********************************************************************//\\n // ------------------------- public views ---------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Indicates if this contract adheres to the specified interface.\\n\\n @dev \\n See {IERC165-supportsInterface}.\\n\\n @param _interfaceId The ID of the interface to check for adherance to.\\n */\\n function supportsInterface(bytes4 _interfaceId)\\n public\\n view\\n virtual\\n override(ERC165, IERC165)\\n returns (bool)\\n {\\n return\\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\\n }\\n\\n //*********************************************************************//\\n // -------------------------- constructors --------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @dev This is the constructor of the implementation. The directory is shared between project payers and is\\n immutable. If a new JBDirectory is needed, a new JBProjectPayerDeployer should be deployed.\\n @param _directory A contract storing directories of terminals and controllers for each project.\\n */\\n constructor(IJBDirectory _directory) {\\n directory = _directory;\\n projectPayerDeployer = msg.sender;\\n }\\n\\n /** \\n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\\n @param _defaultBeneficiary The address that'll receive the project's tokens. \\n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \\n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\\n @param _owner The address that will own the contract.\\n */\\n function initialize(\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string memory _defaultMemo,\\n bytes memory _defaultMetadata,\\n bool _defaultPreferAddToBalance,\\n address _owner\\n ) public {\\n if(msg.sender != projectPayerDeployer) revert ALREADY_INITIALIZED();\\n\\n defaultProjectId = _defaultProjectId;\\n defaultBeneficiary = _defaultBeneficiary;\\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\\n defaultMemo = _defaultMemo;\\n defaultMetadata = _defaultMetadata;\\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\\n _transferOwnership(_owner);\\n }\\n\\n //*********************************************************************//\\n // ------------------------- default receive ------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Received funds are paid to the default project ID using the stored default properties.\\n\\n @dev\\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\\n\\n @dev\\n This function is called automatically when the contract receives an ETH payment.\\n */\\n receive() external payable virtual override {\\n if (defaultPreferAddToBalance)\\n _addToBalanceOf(\\n defaultProjectId,\\n JBTokens.GAS_TOKEN,\\n address(this).balance,\\n 18, // balance is a fixed point number with 18 decimals.\\n defaultMemo,\\n defaultMetadata\\n );\\n else\\n _pay(\\n defaultProjectId,\\n JBTokens.GAS_TOKEN,\\n address(this).balance,\\n 18, // balance is a fixed point number with 18 decimals.\\n defaultBeneficiary == address(0) ? tx.origin : defaultBeneficiary,\\n 0, // Can't determine expectation of returned tokens ahead of time.\\n defaultPreferClaimedTokens,\\n defaultMemo,\\n defaultMetadata\\n );\\n }\\n\\n //*********************************************************************//\\n // ---------------------- external transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\\n\\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\\n @param _beneficiary The address that'll receive the project's tokens. \\n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \\n @param _memo The memo that'll be used. \\n @param _metadata The metadata that'll be sent. \\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\\n */\\n function setDefaultValues(\\n uint256 _projectId,\\n address payable _beneficiary,\\n bool _preferClaimedTokens,\\n string memory _memo,\\n bytes memory _metadata,\\n bool _defaultPreferAddToBalance\\n ) external virtual override onlyOwner {\\n // Set the default project ID if it has changed.\\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\\n\\n // Set the default beneficiary if it has changed.\\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\\n\\n // Set the default claimed token preference if it has changed.\\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\\n defaultPreferClaimedTokens = _preferClaimedTokens;\\n\\n // Set the default memo if it has changed.\\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\\n defaultMemo = _memo;\\n\\n // Set the default metadata if it has changed.\\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\\n defaultMetadata = _metadata;\\n\\n // Set the add to balance preference if it has changed.\\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\\n\\n emit SetDefaultValues(\\n _projectId,\\n _beneficiary,\\n _preferClaimedTokens,\\n _memo,\\n _metadata,\\n _defaultPreferAddToBalance,\\n msg.sender\\n );\\n }\\n\\n //*********************************************************************//\\n // ----------------------- public transactions ----------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n Make a payment to the specified project.\\n\\n @param _projectId The ID of the project that is being paid.\\n @param _token The token being paid in.\\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\\n @param _beneficiary The address who will receive tokens from the payment.\\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\\n */\\n function pay(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) public payable virtual override {\\n // ETH shouldn't be sent if the token isn't ETH.\\n if (address(_token) != JBTokens.GAS_TOKEN) {\\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\\n\\n // Get a reference to the balance before receiving tokens.\\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\\n\\n // Transfer tokens to this contract from the msg sender.\\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\\n\\n // The amount should reflect the change in balance.\\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\\n } else {\\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\\n _amount = msg.value;\\n _decimals = 18;\\n }\\n\\n _pay(\\n _projectId,\\n _token,\\n _amount,\\n _decimals,\\n _beneficiary,\\n _minReturnedTokens,\\n _preferClaimedTokens,\\n _memo,\\n _metadata\\n );\\n }\\n\\n /** \\n @notice \\n Add to the balance of the specified project.\\n\\n @param _projectId The ID of the project that is being paid.\\n @param _token The token being paid in.\\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Extra data to pass along to the terminal.\\n */\\n function addToBalanceOf(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) public payable virtual override {\\n // ETH shouldn't be sent if the token isn't ETH.\\n if (address(_token) != JBTokens.GAS_TOKEN) {\\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\\n\\n // Get a reference to the balance before receiving tokens.\\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\\n\\n // Transfer tokens to this contract from the msg sender.\\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\\n\\n // The amount should reflect the change in balance.\\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\\n } else {\\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\\n _amount = msg.value;\\n _decimals = 18;\\n }\\n\\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\\n }\\n\\n //*********************************************************************//\\n // ---------------------- internal transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n Make a payment to the specified project.\\n\\n @param _projectId The ID of the project that is being paid.\\n @param _token The token being paid in.\\n @param _amount The amount of tokens being paid, as a fixed point number. \\n @param _decimals The number of decimals in the `_amount` fixed point number. \\n @param _beneficiary The address who will receive tokens from the payment.\\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _metadata Bytes to send along to the data source and delegate, if provided.\\n */\\n function _pay(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string memory _memo,\\n bytes memory _metadata\\n ) internal virtual {\\n // Find the terminal for the specified project.\\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\\n\\n // There must be a terminal.\\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\\n\\n // The amount's decimals must match the terminal's expected decimals.\\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\\n\\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).safeApprove(address(_terminal), _amount);\\n\\n // If the token is ETH, send it in msg.value.\\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\\n\\n // Send funds to the terminal.\\n // If the token is ETH, send it in msg.value.\\n _terminal.pay{value: _payableValue}(\\n _projectId,\\n _amount, // ignored if the token is JBTokens.GAS_TOKEN.\\n _token,\\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\\n ? defaultBeneficiary\\n : tx.origin,\\n _minReturnedTokens,\\n _preferClaimedTokens,\\n _memo,\\n _metadata\\n );\\n }\\n\\n /** \\n @notice \\n Add to the balance of the specified project.\\n\\n @param _projectId The ID of the project that is being paid.\\n @param _token The token being paid in.\\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Extra data to pass along to the terminal.\\n */\\n function _addToBalanceOf(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n string memory _memo,\\n bytes memory _metadata\\n ) internal virtual {\\n // Find the terminal for the specified project.\\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\\n\\n // There must be a terminal.\\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\\n\\n // The amount's decimals must match the terminal's expected decimals.\\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\\n\\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).safeApprove(address(_terminal), _amount);\\n\\n // If the token is ETH, send it in msg.value.\\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\\n\\n // Add to balance so tokens don't get issued.\\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\\n }\\n}\\n\",\"keccak256\":\"0xcbadf8e217bb9c43d18161ce576235277834988ea7cb51d58b5a794914e9156c\",\"license\":\"MIT\"},\"contracts/JBGasTokenERC20ProjectPayerDeployer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport { Clones } from '@openzeppelin/contracts/proxy/Clones.sol';\\n\\nimport './interfaces/IJBGasTokenERC20ProjectPayerDeployer.sol';\\nimport './JBGasTokenERC20ProjectPayer.sol';\\n\\n/** \\n @notice \\n Deploys project payer contracts.\\n\\n @dev\\n Adheres to -\\n IJBGasTokenERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n*/\\ncontract JBGasTokenERC20ProjectPayerDeployer is IJBGasTokenERC20ProjectPayerDeployer {\\n\\n address immutable implementation;\\n\\n IJBDirectory immutable directory;\\n\\n /**\\n @param _directory A contract storing directories of terminals and controllers for each project.\\n */\\n constructor(IJBDirectory _directory) {\\n implementation = address(new JBGasTokenERC20ProjectPayer(_directory));\\n directory = _directory;\\n }\\n\\n //*********************************************************************//\\n // ---------------------- external transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n Allows anyone to deploy a new project payer contract.\\n\\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the project payer contract's received payments.\\n @param _defaultBeneficiary The address that'll receive the project's tokens when the project payer receives payments. \\n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \\n @param _defaultMemo The memo that'll be forwarded with the project payer's received payments. \\n @param _defaultMetadata The metadata that'll be forwarded with the project payer's received payments. \\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\\n @param _owner The address that will own the project payer.\\n\\n @return projectPayer The project payer contract.\\n */\\n function deployProjectPayer(\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string memory _defaultMemo,\\n bytes memory _defaultMetadata,\\n bool _defaultPreferAddToBalance,\\n address _owner\\n ) external override returns (IJBProjectPayer projectPayer) {\\n // Deploy the project payer.\\n projectPayer = IJBProjectPayer(payable(Clones.clone(implementation)));\\n\\n // Initialize the project payer.\\n projectPayer.initialize(\\n _defaultProjectId,\\n _defaultBeneficiary,\\n _defaultPreferClaimedTokens,\\n _defaultMemo,\\n _defaultMetadata,\\n _defaultPreferAddToBalance,\\n _owner\\n );\\n\\n emit DeployProjectPayer(\\n projectPayer,\\n _defaultProjectId,\\n _defaultBeneficiary,\\n _defaultPreferClaimedTokens,\\n _defaultMemo,\\n _defaultMetadata,\\n _defaultPreferAddToBalance,\\n directory,\\n _owner,\\n msg.sender\\n );\\n }\\n}\\n\",\"keccak256\":\"0xe8aac15e115cad48d4a84437f4415e8e6852855bba9062a1d2eff6848b83c44f\",\"license\":\"MIT\"},\"contracts/enums/JBBallotState.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nenum JBBallotState {\\n Active,\\n Approved,\\n Failed\\n}\\n\",\"keccak256\":\"0x891fcac63470398b3a11239da7feba6b07d640809fcefd2404303b823d7378f8\",\"license\":\"MIT\"},\"contracts/interfaces/IJBDirectory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBProjects.sol';\\n\\ninterface IJBDirectory {\\n event SetController(uint256 indexed projectId, address indexed controller, address caller);\\n\\n event AddTerminal(uint256 indexed projectId, IJBPaymentTerminal indexed terminal, address caller);\\n\\n event SetTerminals(uint256 indexed projectId, IJBPaymentTerminal[] terminals, address caller);\\n\\n event SetPrimaryTerminal(\\n uint256 indexed projectId,\\n address indexed token,\\n IJBPaymentTerminal indexed terminal,\\n address caller\\n );\\n\\n event SetIsAllowedToSetFirstController(address indexed addr, bool indexed flag, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function controllerOf(uint256 _projectId) external view returns (address);\\n\\n function isAllowedToSetFirstController(address _address) external view returns (bool);\\n\\n function terminalsOf(uint256 _projectId) external view returns (IJBPaymentTerminal[] memory);\\n\\n function isTerminalOf(uint256 _projectId, IJBPaymentTerminal _terminal)\\n external\\n view\\n returns (bool);\\n\\n function primaryTerminalOf(uint256 _projectId, address _token)\\n external\\n view\\n returns (IJBPaymentTerminal);\\n\\n function setControllerOf(uint256 _projectId, address _controller) external;\\n\\n function setTerminalsOf(uint256 _projectId, IJBPaymentTerminal[] calldata _terminals) external;\\n\\n function setPrimaryTerminalOf(\\n uint256 _projectId,\\n address _token,\\n IJBPaymentTerminal _terminal\\n ) external;\\n\\n function setIsAllowedToSetFirstController(address _address, bool _flag) external;\\n}\\n\",\"keccak256\":\"0x715321646db00514d1355ed43c40cd3f01e94959552fd07797b315d9c49cdb1d\",\"license\":\"MIT\"},\"contracts/interfaces/IJBGasTokenERC20ProjectPayerDeployer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBDirectory.sol';\\nimport './IJBProjectPayer.sol';\\n\\ninterface IJBGasTokenERC20ProjectPayerDeployer {\\n event DeployProjectPayer(\\n IJBProjectPayer indexed projectPayer,\\n uint256 defaultProjectId,\\n address defaultBeneficiary,\\n bool defaultPreferClaimedTokens,\\n string defaultMemo,\\n bytes defaultMetadata,\\n bool preferAddToBalance,\\n IJBDirectory directory,\\n address owner,\\n address caller\\n );\\n\\n function deployProjectPayer(\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string memory _defaultMemo,\\n bytes memory _defaultMetadata,\\n bool _preferAddToBalance,\\n address _owner\\n ) external returns (IJBProjectPayer projectPayer);\\n}\\n\",\"keccak256\":\"0x69b364b5e637bc641d453d30aa66b8b8a8f024e0117c892246367344a1d12e64\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleBallot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../enums/JBBallotState.sol';\\n\\ninterface IJBFundingCycleBallot is IERC165 {\\n function duration() external view returns (uint256);\\n\\n function stateOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n uint256 _start\\n ) external view returns (JBBallotState);\\n}\\n\",\"keccak256\":\"0x49553a56209237846bc400cf27f260824a6bd06fd8094a7eb5abb9de75779598\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../enums/JBBallotState.sol';\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBFundingCycleData.sol';\\n\\ninterface IJBFundingCycleStore {\\n event Configure(\\n uint256 indexed configuration,\\n uint256 indexed projectId,\\n JBFundingCycleData data,\\n uint256 metadata,\\n uint256 mustStartAtOrAfter,\\n address caller\\n );\\n\\n event Init(uint256 indexed configuration, uint256 indexed projectId, uint256 indexed basedOn);\\n\\n function latestConfigurationOf(uint256 _projectId) external view returns (uint256);\\n\\n function get(uint256 _projectId, uint256 _configuration)\\n external\\n view\\n returns (JBFundingCycle memory);\\n\\n function latestConfiguredOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBBallotState ballotState);\\n\\n function queuedOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentBallotStateOf(uint256 _projectId) external view returns (JBBallotState);\\n\\n function configureFor(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n uint256 _metadata,\\n uint256 _mustStartAtOrAfter\\n ) external returns (JBFundingCycle memory fundingCycle);\\n}\\n\",\"keccak256\":\"0xaead823851433be0c2ddc8f8086813e6cd647de3a1bc0f7570a5d6b38c378b5a\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\n\\ninterface IJBPaymentTerminal is IERC165 {\\n function acceptsToken(address _token, uint256 _projectId) external view returns (bool);\\n\\n function currencyForToken(address _token) external view returns (uint256);\\n\\n function decimalsForToken(address _token) external view returns (uint256);\\n\\n // Return value must be a fixed point number with 18 decimals.\\n function currentEthOverflowOf(uint256 _projectId) external view returns (uint256);\\n\\n function pay(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable returns (uint256 beneficiaryTokenCount);\\n\\n function addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable;\\n}\\n\",\"keccak256\":\"0xb7826f5ed609359ce322c09e83236c47ba385df1c3cad3607e56fd0a2e00eee2\",\"license\":\"MIT\"},\"contracts/interfaces/IJBProjectPayer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './IJBDirectory.sol';\\n\\ninterface IJBProjectPayer is IERC165 {\\n event SetDefaultValues(\\n uint256 indexed projectId,\\n address indexed beneficiary,\\n bool preferClaimedTokens,\\n string memo,\\n bytes metadata,\\n bool preferAddToBalance,\\n address caller\\n );\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function projectPayerDeployer() external view returns (address);\\n\\n function defaultProjectId() external view returns (uint256);\\n\\n function defaultBeneficiary() external view returns (address payable);\\n\\n function defaultPreferClaimedTokens() external view returns (bool);\\n\\n function defaultMemo() external view returns (string memory);\\n\\n function defaultMetadata() external view returns (bytes memory);\\n\\n function defaultPreferAddToBalance() external view returns (bool);\\n\\n function initialize(\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string memory _defaultMemo,\\n bytes memory _defaultMetadata,\\n bool _defaultPreferAddToBalance,\\n address _owner\\n ) external;\\n\\n function setDefaultValues(\\n uint256 _projectId,\\n address payable _beneficiary,\\n bool _preferClaimedTokens,\\n string memory _memo,\\n bytes memory _metadata,\\n bool _defaultPreferAddToBalance\\n ) external;\\n\\n function pay(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string memory _memo,\\n bytes memory _metadata\\n ) external payable;\\n\\n function addToBalanceOf(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n string memory _memo,\\n bytes memory _metadata\\n ) external payable;\\n\\n receive() external payable;\\n}\\n\",\"keccak256\":\"0x85f4cbd5482e26618994f742c149a5bd3cb3dc39dbeba85b21c36b3215007df6\",\"license\":\"MIT\"},\"contracts/interfaces/IJBProjects.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBTokenUriResolver.sol';\\n\\ninterface IJBProjects is IERC721 {\\n event Create(\\n uint256 indexed projectId,\\n address indexed owner,\\n JBProjectMetadata metadata,\\n address caller\\n );\\n\\n event SetMetadata(uint256 indexed projectId, JBProjectMetadata metadata, address caller);\\n\\n event SetTokenUriResolver(IJBTokenUriResolver indexed resolver, address caller);\\n\\n function count() external view returns (uint256);\\n\\n function metadataContentOf(uint256 _projectId, uint256 _domain)\\n external\\n view\\n returns (string memory);\\n\\n function tokenUriResolver() external view returns (IJBTokenUriResolver);\\n\\n function createFor(address _owner, JBProjectMetadata calldata _metadata)\\n external\\n returns (uint256 projectId);\\n\\n function setMetadataOf(uint256 _projectId, JBProjectMetadata calldata _metadata) external;\\n\\n function setTokenUriResolver(IJBTokenUriResolver _newResolver) external;\\n}\\n\",\"keccak256\":\"0x7cfc021d0bd7e73b1ba8f4845d7d35e3419d6a14d3d25ca3a8010e7f91062fe4\",\"license\":\"MIT\"},\"contracts/interfaces/IJBTokenUriResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBTokenUriResolver {\\n function getUri(uint256 _projectId) external view returns (string memory tokenUri);\\n}\\n\",\"keccak256\":\"0xd267fd8ca7c21c2c71794acdb9a98314c33a35fc559e0bf0897a6686d196d174\",\"license\":\"MIT\"},\"contracts/libraries/JBTokens.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBTokens {\\n /** \\n @notice \\n The ETH token address in Juicebox is represented by 0x000000000000000000000000000000000000EEEe.\\n */\\n address public constant ETH = address(0x000000000000000000000000000000000000EEEe);\\n}\\n\",\"keccak256\":\"0xecf82992f7b827766aa55f16872517a646521eef414d8cc9786617ea377e5463\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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.\\n @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.\\n @member basedOn The `configuration` of the funding cycle that was active when this cycle was created.\\n @member start The timestamp marking the moment from which the funding cycle is considered active. It is a unix timestamp measured in seconds.\\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n @member metadata Extra data that can be associated with a funding cycle.\\n*/\\nstruct JBFundingCycle {\\n uint256 number;\\n uint256 configuration;\\n uint256 basedOn;\\n uint256 start;\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n uint256 metadata;\\n}\\n\",\"keccak256\":\"0xcdd3ac9b6fa67e62ada88d09b73bc35ade1cd77d43db712289266a788928b4c2\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycleData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n*/\\nstruct JBFundingCycleData {\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n}\\n\",\"keccak256\":\"0x2aa6368bf4dfc5797e8b02a978293de0c777fae2658de2c825a103587240f3b0\",\"license\":\"MIT\"},\"contracts/structs/JBProjectMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member content The metadata content.\\n @member domain The domain within which the metadata applies.\\n*/\\nstruct JBProjectMetadata {\\n string content;\\n uint256 domain;\\n}\\n\",\"keccak256\":\"0x90ad7b1014c0a9f945fe7a2efde9d5de41e40574fa27969070b1d2ff52033ea0\",\"license\":\"MIT\"}},\"version\":1}", "bytecode": "0x60c060405234801561001057600080fd5b50604051612c0f380380612c0f83398101604081905261002f9161008d565b8060405161003c90610080565b6001600160a01b039091168152602001604051809103906000f080158015610068573d6000803e3d6000fd5b506001600160a01b039081166080521660a0526100bd565b612549806106c683390190565b60006020828403121561009f57600080fd5b81516001600160a01b03811681146100b657600080fd5b9392505050565b60805160a0516105e56100e1600039600061016a01526000607301526105e56000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c80635be94a6f14610030575b600080fd5b61004361003e3660046103a8565b61006c565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b60006100977f00000000000000000000000000000000000000000000000000000000000000006101b3565b6040517fc0048ca500000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff82169063c0048ca5906100f8908b908b908b908b908b908b908b906004016104c2565b600060405180830381600087803b15801561011257600080fd5b505af1158015610126573d6000803e3d6000fd5b505050508073ffffffffffffffffffffffffffffffffffffffff167f727d4d4c40bee220af4fdbae0c157cb7a5e5f2ce9c3e9676e8f615cd88bc85df8989898989897f00000000000000000000000000000000000000000000000000000000000000008a336040516101a09998979695949392919061052f565b60405180910390a2979650505050505050565b60006040517f3d602d80600a3d3981f3363d3d373d3d3d363d7300000000000000000000000081528260601b60148201527f5af43d82803e903d91602b57fd5bf3000000000000000000000000000000000060288201526037816000f091505073ffffffffffffffffffffffffffffffffffffffff8116610294576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f455243313136373a20637265617465206661696c656400000000000000000000604482015260640160405180910390fd5b919050565b73ffffffffffffffffffffffffffffffffffffffff811681146102bb57600080fd5b50565b8035801515811461029457600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261030e57600080fd5b813567ffffffffffffffff80821115610329576103296102ce565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561036f5761036f6102ce565b8160405283815286602085880101111561038857600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600080600080600060e0888a0312156103c357600080fd5b8735965060208801356103d581610299565b95506103e3604089016102be565b9450606088013567ffffffffffffffff8082111561040057600080fd5b61040c8b838c016102fd565b955060808a013591508082111561042257600080fd5b5061042f8a828b016102fd565b93505061043e60a089016102be565b915060c088013561044e81610299565b8091505092959891949750929550565b6000815180845260005b8181101561048457602081850181015186830182015201610468565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b878152600073ffffffffffffffffffffffffffffffffffffffff8089166020840152871515604084015260e0606084015261050060e084018861045e565b8381036080850152610512818861045e565b95151560a0850152509290921660c0909101525095945050505050565b60006101208b835273ffffffffffffffffffffffffffffffffffffffff808c1660208501528a1515604085015281606085015261056e8285018b61045e565b91508382036080850152610582828a61045e565b97151560a085015295861660c0840152505091831660e0830152909116610100909101529594505050505056fea2646970667358221220d9813aa7b2c826ebec43fdd21bc1f31e50caf91e73764e970cf07c573a4ea35f64736f6c6343000810003360c06040523480156200001157600080fd5b5060405162002549380380620025498339810160408190526200003491620000a5565b6200003f3362000055565b6001600160a01b03166080523360a052620000d7565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600060208284031215620000b857600080fd5b81516001600160a01b0381168114620000d057600080fd5b9392505050565b60805160a051612437620001126000396000818161046d015261133e01526000818161058a0152818161060e015261087201526124376000f3fe6080604052600436106100f75760003560e01c80638293fee61161008a578063b96053df11610059578063b96053df14610543578063c0048ca514610558578063c41c2f2414610578578063f2fde38b146105ac57600080fd5b80638293fee6146104c65780638da5cb5b146104d957806393b7f154146104f7578063a4919eb11461051157600080fd5b806354ab58af116100c657806354ab58af1461042357806364d3ed271461045b578063715018a61461048f5780637e646549146104a457600080fd5b806301ffc9a71461039757806309a6b7e5146103cc5780630e45f78e146103df5780633ce9830b146103ff57600080fd5b366103925760055460ff16156102305761022e60015461eeee4760126003805461012090611ae9565b80601f016020809104026020016040519081016040528092919081815260200182805461014c90611ae9565b80156101995780601f1061016e57610100808354040283529160200191610199565b820191906000526020600020905b81548152906001019060200180831161017c57829003601f168201915b5050505050600480546101ab90611ae9565b80601f01602080910402602001604051908101604052809291908181526020018280546101d790611ae9565b80156102245780601f106101f957610100808354040283529160200191610224565b820191906000526020600020905b81548152906001019060200180831161020757829003601f168201915b50505050506105cc565b005b60015460025461022e919061eeee9047906012906001600160a01b031615610263576002546001600160a01b0316610265565b325b6000600260149054906101000a900460ff166003805461028490611ae9565b80601f01602080910402602001604051908101604052809291908181526020018280546102b090611ae9565b80156102fd5780601f106102d2576101008083540402835291602001916102fd565b820191906000526020600020905b8154815290600101906020018083116102e057829003601f168201915b50505050506004805461030f90611ae9565b80601f016020809104026020016040519081016040528092919081815260200182805461033b90611ae9565b80156103885780601f1061035d57610100808354040283529160200191610388565b820191906000526020600020905b81548152906001019060200180831161036b57829003601f168201915b5050505050610830565b600080fd5b3480156103a357600080fd5b506103b76103b2366004611b3c565b610af1565b60405190151581526020015b60405180910390f35b61022e6103da366004611bdc565b610b8a565b3480156103eb57600080fd5b5061022e6103fa366004611d73565b610d8d565b34801561040b57600080fd5b5061041560015481565b6040519081526020016103c3565b34801561042f57600080fd5b50600254610443906001600160a01b031681565b6040516001600160a01b0390911681526020016103c3565b34801561046757600080fd5b506104437f000000000000000000000000000000000000000000000000000000000000000081565b34801561049b57600080fd5b5061022e61100f565b3480156104b057600080fd5b506104b961108f565b6040516103c39190611e87565b61022e6104d4366004611e9a565b61111d565b3480156104e557600080fd5b506000546001600160a01b0316610443565b34801561050357600080fd5b506005546103b79060ff1681565b34801561051d57600080fd5b506002546103b79074010000000000000000000000000000000000000000900460ff1681565b34801561054f57600080fd5b506104b9611326565b34801561056457600080fd5b5061022e610573366004611f76565b611333565b34801561058457600080fd5b506104437f000000000000000000000000000000000000000000000000000000000000000081565b3480156105b857600080fd5b5061022e6105c7366004612030565b611442565b6040517f86202650000000000000000000000000000000000000000000000000000000008152600481018790526001600160a01b0386811660248301526000917f000000000000000000000000000000000000000000000000000000000000000090911690638620265090604401602060405180830381865afa158015610657573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061067b919061204d565b90506001600160a01b0381166106bd576040517ffba10dd600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fb7bad1b10000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015285919083169063b7bad1b190602401602060405180830381865afa15801561071f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610743919061206a565b1461077a576040517fb972592400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03861661eeee146107a0576107a06001600160a01b0387168287611558565b60006001600160a01b03871661eeee146107bb5760006107bd565b855b9050816001600160a01b0316630cf8e858828a898b89896040518763ffffffff1660e01b81526004016107f4959493929190612083565b6000604051808303818588803b15801561080d57600080fd5b505af1158015610821573d6000803e3d6000fd5b50505050505050505050505050565b6040517f86202650000000000000000000000000000000000000000000000000000000008152600481018a90526001600160a01b0389811660248301526000917f000000000000000000000000000000000000000000000000000000000000000090911690638620265090604401602060405180830381865afa1580156108bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108df919061204d565b90506001600160a01b038116610921576040517ffba10dd600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fb7bad1b10000000000000000000000000000000000000000000000000000000081526001600160a01b038a8116600483015288919083169063b7bad1b190602401602060405180830381865afa158015610983573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109a7919061206a565b146109de576040517fb972592400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03891661eeee14610a0457610a046001600160a01b038a16828a611558565b60006001600160a01b038a1661eeee14610a1f576000610a21565b885b9050816001600160a01b0316631ebc263f828d8c8e60006001600160a01b03168d6001600160a01b031603610a77576002546001600160a01b0316610a665732610a79565b6002546001600160a01b0316610a79565b8c5b8c8c8c8c6040518a63ffffffff1660e01b8152600401610aa09897969594939291906120cf565b60206040518083038185885af1158015610abe573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610ae3919061206a565b505050505050505050505050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7ddb72fc000000000000000000000000000000000000000000000000000000001480610b8457507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b6001600160a01b03871661eeee14610d04573415610bd4576040517fbcfd35be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038916906370a0823190602401602060405180830381865afa158015610c34573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c58919061206a565b9050610c6f6001600160a01b03891633308a611743565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015281906001600160a01b038a16906370a0823190602401602060405180830381865afa158015610cce573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cf2919061206a565b610cfc9190612139565b965050610d0c565b349550601294505b610d838888888888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8c018190048102820181019092528a815292508a91508990819084018382808284376000920191909152506105cc92505050565b5050505050505050565b6000546001600160a01b03163314610e06576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b6001548614610e155760018690555b6002546001600160a01b03868116911614610e5e57600280547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0387161790555b600260149054906101000a900460ff16151584151514610ebc57600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000861515021790555b6003604051602001610ece9190612204565b6040516020818303038152906040528051906020012083604051602001610ef59190612210565b6040516020818303038152906040528051906020012014610f1e576003610f1c848261227a565b505b6004604051602001610f309190612204565b6040516020818303038152906040528051906020012082604051602001610f579190612210565b6040516020818303038152906040528051906020012014610f80576004610f7e838261227a565b505b60055460ff16151581151514610fbd57600580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168215151790555b846001600160a01b0316867f36b1c5cef608e320317b9ee5155756634c65fe7055b424ce57e2f6c59eec79478686868633604051610fff959493929190612394565b60405180910390a3505050505050565b6000546001600160a01b03163314611083576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610dfd565b61108d600061179a565b565b6004805461109c90611ae9565b80601f01602080910402602001604051908101604052809291908181526020018280546110c890611ae9565b80156111155780601f106110ea57610100808354040283529160200191611115565b820191906000526020600020905b8154815290600101906020018083116110f857829003601f168201915b505050505081565b6001600160a01b038a1661eeee14611297573415611167576040517fbcfd35be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038c16906370a0823190602401602060405180830381865afa1580156111c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111eb919061206a565b90506112026001600160a01b038c1633308d611743565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015281906001600160a01b038d16906370a0823190602401602060405180830381865afa158015611261573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611285919061206a565b61128f9190612139565b99505061129f565b349850601297505b6113198b8b8b8b8b8b8b8b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8f018190048102820181019092528d815292508d91508c908190840183828082843760009201919091525061083092505050565b5050505050505050505050565b6003805461109c90611ae9565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611395576040517f439a74c900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018790556002805486151574010000000000000000000000000000000000000000027fffffffffffffffffffffff0000000000000000000000000000000000000000009091166001600160a01b0389161717905560036113f6858261227a565b506004611403848261227a565b50600580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168315151790556114398161179a565b50505050505050565b6000546001600160a01b031633146114b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610dfd565b6001600160a01b03811661154c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610dfd565b6115558161179a565b50565b8015806115eb57506040517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa1580156115c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115e9919061206a565b155b611677576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e6365000000000000000000006064820152608401610dfd565b6040516001600160a01b03831660248201526044810182905261173e9084907f095ea7b300000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611802565b505050565b6040516001600160a01b03808516602483015283166044820152606481018290526117949085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016116bc565b50505050565b600080546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000611857826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166119019092919063ffffffff16565b80519091501561173e578080602001905181019061187591906123e4565b61173e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610dfd565b6060611910848460008561191a565b90505b9392505050565b6060824710156119ac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610dfd565b6001600160a01b0385163b611a1d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610dfd565b600080866001600160a01b03168587604051611a399190612210565b60006040518083038185875af1925050503d8060008114611a76576040519150601f19603f3d011682016040523d82523d6000602084013e611a7b565b606091505b5091509150611a8b828286611a96565b979650505050505050565b60608315611aa5575081611913565b825115611ab55782518084602001fd5b816040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dfd9190611e87565b600181811c90821680611afd57607f821691505b602082108103611b36577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600060208284031215611b4e57600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461191357600080fd5b6001600160a01b038116811461155557600080fd5b60008083601f840112611ba557600080fd5b50813567ffffffffffffffff811115611bbd57600080fd5b602083019150836020828501011115611bd557600080fd5b9250929050565b60008060008060008060008060c0898b031215611bf857600080fd5b883597506020890135611c0a81611b7e565b96506040890135955060608901359450608089013567ffffffffffffffff80821115611c3557600080fd5b611c418c838d01611b93565b909650945060a08b0135915080821115611c5a57600080fd5b50611c678b828c01611b93565b999c989b5096995094979396929594505050565b801515811461155557600080fd5b8035611c9481611c7b565b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f830112611cd957600080fd5b813567ffffffffffffffff80821115611cf457611cf4611c99565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715611d3a57611d3a611c99565b81604052838152866020858801011115611d5357600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c08789031215611d8c57600080fd5b863595506020870135611d9e81611b7e565b94506040870135611dae81611c7b565b9350606087013567ffffffffffffffff80821115611dcb57600080fd5b611dd78a838b01611cc8565b94506080890135915080821115611ded57600080fd5b50611dfa89828a01611cc8565b92505060a0870135611e0b81611c7b565b809150509295509295509295565b60005b83811015611e34578181015183820152602001611e1c565b50506000910152565b60008151808452611e55816020860160208601611e19565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006119136020830184611e3d565b60008060008060008060008060008060006101208c8e031215611ebc57600080fd5b8b359a50611ecd60208d0135611b7e565b60208c0135995060408c0135985060608c01359750611eef60808d0135611b7e565b60808c0135965060a08c01359550611f0960c08d01611c89565b945067ffffffffffffffff8060e08e01351115611f2557600080fd5b611f358e60e08f01358f01611b93565b90955093506101008d0135811015611f4c57600080fd5b50611f5e8d6101008e01358e01611b93565b81935080925050509295989b509295989b9093969950565b600080600080600080600060e0888a031215611f9157600080fd5b873596506020880135611fa381611b7e565b95506040880135611fb381611c7b565b9450606088013567ffffffffffffffff80821115611fd057600080fd5b611fdc8b838c01611cc8565b955060808a0135915080821115611ff257600080fd5b50611fff8a828b01611cc8565b93505060a088013561201081611c7b565b915060c088013561202081611b7e565b8091505092959891949750929550565b60006020828403121561204257600080fd5b813561191381611b7e565b60006020828403121561205f57600080fd5b815161191381611b7e565b60006020828403121561207c57600080fd5b5051919050565b8581528460208201526001600160a01b038416604082015260a0606082015260006120b160a0830185611e3d565b82810360808401526120c38185611e3d565b98975050505050505050565b60006101008a83528960208401526001600160a01b03808a16604085015280891660608501525086608084015285151560a08401528060c084015261211681840186611e3d565b905082810360e084015261212a8185611e3d565b9b9a5050505050505050505050565b81810381811115610b84577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000815461218081611ae9565b6001828116801561219857600181146121cb576121fa565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00841687528215158302870194506121fa565b8560005260208060002060005b858110156121f15781548a8201529084019082016121d8565b50505082870194505b5050505092915050565b60006119138284612173565b60008251612222818460208701611e19565b9190910192915050565b601f82111561173e57600081815260208120601f850160051c810160208610156122535750805b601f850160051c820191505b818110156122725782815560010161225f565b505050505050565b815167ffffffffffffffff81111561229457612294611c99565b6122a8816122a28454611ae9565b8461222c565b602080601f8311600181146122fb57600084156122c55750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555612272565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561234857888601518255948401946001909101908401612329565b508582101561238457878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b851515815260a0602082015260006123af60a0830187611e3d565b82810360408401526123c18187611e3d565b941515606084015250506001600160a01b03919091166080909101529392505050565b6000602082840312156123f657600080fd5b815161191381611c7b56fea2646970667358221220d8fef8595bb92757a75cfecd11a51f739d7c43b0f78c357375608404c1047b7064736f6c63430008100033", "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c80635be94a6f14610030575b600080fd5b61004361003e3660046103a8565b61006c565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b60006100977f00000000000000000000000000000000000000000000000000000000000000006101b3565b6040517fc0048ca500000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff82169063c0048ca5906100f8908b908b908b908b908b908b908b906004016104c2565b600060405180830381600087803b15801561011257600080fd5b505af1158015610126573d6000803e3d6000fd5b505050508073ffffffffffffffffffffffffffffffffffffffff167f727d4d4c40bee220af4fdbae0c157cb7a5e5f2ce9c3e9676e8f615cd88bc85df8989898989897f00000000000000000000000000000000000000000000000000000000000000008a336040516101a09998979695949392919061052f565b60405180910390a2979650505050505050565b60006040517f3d602d80600a3d3981f3363d3d373d3d3d363d7300000000000000000000000081528260601b60148201527f5af43d82803e903d91602b57fd5bf3000000000000000000000000000000000060288201526037816000f091505073ffffffffffffffffffffffffffffffffffffffff8116610294576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f455243313136373a20637265617465206661696c656400000000000000000000604482015260640160405180910390fd5b919050565b73ffffffffffffffffffffffffffffffffffffffff811681146102bb57600080fd5b50565b8035801515811461029457600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f83011261030e57600080fd5b813567ffffffffffffffff80821115610329576103296102ce565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561036f5761036f6102ce565b8160405283815286602085880101111561038857600080fd5b836020870160208301376000602085830101528094505050505092915050565b600080600080600080600060e0888a0312156103c357600080fd5b8735965060208801356103d581610299565b95506103e3604089016102be565b9450606088013567ffffffffffffffff8082111561040057600080fd5b61040c8b838c016102fd565b955060808a013591508082111561042257600080fd5b5061042f8a828b016102fd565b93505061043e60a089016102be565b915060c088013561044e81610299565b8091505092959891949750929550565b6000815180845260005b8181101561048457602081850181015186830182015201610468565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b878152600073ffffffffffffffffffffffffffffffffffffffff8089166020840152871515604084015260e0606084015261050060e084018861045e565b8381036080850152610512818861045e565b95151560a0850152509290921660c0909101525095945050505050565b60006101208b835273ffffffffffffffffffffffffffffffffffffffff808c1660208501528a1515604085015281606085015261056e8285018b61045e565b91508382036080850152610582828a61045e565b97151560a085015295861660c0840152505091831660e0830152909116610100909101529594505050505056fea2646970667358221220d9813aa7b2c826ebec43fdd21bc1f31e50caf91e73764e970cf07c573a4ea35f64736f6c63430008100033", "devdoc": { - "details": "Adheres to - IJBETHERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.", + "details": "Adheres to - IJBGasTokenERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.", "kind": "dev", "methods": { "constructor": { diff --git a/deployments/mainnet/JBETHERC20SplitsPayerDeployer.json b/deployments/mainnet/JBETHERC20SplitsPayerDeployer.json index 968b51ae7..a47728bbd 100644 --- a/deployments/mainnet/JBETHERC20SplitsPayerDeployer.json +++ b/deployments/mainnet/JBETHERC20SplitsPayerDeployer.json @@ -299,11 +299,11 @@ ], "numDeployments": 1, "solcInputHash": "e87fd161fb98793b8dd4dcaee81afb88", - "metadata": "{\"compiler\":{\"version\":\"0.8.16+commit.07a7930e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IJBSplitsStore\",\"name\":\"_splitsStore\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IJBSplitsPayer\",\"name\":\"splitsPayer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"defaultSplitsProjectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"defaultSplitsDomain\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"defaultSplitsGroup\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"contract IJBSplitsStore\",\"name\":\"splitsStore\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"defaultProjectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"defaultBeneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"defaultPreferClaimedTokens\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"defaultMemo\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"defaultMetadata\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"preferAddToBalance\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"DeploySplitsPayer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_defaultSplitsProjectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_defaultSplitsDomain\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_defaultSplitsGroup\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_defaultProjectId\",\"type\":\"uint256\"},{\"internalType\":\"address payable\",\"name\":\"_defaultBeneficiary\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_defaultPreferClaimedTokens\",\"type\":\"bool\"},{\"internalType\":\"string\",\"name\":\"_defaultMemo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_defaultMetadata\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"_defaultPreferAddToBalance\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"deploySplitsPayer\",\"outputs\":[{\"internalType\":\"contract IJBSplitsPayer\",\"name\":\"splitsPayer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_defaultSplitsProjectId\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"preferClaimed\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"preferAddToBalance\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"percent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"lockedUntil\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBSplitAllocator\",\"name\":\"allocator\",\"type\":\"address\"}],\"internalType\":\"struct JBSplit[]\",\"name\":\"_defaultSplits\",\"type\":\"tuple[]\"},{\"internalType\":\"contract IJBSplitsStore\",\"name\":\"_splitsStore\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_defaultProjectId\",\"type\":\"uint256\"},{\"internalType\":\"address payable\",\"name\":\"_defaultBeneficiary\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_defaultPreferClaimedTokens\",\"type\":\"bool\"},{\"internalType\":\"string\",\"name\":\"_defaultMemo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_defaultMetadata\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"_defaultPreferAddToBalance\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"deploySplitsPayerWithSplits\",\"outputs\":[{\"internalType\":\"contract IJBSplitsPayer\",\"name\":\"splitsPayer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Adheres to - IJBETHERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\",\"kind\":\"dev\",\"methods\":{\"deploySplitsPayer(uint256,uint256,uint256,uint256,address,bool,string,bytes,bool,address)\":{\"params\":{\"_defaultBeneficiary\":\"The address that'll receive the project's tokens when the splits payer receives payments. \",\"_defaultMemo\":\"The memo that'll be forwarded with the splits payer's received payments. \",\"_defaultMetadata\":\"The metadata that'll be forwarded with the splits payer's received payments. \",\"_defaultPreferAddToBalance\":\"A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\",\"_defaultPreferClaimedTokens\":\"A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \",\"_defaultProjectId\":\"The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\",\"_defaultSplitsDomain\":\"The splits domain to payout when this contract receives direct payments.\",\"_defaultSplitsGroup\":\"The splits group to payout when this contract receives direct payments.\",\"_defaultSplitsProjectId\":\"The ID of project for which the default splits are stored.\",\"_owner\":\"The address that will own the splits payer.\"},\"returns\":{\"splitsPayer\":\"The splits payer contract.\"}},\"deploySplitsPayerWithSplits(uint256,(bool,bool,uint256,uint256,address,uint256,address)[],address,uint256,address,bool,string,bytes,bool,address)\":{\"details\":\"This contract must have Operator permissions over the SET_SPLITS permission of the specified `_defaultSplitsProjectId`.\",\"params\":{\"_defaultBeneficiary\":\"The address that'll receive the project's tokens when the splits payer receives payments. \",\"_defaultMemo\":\"The memo that'll be forwarded with the splits payer's received payments. \",\"_defaultMetadata\":\"The metadata that'll be forwarded with the splits payer's received payments. \",\"_defaultPreferAddToBalance\":\"A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\",\"_defaultPreferClaimedTokens\":\"A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \",\"_defaultProjectId\":\"The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\",\"_defaultSplits\":\"The splits to payout when this contract receives direct payments.\",\"_defaultSplitsProjectId\":\"The ID of project for which the default splits are stored.\",\"_owner\":\"The address that will own the splits payer.\",\"_splitsStore\":\"A contract that stores splits for each project.\"},\"returns\":{\"splitsPayer\":\"The splits payer contract.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"deploySplitsPayer(uint256,uint256,uint256,uint256,address,bool,string,bytes,bool,address)\":{\"notice\":\" Allows anyone to deploy a new splits payer contract.\"},\"deploySplitsPayerWithSplits(uint256,(bool,bool,uint256,uint256,address,uint256,address)[],address,uint256,address,bool,string,bytes,bool,address)\":{\"notice\":\" Allows anyone to deploy a new splits payer contract.\"}},\"notice\":\" Deploys splits payer contracts.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/JBETHERC20SplitsPayerDeployer.sol\":\"JBETHERC20SplitsPayerDeployer\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0x24e0364e503a9bbde94c715d26573a76f14cd2a202d45f96f52134ab806b67b9\",\"license\":\"MIT\"},\"@openzeppelin/contracts/proxy/Clones.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/Clones.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for\\n * deploying minimal proxy contracts, also known as \\\"clones\\\".\\n *\\n * > To simply and cheaply clone contract functionality in an immutable way, this standard specifies\\n * > a minimal bytecode implementation that delegates all calls to a known, fixed address.\\n *\\n * The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2`\\n * (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the\\n * deterministic method.\\n *\\n * _Available since v3.4._\\n */\\nlibrary Clones {\\n /**\\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.\\n *\\n * This function uses the create opcode, which should never revert.\\n */\\n function clone(address implementation) internal returns (address instance) {\\n assembly {\\n let ptr := mload(0x40)\\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\\n mstore(add(ptr, 0x14), shl(0x60, implementation))\\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\\n instance := create(0, ptr, 0x37)\\n }\\n require(instance != address(0), \\\"ERC1167: create failed\\\");\\n }\\n\\n /**\\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.\\n *\\n * This function uses the create2 opcode and a `salt` to deterministically deploy\\n * the clone. Using the same `implementation` and `salt` multiple time will revert, since\\n * the clones cannot be deployed twice at the same address.\\n */\\n function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) {\\n assembly {\\n let ptr := mload(0x40)\\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\\n mstore(add(ptr, 0x14), shl(0x60, implementation))\\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\\n instance := create2(0, ptr, 0x37, salt)\\n }\\n require(instance != address(0), \\\"ERC1167: create2 failed\\\");\\n }\\n\\n /**\\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\\n */\\n function predictDeterministicAddress(\\n address implementation,\\n bytes32 salt,\\n address deployer\\n ) internal pure returns (address predicted) {\\n assembly {\\n let ptr := mload(0x40)\\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\\n mstore(add(ptr, 0x14), shl(0x60, implementation))\\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf3ff00000000000000000000000000000000)\\n mstore(add(ptr, 0x38), shl(0x60, deployer))\\n mstore(add(ptr, 0x4c), salt)\\n mstore(add(ptr, 0x6c), keccak256(ptr, 0x37))\\n predicted := keccak256(add(ptr, 0x37), 0x55)\\n }\\n }\\n\\n /**\\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\\n */\\n function predictDeterministicAddress(address implementation, bytes32 salt)\\n internal\\n view\\n returns (address predicted)\\n {\\n return predictDeterministicAddress(implementation, salt, address(this));\\n }\\n}\\n\",\"keccak256\":\"0x1cc0efb01cbf008b768fd7b334786a6e358809198bb7e67f1c530af4957c6a21\",\"license\":\"MIT\"},\"@openzeppelin/contracts/security/ReentrancyGuard.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuard {\\n // Booleans are more expensive than uint256 or any type that takes up a full\\n // word because each write operation emits an extra SLOAD to first read the\\n // slot's contents, replace the bits taken up by the boolean, and then write\\n // back. This is the compiler's defense against contract upgrades and\\n // pointer aliasing, and it cannot be disabled.\\n\\n // The values being non-zero value makes deployment a bit more expensive,\\n // but in exchange the refund on every call to nonReentrant will be lower in\\n // amount. Since refunds are capped to a percentage of the total\\n // transaction's gas, it is best to keep them low in cases like this one, to\\n // increase the likelihood of the full refund coming into effect.\\n uint256 private constant _NOT_ENTERED = 1;\\n uint256 private constant _ENTERED = 2;\\n\\n uint256 private _status;\\n\\n constructor() {\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and making it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n // On the first call to nonReentrant, _notEntered will be true\\n require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n _status = _ENTERED;\\n\\n _;\\n\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n _status = _NOT_ENTERED;\\n }\\n}\\n\",\"keccak256\":\"0x0e9621f60b2faabe65549f7ed0f24e8853a45c1b7990d47e8160e523683f3935\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address sender,\\n address recipient,\\n uint256 amount\\n ) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0x61437cb513a887a1bbad006e7b1c8b414478427d33de47c5600af3c748f108da\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(\\n IERC20 token,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(\\n IERC20 token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) {\\n // Return data is optional\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xc3d946432c0ddbb1f846a0d3985be71299df331b91d06732152117f62f0be2b5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool _approved) external;\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x516a22876c1fab47f49b1bc22b4614491cd05338af8bd2e7b382da090a079990\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3777e696b62134e6177440dbe6e6601c0c156a443f57167194b67e75527439de\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"@paulrberg/contracts/math/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\nimport \\\"prb-math/contracts/PRBMath.sol\\\";\\n\",\"keccak256\":\"0x42821345981bc0434a90ba2268a2f5278dfe9e38166981d72fc7f3b776a29495\",\"license\":\"Unlicense\"},\"contracts/JBETHERC20ProjectPayer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport '@openzeppelin/contracts/access/Ownable.sol';\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\\nimport './interfaces/IJBProjectPayer.sol';\\nimport './libraries/JBTokens.sol';\\n\\n/** \\n @notice \\n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\\n\\n @dev\\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\\n\\n @dev\\n Adheres to -\\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n\\n @dev\\n Inherits from -\\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\\n ERC165: Introspection on interface adherance. \\n*/\\ncontract JBETHERC20ProjectPayer is Ownable, ERC165, IJBProjectPayer {\\n using SafeERC20 for IERC20;\\n\\n //*********************************************************************//\\n // -------------------------- custom errors -------------------------- //\\n //*********************************************************************//\\n error INCORRECT_DECIMAL_AMOUNT();\\n error ALREADY_INITIALIZED();\\n error NO_MSG_VALUE_ALLOWED();\\n error TERMINAL_NOT_FOUND();\\n\\n //*********************************************************************//\\n // ------------------- public immutable properties ------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice \\n A contract storing directories of terminals and controllers for each project.\\n */\\n IJBDirectory public immutable override directory;\\n\\n /**\\n @notice \\n The deployer associated with this implementation. Used to rule out double initialization.\\n */\\n address public immutable override projectPayerDeployer;\\n\\n //*********************************************************************//\\n // --------------------- public stored properties -------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n The ID of the project that should be used to forward this contract's received payments.\\n */\\n uint256 public override defaultProjectId;\\n\\n /** \\n @notice \\n The beneficiary that should be used in the payment made when this contract receives payments.\\n */\\n address payable public override defaultBeneficiary;\\n\\n /** \\n @notice \\n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\\n */\\n bool public override defaultPreferClaimedTokens;\\n\\n /** \\n @notice \\n The memo that should be used in the payment made when this contract receives payments.\\n */\\n string public override defaultMemo;\\n\\n /** \\n @notice \\n The metadata that should be used in the payment made when this contract receives payments.\\n */\\n bytes public override defaultMetadata;\\n\\n /**\\n @notice \\n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\\n */\\n bool public override defaultPreferAddToBalance;\\n\\n //*********************************************************************//\\n // ------------------------- public views ---------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Indicates if this contract adheres to the specified interface.\\n\\n @dev \\n See {IERC165-supportsInterface}.\\n\\n @param _interfaceId The ID of the interface to check for adherance to.\\n */\\n function supportsInterface(bytes4 _interfaceId)\\n public\\n view\\n virtual\\n override(ERC165, IERC165)\\n returns (bool)\\n {\\n return\\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\\n }\\n\\n //*********************************************************************//\\n // -------------------------- constructors --------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @dev This is the constructor of the implementation. The directory is shared between project payers and is\\n immutable. If a new JBDirectory is needed, a new JBProjectPayerDeployer should be deployed.\\n @param _directory A contract storing directories of terminals and controllers for each project.\\n */\\n constructor(IJBDirectory _directory) {\\n directory = _directory;\\n projectPayerDeployer = msg.sender;\\n }\\n\\n /** \\n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\\n @param _defaultBeneficiary The address that'll receive the project's tokens. \\n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \\n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\\n @param _owner The address that will own the contract.\\n */\\n function initialize(\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string memory _defaultMemo,\\n bytes memory _defaultMetadata,\\n bool _defaultPreferAddToBalance,\\n address _owner\\n ) public {\\n if(msg.sender != projectPayerDeployer) revert ALREADY_INITIALIZED();\\n\\n defaultProjectId = _defaultProjectId;\\n defaultBeneficiary = _defaultBeneficiary;\\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\\n defaultMemo = _defaultMemo;\\n defaultMetadata = _defaultMetadata;\\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\\n _transferOwnership(_owner);\\n }\\n\\n //*********************************************************************//\\n // ------------------------- default receive ------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Received funds are paid to the default project ID using the stored default properties.\\n\\n @dev\\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\\n\\n @dev\\n This function is called automatically when the contract receives an ETH payment.\\n */\\n receive() external payable virtual override {\\n if (defaultPreferAddToBalance)\\n _addToBalanceOf(\\n defaultProjectId,\\n JBTokens.ETH,\\n address(this).balance,\\n 18, // balance is a fixed point number with 18 decimals.\\n defaultMemo,\\n defaultMetadata\\n );\\n else\\n _pay(\\n defaultProjectId,\\n JBTokens.ETH,\\n address(this).balance,\\n 18, // balance is a fixed point number with 18 decimals.\\n defaultBeneficiary == address(0) ? tx.origin : defaultBeneficiary,\\n 0, // Can't determine expectation of returned tokens ahead of time.\\n defaultPreferClaimedTokens,\\n defaultMemo,\\n defaultMetadata\\n );\\n }\\n\\n //*********************************************************************//\\n // ---------------------- external transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\\n\\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\\n @param _beneficiary The address that'll receive the project's tokens. \\n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \\n @param _memo The memo that'll be used. \\n @param _metadata The metadata that'll be sent. \\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\\n */\\n function setDefaultValues(\\n uint256 _projectId,\\n address payable _beneficiary,\\n bool _preferClaimedTokens,\\n string memory _memo,\\n bytes memory _metadata,\\n bool _defaultPreferAddToBalance\\n ) external virtual override onlyOwner {\\n // Set the default project ID if it has changed.\\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\\n\\n // Set the default beneficiary if it has changed.\\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\\n\\n // Set the default claimed token preference if it has changed.\\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\\n defaultPreferClaimedTokens = _preferClaimedTokens;\\n\\n // Set the default memo if it has changed.\\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\\n defaultMemo = _memo;\\n\\n // Set the default metadata if it has changed.\\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\\n defaultMetadata = _metadata;\\n\\n // Set the add to balance preference if it has changed.\\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\\n\\n emit SetDefaultValues(\\n _projectId,\\n _beneficiary,\\n _preferClaimedTokens,\\n _memo,\\n _metadata,\\n _defaultPreferAddToBalance,\\n msg.sender\\n );\\n }\\n\\n //*********************************************************************//\\n // ----------------------- public transactions ----------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n Make a payment to the specified project.\\n\\n @param _projectId The ID of the project that is being paid.\\n @param _token The token being paid in.\\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\\n @param _beneficiary The address who will receive tokens from the payment.\\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\\n */\\n function pay(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) public payable virtual override {\\n // ETH shouldn't be sent if the token isn't ETH.\\n if (address(_token) != JBTokens.ETH) {\\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\\n\\n // Get a reference to the balance before receiving tokens.\\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\\n\\n // Transfer tokens to this contract from the msg sender.\\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\\n\\n // The amount should reflect the change in balance.\\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\\n } else {\\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\\n _amount = msg.value;\\n _decimals = 18;\\n }\\n\\n _pay(\\n _projectId,\\n _token,\\n _amount,\\n _decimals,\\n _beneficiary,\\n _minReturnedTokens,\\n _preferClaimedTokens,\\n _memo,\\n _metadata\\n );\\n }\\n\\n /** \\n @notice \\n Add to the balance of the specified project.\\n\\n @param _projectId The ID of the project that is being paid.\\n @param _token The token being paid in.\\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Extra data to pass along to the terminal.\\n */\\n function addToBalanceOf(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) public payable virtual override {\\n // ETH shouldn't be sent if the token isn't ETH.\\n if (address(_token) != JBTokens.ETH) {\\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\\n\\n // Get a reference to the balance before receiving tokens.\\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\\n\\n // Transfer tokens to this contract from the msg sender.\\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\\n\\n // The amount should reflect the change in balance.\\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\\n } else {\\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\\n _amount = msg.value;\\n _decimals = 18;\\n }\\n\\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\\n }\\n\\n //*********************************************************************//\\n // ---------------------- internal transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n Make a payment to the specified project.\\n\\n @param _projectId The ID of the project that is being paid.\\n @param _token The token being paid in.\\n @param _amount The amount of tokens being paid, as a fixed point number. \\n @param _decimals The number of decimals in the `_amount` fixed point number. \\n @param _beneficiary The address who will receive tokens from the payment.\\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _metadata Bytes to send along to the data source and delegate, if provided.\\n */\\n function _pay(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string memory _memo,\\n bytes memory _metadata\\n ) internal virtual {\\n // Find the terminal for the specified project.\\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\\n\\n // There must be a terminal.\\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\\n\\n // The amount's decimals must match the terminal's expected decimals.\\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\\n\\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\\n if (_token != JBTokens.ETH) IERC20(_token).safeApprove(address(_terminal), _amount);\\n\\n // If the token is ETH, send it in msg.value.\\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\\n\\n // Send funds to the terminal.\\n // If the token is ETH, send it in msg.value.\\n _terminal.pay{value: _payableValue}(\\n _projectId,\\n _amount, // ignored if the token is JBTokens.ETH.\\n _token,\\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\\n ? defaultBeneficiary\\n : tx.origin,\\n _minReturnedTokens,\\n _preferClaimedTokens,\\n _memo,\\n _metadata\\n );\\n }\\n\\n /** \\n @notice \\n Add to the balance of the specified project.\\n\\n @param _projectId The ID of the project that is being paid.\\n @param _token The token being paid in.\\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Extra data to pass along to the terminal.\\n */\\n function _addToBalanceOf(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n string memory _memo,\\n bytes memory _metadata\\n ) internal virtual {\\n // Find the terminal for the specified project.\\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\\n\\n // There must be a terminal.\\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\\n\\n // The amount's decimals must match the terminal's expected decimals.\\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\\n\\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\\n if (_token != JBTokens.ETH) IERC20(_token).safeApprove(address(_terminal), _amount);\\n\\n // If the token is ETH, send it in msg.value.\\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\\n\\n // Add to balance so tokens don't get issued.\\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\\n }\\n}\\n\",\"keccak256\":\"0xcbadf8e217bb9c43d18161ce576235277834988ea7cb51d58b5a794914e9156c\",\"license\":\"MIT\"},\"contracts/JBETHERC20SplitsPayer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport '@openzeppelin/contracts/utils/Address.sol';\\nimport '@paulrberg/contracts/math/PRBMath.sol';\\nimport './interfaces/IJBSplitsPayer.sol';\\nimport './interfaces/IJBSplitsStore.sol';\\nimport './libraries/JBConstants.sol';\\nimport './JBETHERC20ProjectPayer.sol';\\n\\n/** \\n @notice \\n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\\n\\n @dev\\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\\n\\n @dev\\n Adheres to -\\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n\\n @dev\\n Inherits from -\\n JBETHERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\\n*/\\ncontract JBETHERC20SplitsPayer is JBETHERC20ProjectPayer, ReentrancyGuard, IJBSplitsPayer {\\n using SafeERC20 for IERC20;\\n\\n //*********************************************************************//\\n // ---------------- public immutable stored properties --------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The contract that stores splits for each project.\\n */\\n IJBSplitsStore public immutable override splitsStore;\\n\\n //*********************************************************************//\\n // --------------------- public stored properties -------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The ID of project for which the default splits are stored. \\n */\\n uint256 public override defaultSplitsProjectId;\\n\\n /**\\n @notice\\n The domain within which the default splits are stored. \\n */\\n uint256 public override defaultSplitsDomain;\\n\\n /**\\n @notice\\n The group within which the default splits are stored. \\n */\\n uint256 public override defaultSplitsGroup;\\n\\n //*********************************************************************//\\n // -------------------------- public views --------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Indicates if this contract adheres to the specified interface.\\n\\n @dev \\n See {IERC165-supportsInterface}.\\n\\n @param _interfaceId The ID of the interface to check for adherance to.\\n\\n @return A flag indicating if this contract adheres to the specified interface.\\n */\\n function supportsInterface(bytes4 _interfaceId)\\n public\\n view\\n virtual\\n override(JBETHERC20ProjectPayer, IERC165)\\n returns (bool)\\n {\\n return\\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\\n }\\n\\n //*********************************************************************//\\n // -------------------------- constructor ---------------------------- //\\n //*********************************************************************//\\n/**\\n @param _splitsStore A contract that stores splits for each project.\\n*/\\n constructor(\\n IJBSplitsStore _splitsStore\\n )\\n JBETHERC20ProjectPayer(\\n _splitsStore.directory()\\n )\\n {\\n splitsStore = _splitsStore;\\n }\\n /**\\n @dev The re-initialize check is done in the inherited paroject payer\\n \\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\\n @param _defaultBeneficiary The address that'll receive the project's tokens. \\n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \\n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\\n @param _owner The address that will own the contract.\\n */\\n function initialize(\\n uint256 _defaultSplitsProjectId,\\n uint256 _defaultSplitsDomain,\\n uint256 _defaultSplitsGroup,\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string memory _defaultMemo,\\n bytes memory _defaultMetadata,\\n bool _preferAddToBalance,\\n address _owner\\n ) external override {\\n\\n super.initialize(\\n _defaultProjectId,\\n _defaultBeneficiary,\\n _defaultPreferClaimedTokens,\\n _defaultMemo,\\n _defaultMetadata,\\n _preferAddToBalance,\\n _owner\\n );\\n\\n defaultSplitsProjectId = _defaultSplitsProjectId;\\n defaultSplitsDomain = _defaultSplitsDomain;\\n defaultSplitsGroup = _defaultSplitsGroup;\\n }\\n\\n\\n\\n //*********************************************************************//\\n // ------------------------- default receive ------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Received funds are paid to the default split group using the stored default properties.\\n\\n @dev\\n This function is called automatically when the contract receives an ETH payment.\\n */\\n receive() external payable virtual override nonReentrant {\\n // Pay the splits and get a reference to the amount leftover.\\n uint256 _leftoverAmount = _payToSplits(\\n defaultSplitsProjectId,\\n defaultSplitsDomain,\\n defaultSplitsGroup,\\n JBTokens.ETH,\\n address(this).balance,\\n 18, // decimals.\\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\\n );\\n\\n // If there is no leftover amount, nothing left to pay.\\n if (_leftoverAmount == 0) return;\\n\\n // If there's a default project ID, try to pay it.\\n if (defaultProjectId != 0)\\n if (defaultPreferAddToBalance)\\n // Pay the project by adding to its balance if prefered.\\n _addToBalanceOf(\\n defaultProjectId,\\n JBTokens.ETH,\\n _leftoverAmount,\\n 18, // decimals.\\n defaultMemo,\\n defaultMetadata\\n );\\n // Otherwise, issue a payment to the project.\\n else\\n _pay(\\n defaultProjectId,\\n JBTokens.ETH,\\n _leftoverAmount,\\n 18, // decimals.\\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\\n 0, // min returned tokens.\\n defaultPreferClaimedTokens,\\n defaultMemo,\\n defaultMetadata\\n );\\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\\n else\\n Address.sendValue(\\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(tx.origin),\\n _leftoverAmount\\n );\\n }\\n\\n //*********************************************************************//\\n // ---------------------- external transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Sets the splits in the splits store that payments this contract receives will be split between.\\n\\n @param _projectId The ID of project for which the default splits are stored. \\n @param _domain The domain within which the default splits are stored. \\n @param _group The group within which the default splits are stored. \\n @param _groupedSplits The split groups to set.\\n */\\n function setDefaultSplits(\\n uint256 _projectId,\\n uint256 _domain,\\n uint256 _group,\\n JBGroupedSplits[] memory _groupedSplits\\n ) external virtual override onlyOwner {\\n // Set the splits in the store.\\n splitsStore.set(_projectId, _domain, _groupedSplits);\\n\\n // Set the splits reference.\\n setDefaultSplitsReference(_projectId, _domain, _group);\\n }\\n\\n //*********************************************************************//\\n // ----------------------- public transactions ----------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Sets the location of the splits that payments this contract receives will be split between.\\n\\n @param _projectId The ID of project for which the default splits are stored. \\n @param _domain The domain within which the default splits are stored. \\n @param _group The group within which the default splits are stored. \\n */\\n function setDefaultSplitsReference(\\n uint256 _projectId,\\n uint256 _domain,\\n uint256 _group\\n ) public virtual override onlyOwner {\\n // Set the default splits project ID if it's changing.\\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\\n\\n // Set the default splits domain if it's changing.\\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\\n\\n // Set the default splits group if it's changing.\\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\\n\\n emit SetDefaultSplitsReference(_projectId, _domain, _group, msg.sender);\\n }\\n\\n /** \\n @notice \\n Make a payment to the specified project after first splitting the amount among the stored default splits.\\n\\n @param _projectId The ID of the project that is being paid after.\\n @param _token The token being paid in.\\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\\n */\\n function pay(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) public payable virtual override nonReentrant {\\n // ETH shouldn't be sent if the token isn't ETH.\\n if (address(_token) != JBTokens.ETH) {\\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\\n\\n // Get a reference to the balance before receiving tokens.\\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\\n\\n // Transfer tokens to this contract from the msg sender.\\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\\n\\n // The amount should reflect the change in balance.\\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\\n } else {\\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\\n _amount = msg.value;\\n _decimals = 18;\\n }\\n\\n // Pay the splits and get a reference to the amount leftover.\\n uint256 _leftoverAmount = _payToSplits(\\n defaultSplitsProjectId,\\n defaultSplitsDomain,\\n defaultSplitsGroup,\\n _token,\\n _amount,\\n _decimals,\\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\\n );\\n\\n // Pay any leftover amount.\\n if (_leftoverAmount > 0) {\\n // If there's a default project ID, try to pay it.\\n if (_projectId != 0) {\\n _pay(\\n _projectId,\\n _token,\\n _leftoverAmount,\\n _decimals,\\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\\n ? defaultBeneficiary\\n : tx.origin,\\n _minReturnedTokens,\\n _preferClaimedTokens,\\n _memo,\\n _metadata\\n );\\n }\\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\\n else {\\n // Transfer the ETH.\\n if (_token == JBTokens.ETH)\\n Address.sendValue(\\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\\n _beneficiary != address(0) ? payable(_beneficiary) : defaultBeneficiary != address(0)\\n ? defaultBeneficiary\\n : payable(tx.origin),\\n _leftoverAmount\\n );\\n // Or, transfer the ERC20.\\n else\\n IERC20(_token).safeTransfer(\\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\\n ? defaultBeneficiary\\n : tx.origin,\\n _leftoverAmount\\n );\\n }\\n }\\n\\n emit Pay(\\n _projectId,\\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\\n ? defaultBeneficiary\\n : tx.origin,\\n _token,\\n _amount,\\n _decimals,\\n _leftoverAmount,\\n _minReturnedTokens,\\n _preferClaimedTokens,\\n _memo,\\n _metadata,\\n msg.sender\\n );\\n }\\n\\n /** \\n @notice \\n Add to the balance of the specified project after first splitting the amount among the stored default splits.\\n\\n @param _projectId The ID of the project that is being paid after.\\n @param _token The token being paid in.\\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\\n @param _memo A memo to pass along to the emitted event. \\n @param _metadata Extra data to pass along to the terminal.\\n */\\n function addToBalanceOf(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) public payable virtual override nonReentrant {\\n // ETH shouldn't be sent if this terminal's token isn't ETH.\\n if (address(_token) != JBTokens.ETH) {\\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\\n\\n // Get a reference to the balance before receiving tokens.\\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\\n\\n // Transfer tokens to this contract from the msg sender.\\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\\n\\n // The amount should reflect the change in balance.\\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\\n } else {\\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\\n _amount = msg.value;\\n _decimals = 18;\\n }\\n\\n // Pay the splits and get a reference to the amount leftover.\\n uint256 _leftoverAmount = _payToSplits(\\n defaultSplitsProjectId,\\n defaultSplitsDomain,\\n defaultSplitsGroup,\\n _token,\\n _amount,\\n _decimals,\\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\\n );\\n\\n // Distribute any leftover amount.\\n if (_leftoverAmount > 0) {\\n // If there's a default project ID, try to add to its balance.\\n if (_projectId != 0)\\n // Add to the project's balance.\\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\\n\\n // Otherwise, send a payment to the beneficiary.\\n else {\\n // Transfer the ETH.\\n if (_token == JBTokens.ETH)\\n Address.sendValue(\\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(tx.origin),\\n _leftoverAmount\\n );\\n // Or, transfer the ERC20.\\n else\\n IERC20(_token).safeTransfer(\\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\\n _leftoverAmount\\n );\\n }\\n }\\n\\n emit AddToBalance(\\n _projectId,\\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\\n _token,\\n _amount,\\n _decimals,\\n _leftoverAmount,\\n _memo,\\n _metadata,\\n msg.sender\\n );\\n }\\n\\n //*********************************************************************//\\n // ---------------------- internal transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n Split an amount between all splits.\\n\\n @param _splitsProjectId The ID of the project to which the splits belong.\\n @param _splitsDomain The splits domain to which the group belongs.\\n @param _splitsGroup The splits group to pay.\\n @param _token The token the amonut being split is in.\\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\\n @param _decimals The number of decimals in the `_amount` fixed point number. \\n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\\n\\n @return leftoverAmount The amount leftover after all splits were paid.\\n */\\n function _payToSplits(\\n uint256 _splitsProjectId,\\n uint256 _splitsDomain,\\n uint256 _splitsGroup,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n address _defaultBeneficiary\\n ) internal virtual returns (uint256 leftoverAmount) {\\n // Pay the splits.\\n leftoverAmount = _payTo(\\n splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup),\\n _token,\\n _amount,\\n _decimals,\\n _defaultBeneficiary\\n );\\n emit DistributeToSplitGroup(_splitsProjectId, _splitsDomain, _splitsGroup, msg.sender);\\n }\\n\\n /** \\n @notice \\n Split an amount between all splits.\\n\\n @param _splits The splits.\\n @param _token The token the amonut being split is in.\\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\\n @param _decimals The number of decimals in the `_amount` fixed point number. \\n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\\n\\n @return leftoverAmount The amount leftover after all splits were paid.\\n */\\n function _payTo(\\n JBSplit[] memory _splits,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n address _defaultBeneficiary\\n ) internal virtual returns (uint256 leftoverAmount) {\\n // Set the leftover amount to the initial balance.\\n leftoverAmount = _amount;\\n\\n // Settle between all splits.\\n for (uint256 i; i < _splits.length; ) {\\n // Get a reference to the split being iterated on.\\n JBSplit memory _split = _splits[i];\\n\\n // The amount to send towards the split.\\n uint256 _splitAmount = PRBMath.mulDiv(\\n _amount,\\n _split.percent,\\n JBConstants.SPLITS_TOTAL_PERCENT\\n );\\n\\n if (_splitAmount > 0) {\\n // Transfer tokens to the split.\\n // If there's an allocator set, transfer to its `allocate` function.\\n if (_split.allocator != IJBSplitAllocator(address(0))) {\\n // Create the data to send to the allocator.\\n JBSplitAllocationData memory _data = JBSplitAllocationData(\\n _token,\\n _splitAmount,\\n _decimals,\\n defaultProjectId,\\n 0,\\n _split\\n );\\n\\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\\n if (_token != JBTokens.ETH)\\n IERC20(_token).safeApprove(address(_split.allocator), _splitAmount);\\n\\n // If the token is ETH, send it in msg.value.\\n uint256 _payableValue = _token == JBTokens.ETH ? _splitAmount : 0;\\n\\n // Trigger the allocator's `allocate` function.\\n _split.allocator.allocate{value: _payableValue}(_data);\\n\\n // Otherwise, if a project is specified, make a payment to it.\\n } else if (_split.projectId != 0) {\\n if (_split.preferAddToBalance)\\n _addToBalanceOf(\\n _split.projectId,\\n _token,\\n _splitAmount,\\n _decimals,\\n defaultMemo,\\n defaultMetadata\\n );\\n else\\n _pay(\\n _split.projectId,\\n _token,\\n _splitAmount,\\n _decimals,\\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\\n 0,\\n _split.preferClaimed,\\n defaultMemo,\\n defaultMetadata\\n );\\n } else {\\n // Transfer the ETH.\\n if (_token == JBTokens.ETH)\\n Address.sendValue(\\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\\n _split.beneficiary != address(0) ? _split.beneficiary : payable(_defaultBeneficiary),\\n _splitAmount\\n );\\n // Or, transfer the ERC20.\\n else {\\n IERC20(_token).safeTransfer(\\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\\n _splitAmount\\n );\\n }\\n }\\n\\n // Subtract from the amount to be sent to the beneficiary.\\n leftoverAmount = leftoverAmount - _splitAmount;\\n }\\n\\n emit DistributeToSplit(_split, _splitAmount, _defaultBeneficiary, msg.sender);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x19b81077f19b544d6ad5c6b945584fd9187c774f0f85e2965475ade2da15ae42\",\"license\":\"MIT\"},\"contracts/JBETHERC20SplitsPayerDeployer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport { Clones } from '@openzeppelin/contracts/proxy/Clones.sol';\\n\\nimport './interfaces/IJBETHERC20SplitsPayerDeployer.sol';\\nimport './structs/JBSplit.sol';\\nimport './structs/JBGroupedSplits.sol';\\nimport './JBETHERC20SplitsPayer.sol';\\n\\n/** \\n @notice \\n Deploys splits payer contracts.\\n\\n @dev\\n Adheres to -\\n IJBETHERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n*/\\ncontract JBETHERC20SplitsPayerDeployer is IJBETHERC20SplitsPayerDeployer {\\n\\n address immutable implementation;\\n\\n IJBSplitsStore immutable splitsStore;\\n\\n constructor(IJBSplitsStore _splitsStore) {\\n implementation = address(new JBETHERC20SplitsPayer(_splitsStore));\\n splitsStore = _splitsStore;\\n }\\n\\n //*********************************************************************//\\n // ---------------------- external transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n Allows anyone to deploy a new splits payer contract.\\n\\n @dev\\n This contract must have Operator permissions over the SET_SPLITS permission of the specified `_defaultSplitsProjectId`.\\n\\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\\n @param _defaultSplits The splits to payout when this contract receives direct payments.\\n @param _splitsStore A contract that stores splits for each project.\\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \\n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \\n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \\n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\\n @param _owner The address that will own the splits payer.\\n\\n @return splitsPayer The splits payer contract.\\n */\\n function deploySplitsPayerWithSplits(\\n uint256 _defaultSplitsProjectId,\\n JBSplit[] memory _defaultSplits,\\n IJBSplitsStore _splitsStore,\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string memory _defaultMemo,\\n bytes memory _defaultMetadata,\\n bool _defaultPreferAddToBalance,\\n address _owner\\n ) external override returns (IJBSplitsPayer splitsPayer) {\\n // Use this contract's address as the domain.\\n uint256 _domain = uint256(uint160(address(this)));\\n\\n // Create the random hash using data unique to this instance that'll be used as the storage domain.\\n uint256 _group = uint256(keccak256(abi.encodePacked(msg.sender, block.number)));\\n\\n // Set the splits in the store.\\n JBGroupedSplits[] memory _groupedSplits;\\n _groupedSplits = new JBGroupedSplits[](1);\\n _groupedSplits[0] = JBGroupedSplits(_group, _defaultSplits);\\n _splitsStore.set(_defaultSplitsProjectId, _domain, _groupedSplits);\\n\\n return\\n deploySplitsPayer(\\n _defaultSplitsProjectId,\\n _domain,\\n _group,\\n _defaultProjectId,\\n _defaultBeneficiary,\\n _defaultPreferClaimedTokens,\\n _defaultMemo,\\n _defaultMetadata,\\n _defaultPreferAddToBalance,\\n _owner\\n );\\n }\\n\\n //*********************************************************************//\\n // ---------------------- public transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n Allows anyone to deploy a new splits payer contract.\\n\\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \\n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \\n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \\n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\\n @param _owner The address that will own the splits payer.\\n\\n @return splitsPayer The splits payer contract.\\n */\\n function deploySplitsPayer(\\n uint256 _defaultSplitsProjectId,\\n uint256 _defaultSplitsDomain,\\n uint256 _defaultSplitsGroup,\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string memory _defaultMemo,\\n bytes memory _defaultMetadata,\\n bool _defaultPreferAddToBalance,\\n address _owner\\n ) public override returns (IJBSplitsPayer splitsPayer) {\\n\\n // Deploy the splits payer.\\n splitsPayer = IJBSplitsPayer(payable(Clones.clone(implementation)));\\n\\n splitsPayer.initialize(\\n _defaultSplitsProjectId,\\n _defaultSplitsDomain,\\n _defaultSplitsGroup,\\n _defaultProjectId,\\n _defaultBeneficiary,\\n _defaultPreferClaimedTokens,\\n _defaultMemo,\\n _defaultMetadata,\\n _defaultPreferAddToBalance,\\n _owner\\n );\\n\\n emit DeploySplitsPayer(\\n splitsPayer,\\n _defaultSplitsProjectId,\\n _defaultSplitsDomain,\\n _defaultSplitsGroup,\\n splitsStore,\\n _defaultProjectId,\\n _defaultBeneficiary,\\n _defaultPreferClaimedTokens,\\n _defaultMemo,\\n _defaultMetadata,\\n _defaultPreferAddToBalance,\\n _owner,\\n msg.sender\\n );\\n }\\n}\\n\",\"keccak256\":\"0x1d772589f0079d573ea80929092e23a4b2bc9a41f0e930dc1efb10d7fc731d81\",\"license\":\"MIT\"},\"contracts/enums/JBBallotState.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nenum JBBallotState {\\n Active,\\n Approved,\\n Failed\\n}\\n\",\"keccak256\":\"0x891fcac63470398b3a11239da7feba6b07d640809fcefd2404303b823d7378f8\",\"license\":\"MIT\"},\"contracts/interfaces/IJBDirectory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBProjects.sol';\\n\\ninterface IJBDirectory {\\n event SetController(uint256 indexed projectId, address indexed controller, address caller);\\n\\n event AddTerminal(uint256 indexed projectId, IJBPaymentTerminal indexed terminal, address caller);\\n\\n event SetTerminals(uint256 indexed projectId, IJBPaymentTerminal[] terminals, address caller);\\n\\n event SetPrimaryTerminal(\\n uint256 indexed projectId,\\n address indexed token,\\n IJBPaymentTerminal indexed terminal,\\n address caller\\n );\\n\\n event SetIsAllowedToSetFirstController(address indexed addr, bool indexed flag, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function controllerOf(uint256 _projectId) external view returns (address);\\n\\n function isAllowedToSetFirstController(address _address) external view returns (bool);\\n\\n function terminalsOf(uint256 _projectId) external view returns (IJBPaymentTerminal[] memory);\\n\\n function isTerminalOf(uint256 _projectId, IJBPaymentTerminal _terminal)\\n external\\n view\\n returns (bool);\\n\\n function primaryTerminalOf(uint256 _projectId, address _token)\\n external\\n view\\n returns (IJBPaymentTerminal);\\n\\n function setControllerOf(uint256 _projectId, address _controller) external;\\n\\n function setTerminalsOf(uint256 _projectId, IJBPaymentTerminal[] calldata _terminals) external;\\n\\n function setPrimaryTerminalOf(\\n uint256 _projectId,\\n address _token,\\n IJBPaymentTerminal _terminal\\n ) external;\\n\\n function setIsAllowedToSetFirstController(address _address, bool _flag) external;\\n}\\n\",\"keccak256\":\"0x715321646db00514d1355ed43c40cd3f01e94959552fd07797b315d9c49cdb1d\",\"license\":\"MIT\"},\"contracts/interfaces/IJBETHERC20SplitsPayerDeployer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBSplitsPayer.sol';\\nimport './IJBSplitsStore.sol';\\n\\ninterface IJBETHERC20SplitsPayerDeployer {\\n event DeploySplitsPayer(\\n IJBSplitsPayer indexed splitsPayer,\\n uint256 defaultSplitsProjectId,\\n uint256 defaultSplitsDomain,\\n uint256 defaultSplitsGroup,\\n IJBSplitsStore splitsStore,\\n uint256 defaultProjectId,\\n address defaultBeneficiary,\\n bool defaultPreferClaimedTokens,\\n string defaultMemo,\\n bytes defaultMetadata,\\n bool preferAddToBalance,\\n address owner,\\n address caller\\n );\\n\\n function deploySplitsPayer(\\n uint256 _defaultSplitsProjectId,\\n uint256 _defaultSplitsDomain,\\n uint256 _defaultSplitsGroup,\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string calldata _defaultMemo,\\n bytes calldata _defaultMetadata,\\n bool _preferAddToBalance,\\n address _owner\\n ) external returns (IJBSplitsPayer splitsPayer);\\n\\n function deploySplitsPayerWithSplits(\\n uint256 _defaultSplitsProjectId,\\n JBSplit[] memory _defaultSplits,\\n IJBSplitsStore _splitsStore,\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string memory _defaultMemo,\\n bytes memory _defaultMetadata,\\n bool _defaultPreferAddToBalance,\\n address _owner\\n ) external returns (IJBSplitsPayer splitsPayer);\\n}\\n\",\"keccak256\":\"0xc476797aa84a54530cdbaff6a9e8c2fc8bf90a051dd51a17a00c51345db2798c\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleBallot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../enums/JBBallotState.sol';\\n\\ninterface IJBFundingCycleBallot is IERC165 {\\n function duration() external view returns (uint256);\\n\\n function stateOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n uint256 _start\\n ) external view returns (JBBallotState);\\n}\\n\",\"keccak256\":\"0x49553a56209237846bc400cf27f260824a6bd06fd8094a7eb5abb9de75779598\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../enums/JBBallotState.sol';\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBFundingCycleData.sol';\\n\\ninterface IJBFundingCycleStore {\\n event Configure(\\n uint256 indexed configuration,\\n uint256 indexed projectId,\\n JBFundingCycleData data,\\n uint256 metadata,\\n uint256 mustStartAtOrAfter,\\n address caller\\n );\\n\\n event Init(uint256 indexed configuration, uint256 indexed projectId, uint256 indexed basedOn);\\n\\n function latestConfigurationOf(uint256 _projectId) external view returns (uint256);\\n\\n function get(uint256 _projectId, uint256 _configuration)\\n external\\n view\\n returns (JBFundingCycle memory);\\n\\n function latestConfiguredOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBBallotState ballotState);\\n\\n function queuedOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentBallotStateOf(uint256 _projectId) external view returns (JBBallotState);\\n\\n function configureFor(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n uint256 _metadata,\\n uint256 _mustStartAtOrAfter\\n ) external returns (JBFundingCycle memory fundingCycle);\\n}\\n\",\"keccak256\":\"0xaead823851433be0c2ddc8f8086813e6cd647de3a1bc0f7570a5d6b38c378b5a\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\n\\ninterface IJBPaymentTerminal is IERC165 {\\n function acceptsToken(address _token, uint256 _projectId) external view returns (bool);\\n\\n function currencyForToken(address _token) external view returns (uint256);\\n\\n function decimalsForToken(address _token) external view returns (uint256);\\n\\n // Return value must be a fixed point number with 18 decimals.\\n function currentEthOverflowOf(uint256 _projectId) external view returns (uint256);\\n\\n function pay(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable returns (uint256 beneficiaryTokenCount);\\n\\n function addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable;\\n}\\n\",\"keccak256\":\"0xb7826f5ed609359ce322c09e83236c47ba385df1c3cad3607e56fd0a2e00eee2\",\"license\":\"MIT\"},\"contracts/interfaces/IJBProjectPayer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './IJBDirectory.sol';\\n\\ninterface IJBProjectPayer is IERC165 {\\n event SetDefaultValues(\\n uint256 indexed projectId,\\n address indexed beneficiary,\\n bool preferClaimedTokens,\\n string memo,\\n bytes metadata,\\n bool preferAddToBalance,\\n address caller\\n );\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function projectPayerDeployer() external view returns (address);\\n\\n function defaultProjectId() external view returns (uint256);\\n\\n function defaultBeneficiary() external view returns (address payable);\\n\\n function defaultPreferClaimedTokens() external view returns (bool);\\n\\n function defaultMemo() external view returns (string memory);\\n\\n function defaultMetadata() external view returns (bytes memory);\\n\\n function defaultPreferAddToBalance() external view returns (bool);\\n\\n function initialize(\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string memory _defaultMemo,\\n bytes memory _defaultMetadata,\\n bool _defaultPreferAddToBalance,\\n address _owner\\n ) external;\\n\\n function setDefaultValues(\\n uint256 _projectId,\\n address payable _beneficiary,\\n bool _preferClaimedTokens,\\n string memory _memo,\\n bytes memory _metadata,\\n bool _defaultPreferAddToBalance\\n ) external;\\n\\n function pay(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string memory _memo,\\n bytes memory _metadata\\n ) external payable;\\n\\n function addToBalanceOf(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n string memory _memo,\\n bytes memory _metadata\\n ) external payable;\\n\\n receive() external payable;\\n}\\n\",\"keccak256\":\"0x85f4cbd5482e26618994f742c149a5bd3cb3dc39dbeba85b21c36b3215007df6\",\"license\":\"MIT\"},\"contracts/interfaces/IJBProjects.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBTokenUriResolver.sol';\\n\\ninterface IJBProjects is IERC721 {\\n event Create(\\n uint256 indexed projectId,\\n address indexed owner,\\n JBProjectMetadata metadata,\\n address caller\\n );\\n\\n event SetMetadata(uint256 indexed projectId, JBProjectMetadata metadata, address caller);\\n\\n event SetTokenUriResolver(IJBTokenUriResolver indexed resolver, address caller);\\n\\n function count() external view returns (uint256);\\n\\n function metadataContentOf(uint256 _projectId, uint256 _domain)\\n external\\n view\\n returns (string memory);\\n\\n function tokenUriResolver() external view returns (IJBTokenUriResolver);\\n\\n function createFor(address _owner, JBProjectMetadata calldata _metadata)\\n external\\n returns (uint256 projectId);\\n\\n function setMetadataOf(uint256 _projectId, JBProjectMetadata calldata _metadata) external;\\n\\n function setTokenUriResolver(IJBTokenUriResolver _newResolver) external;\\n}\\n\",\"keccak256\":\"0x7cfc021d0bd7e73b1ba8f4845d7d35e3419d6a14d3d25ca3a8010e7f91062fe4\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSplitAllocator.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport '../structs/JBSplitAllocationData.sol';\\n\\n/**\\n @title\\n Split allocator\\n\\n @notice\\n Provide a way to process a single split with extra logic\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n\\n @dev\\n The contract address should be set as an allocator in the adequate split\\n*/\\ninterface IJBSplitAllocator is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.distributePayoutOf(..), during the processing of the split including it\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control. The token and/or eth are optimistically transfered\\n to the allocator for its logic.\\n \\n @param _data the data passed by the terminal, as a JBSplitAllocationData struct:\\n address token;\\n uint256 amount;\\n uint256 decimals;\\n uint256 projectId;\\n uint256 group;\\n JBSplit split;\\n */\\n function allocate(JBSplitAllocationData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0x5efb6f51fc161f42ff58989386ad99028e4039a0ba897d66f358c3dfcf686105\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSplitsPayer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBSplit.sol';\\nimport './../structs/JBGroupedSplits.sol';\\nimport './IJBSplitsStore.sol';\\n\\ninterface IJBSplitsPayer is IERC165 {\\n event SetDefaultSplitsReference(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n address caller\\n );\\n event Pay(\\n uint256 indexed projectId,\\n address beneficiary,\\n address token,\\n uint256 amount,\\n uint256 decimals,\\n uint256 leftoverAmount,\\n uint256 minReturnedTokens,\\n bool preferClaimedTokens,\\n string memo,\\n bytes metadata,\\n address caller\\n );\\n\\n event AddToBalance(\\n uint256 indexed projectId,\\n address beneficiary,\\n address token,\\n uint256 amount,\\n uint256 decimals,\\n uint256 leftoverAmount,\\n string memo,\\n bytes metadata,\\n address caller\\n );\\n\\n event DistributeToSplitGroup(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n address caller\\n );\\n\\n event DistributeToSplit(\\n JBSplit split,\\n uint256 amount,\\n address defaultBeneficiary,\\n address caller\\n );\\n\\n function defaultSplitsProjectId() external view returns (uint256);\\n\\n function defaultSplitsDomain() external view returns (uint256);\\n\\n function defaultSplitsGroup() external view returns (uint256);\\n\\n function splitsStore() external view returns (IJBSplitsStore);\\n\\n function initialize(\\n uint256 _defaultSplitsProjectId,\\n uint256 _defaultSplitsDomain,\\n uint256 _defaultSplitsGroup,\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string memory _defaultMemo,\\n bytes memory _defaultMetadata,\\n bool _preferAddToBalance,\\n address _owner\\n ) external;\\n\\n function setDefaultSplitsReference(\\n uint256 _projectId,\\n uint256 _domain,\\n uint256 _group\\n ) external;\\n\\n function setDefaultSplits(\\n uint256 _projectId,\\n uint256 _domain,\\n uint256 _group,\\n JBGroupedSplits[] memory _splitsGroup\\n ) external;\\n}\\n\",\"keccak256\":\"0xb37aebcf7b3db4d026d635212ff27fca7467e5d6c0084d8331819f41555d4f20\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSplitsStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBGroupedSplits.sol';\\nimport './../structs/JBSplit.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBProjects.sol';\\n\\ninterface IJBSplitsStore {\\n event SetSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n address caller\\n );\\n\\n function projects() external view returns (IJBProjects);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function splitsOf(\\n uint256 _projectId,\\n uint256 _domain,\\n uint256 _group\\n ) external view returns (JBSplit[] memory);\\n\\n function set(\\n uint256 _projectId,\\n uint256 _domain,\\n JBGroupedSplits[] memory _groupedSplits\\n ) external;\\n}\\n\",\"keccak256\":\"0x66dab3dd394e318b850401ca92c2963b906cc0ad5562fa5d4f6f850175d1c77a\",\"license\":\"MIT\"},\"contracts/interfaces/IJBTokenUriResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBTokenUriResolver {\\n function getUri(uint256 _projectId) external view returns (string memory tokenUri);\\n}\\n\",\"keccak256\":\"0xd267fd8ca7c21c2c71794acdb9a98314c33a35fc559e0bf0897a6686d196d174\",\"license\":\"MIT\"},\"contracts/libraries/JBConstants.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/**\\n @notice\\n Global constants used across Juicebox contracts.\\n*/\\nlibrary JBConstants {\\n uint256 public constant MAX_RESERVED_RATE = 10_000;\\n uint256 public constant MAX_REDEMPTION_RATE = 10_000;\\n uint256 public constant MAX_DISCOUNT_RATE = 1_000_000_000;\\n uint256 public constant SPLITS_TOTAL_PERCENT = 1_000_000_000;\\n uint256 public constant MAX_FEE = 1_000_000_000;\\n uint256 public constant MAX_FEE_DISCOUNT = 1_000_000_000;\\n}\\n\",\"keccak256\":\"0x34362846a1cd428a8bdedf4ab6857e11402f345cb87b994b2e7fb6d2474b808d\",\"license\":\"MIT\"},\"contracts/libraries/JBTokens.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBTokens {\\n /** \\n @notice \\n The ETH token address in Juicebox is represented by 0x000000000000000000000000000000000000EEEe.\\n */\\n address public constant ETH = address(0x000000000000000000000000000000000000EEEe);\\n}\\n\",\"keccak256\":\"0xecf82992f7b827766aa55f16872517a646521eef414d8cc9786617ea377e5463\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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.\\n @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.\\n @member basedOn The `configuration` of the funding cycle that was active when this cycle was created.\\n @member start The timestamp marking the moment from which the funding cycle is considered active. It is a unix timestamp measured in seconds.\\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n @member metadata Extra data that can be associated with a funding cycle.\\n*/\\nstruct JBFundingCycle {\\n uint256 number;\\n uint256 configuration;\\n uint256 basedOn;\\n uint256 start;\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n uint256 metadata;\\n}\\n\",\"keccak256\":\"0xcdd3ac9b6fa67e62ada88d09b73bc35ade1cd77d43db712289266a788928b4c2\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycleData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n*/\\nstruct JBFundingCycleData {\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n}\\n\",\"keccak256\":\"0x2aa6368bf4dfc5797e8b02a978293de0c777fae2658de2c825a103587240f3b0\",\"license\":\"MIT\"},\"contracts/structs/JBGroupedSplits.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBSplit.sol';\\n\\n/** \\n @member group The group indentifier.\\n @member splits The splits to associate with the group.\\n*/\\nstruct JBGroupedSplits {\\n uint256 group;\\n JBSplit[] splits;\\n}\\n\",\"keccak256\":\"0x80be1b220da4ac04851ea540ebb94c1ec2b0442ec5bd1e88fdf78a56becd8b5a\",\"license\":\"MIT\"},\"contracts/structs/JBProjectMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member content The metadata content.\\n @member domain The domain within which the metadata applies.\\n*/\\nstruct JBProjectMetadata {\\n string content;\\n uint256 domain;\\n}\\n\",\"keccak256\":\"0x90ad7b1014c0a9f945fe7a2efde9d5de41e40574fa27969070b1d2ff52033ea0\",\"license\":\"MIT\"},\"contracts/structs/JBSplit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBSplitAllocator.sol';\\n\\n/** \\n @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.\\n @member preferAddToBalance A flag indicating if a distribution to a project should prefer triggering it's addToBalance function instead of its pay function.\\n @member percent The percent of the whole group that this split occupies. This number is out of `JBConstants.SPLITS_TOTAL_PERCENT`.\\n @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.\\n @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.\\n @member lockedUntil Specifies if the split should be unchangeable until the specified time, with the exception of extending the locked period.\\n @member allocator If an allocator is specified, funds will be sent to the allocator contract along with all properties of this split.\\n*/\\nstruct JBSplit {\\n bool preferClaimed;\\n bool preferAddToBalance;\\n uint256 percent;\\n uint256 projectId;\\n address payable beneficiary;\\n uint256 lockedUntil;\\n IJBSplitAllocator allocator;\\n}\\n\",\"keccak256\":\"0xc80a16606da8abf76d0f73abc38aee041e24f29342c1939018f70c286e89f105\",\"license\":\"MIT\"},\"contracts/structs/JBSplitAllocationData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBSplit.sol';\\n\\n/** \\n @member token The token being sent to the split allocator.\\n @member amount The amount being sent to the split allocator, as a fixed point number.\\n @member decimals The number of decimals in the amount.\\n @member projectId The project to which the split belongs.\\n @member group The group to which the split belongs.\\n @member split The split that caused the allocation.\\n*/\\nstruct JBSplitAllocationData {\\n address token;\\n uint256 amount;\\n uint256 decimals;\\n uint256 projectId;\\n uint256 group;\\n JBSplit split;\\n}\\n\",\"keccak256\":\"0x39f5c41bd31d36774744698ac94484b6cab62d7038df2f29d947668959782e63\",\"license\":\"MIT\"},\"prb-math/contracts/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivFixedPointOverflow(uint256 prod1);\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivOverflow(uint256 prod1, uint256 denominator);\\n\\n/// @notice Emitted when one of the inputs is type(int256).min.\\nerror PRBMath__MulDivSignedInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows int256.\\nerror PRBMath__MulDivSignedOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is MIN_SD59x18.\\nerror PRBMathSD59x18__AbsInputTooSmall();\\n\\n/// @notice Emitted when ceiling a number overflows SD59x18.\\nerror PRBMathSD59x18__CeilOverflow(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__DivInputTooSmall();\\n\\n/// @notice Emitted when one of the intermediary unsigned results overflows SD59x18.\\nerror PRBMathSD59x18__DivOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathSD59x18__ExpInputTooBig(int256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathSD59x18__Exp2InputTooBig(int256 x);\\n\\n/// @notice Emitted when flooring a number underflows SD59x18.\\nerror PRBMathSD59x18__FloorUnderflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format overflows SD59x18.\\nerror PRBMathSD59x18__FromIntOverflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format underflows SD59x18.\\nerror PRBMathSD59x18__FromIntUnderflow(int256 x);\\n\\n/// @notice Emitted when the product of the inputs is negative.\\nerror PRBMathSD59x18__GmNegativeProduct(int256 x, int256 y);\\n\\n/// @notice Emitted when multiplying the inputs overflows SD59x18.\\nerror PRBMathSD59x18__GmOverflow(int256 x, int256 y);\\n\\n/// @notice Emitted when the input is less than or equal to zero.\\nerror PRBMathSD59x18__LogInputTooSmall(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__MulInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__MulOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__PowuOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is negative.\\nerror PRBMathSD59x18__SqrtNegativeInput(int256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows SD59x18.\\nerror PRBMathSD59x18__SqrtOverflow(int256 x);\\n\\n/// @notice Emitted when addition overflows UD60x18.\\nerror PRBMathUD60x18__AddOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when ceiling a number overflows UD60x18.\\nerror PRBMathUD60x18__CeilOverflow(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathUD60x18__ExpInputTooBig(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathUD60x18__Exp2InputTooBig(uint256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format format overflows UD60x18.\\nerror PRBMathUD60x18__FromUintOverflow(uint256 x);\\n\\n/// @notice Emitted when multiplying the inputs overflows UD60x18.\\nerror PRBMathUD60x18__GmOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when the input is less than 1.\\nerror PRBMathUD60x18__LogInputTooSmall(uint256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows UD60x18.\\nerror PRBMathUD60x18__SqrtOverflow(uint256 x);\\n\\n/// @notice Emitted when subtraction underflows UD60x18.\\nerror PRBMathUD60x18__SubUnderflow(uint256 x, uint256 y);\\n\\n/// @dev Common mathematical functions used in both PRBMathSD59x18 and PRBMathUD60x18. Note that this shared library\\n/// does not always assume the signed 59.18-decimal fixed-point or the unsigned 60.18-decimal fixed-point\\n/// representation. When it does not, it is explicitly mentioned in the NatSpec documentation.\\nlibrary PRBMath {\\n /// STRUCTS ///\\n\\n struct SD59x18 {\\n int256 value;\\n }\\n\\n struct UD60x18 {\\n uint256 value;\\n }\\n\\n /// STORAGE ///\\n\\n /// @dev How many trailing decimals can be represented.\\n uint256 internal constant SCALE = 1e18;\\n\\n /// @dev Largest power of two divisor of SCALE.\\n uint256 internal constant SCALE_LPOTD = 262144;\\n\\n /// @dev SCALE inverted mod 2^256.\\n uint256 internal constant SCALE_INVERSE =\\n 78156646155174841979727994598816262306175212592076161876661_508869554232690281;\\n\\n /// FUNCTIONS ///\\n\\n /// @notice Calculates the binary exponent of x using the binary fraction method.\\n /// @dev Has to use 192.64-bit fixed-point numbers.\\n /// See https://ethereum.stackexchange.com/a/96594/24693.\\n /// @param x The exponent as an unsigned 192.64-bit fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp2(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n // Start from 0.5 in the 192.64-bit fixed-point format.\\n result = 0x800000000000000000000000000000000000000000000000;\\n\\n // Multiply the result by root(2, 2^-i) when the bit at position i is 1. None of the intermediary results overflows\\n // because the initial result is 2^191 and all magic factors are less than 2^65.\\n if (x & 0x8000000000000000 > 0) {\\n result = (result * 0x16A09E667F3BCC909) >> 64;\\n }\\n if (x & 0x4000000000000000 > 0) {\\n result = (result * 0x1306FE0A31B7152DF) >> 64;\\n }\\n if (x & 0x2000000000000000 > 0) {\\n result = (result * 0x1172B83C7D517ADCE) >> 64;\\n }\\n if (x & 0x1000000000000000 > 0) {\\n result = (result * 0x10B5586CF9890F62A) >> 64;\\n }\\n if (x & 0x800000000000000 > 0) {\\n result = (result * 0x1059B0D31585743AE) >> 64;\\n }\\n if (x & 0x400000000000000 > 0) {\\n result = (result * 0x102C9A3E778060EE7) >> 64;\\n }\\n if (x & 0x200000000000000 > 0) {\\n result = (result * 0x10163DA9FB33356D8) >> 64;\\n }\\n if (x & 0x100000000000000 > 0) {\\n result = (result * 0x100B1AFA5ABCBED61) >> 64;\\n }\\n if (x & 0x80000000000000 > 0) {\\n result = (result * 0x10058C86DA1C09EA2) >> 64;\\n }\\n if (x & 0x40000000000000 > 0) {\\n result = (result * 0x1002C605E2E8CEC50) >> 64;\\n }\\n if (x & 0x20000000000000 > 0) {\\n result = (result * 0x100162F3904051FA1) >> 64;\\n }\\n if (x & 0x10000000000000 > 0) {\\n result = (result * 0x1000B175EFFDC76BA) >> 64;\\n }\\n if (x & 0x8000000000000 > 0) {\\n result = (result * 0x100058BA01FB9F96D) >> 64;\\n }\\n if (x & 0x4000000000000 > 0) {\\n result = (result * 0x10002C5CC37DA9492) >> 64;\\n }\\n if (x & 0x2000000000000 > 0) {\\n result = (result * 0x1000162E525EE0547) >> 64;\\n }\\n if (x & 0x1000000000000 > 0) {\\n result = (result * 0x10000B17255775C04) >> 64;\\n }\\n if (x & 0x800000000000 > 0) {\\n result = (result * 0x1000058B91B5BC9AE) >> 64;\\n }\\n if (x & 0x400000000000 > 0) {\\n result = (result * 0x100002C5C89D5EC6D) >> 64;\\n }\\n if (x & 0x200000000000 > 0) {\\n result = (result * 0x10000162E43F4F831) >> 64;\\n }\\n if (x & 0x100000000000 > 0) {\\n result = (result * 0x100000B1721BCFC9A) >> 64;\\n }\\n if (x & 0x80000000000 > 0) {\\n result = (result * 0x10000058B90CF1E6E) >> 64;\\n }\\n if (x & 0x40000000000 > 0) {\\n result = (result * 0x1000002C5C863B73F) >> 64;\\n }\\n if (x & 0x20000000000 > 0) {\\n result = (result * 0x100000162E430E5A2) >> 64;\\n }\\n if (x & 0x10000000000 > 0) {\\n result = (result * 0x1000000B172183551) >> 64;\\n }\\n if (x & 0x8000000000 > 0) {\\n result = (result * 0x100000058B90C0B49) >> 64;\\n }\\n if (x & 0x4000000000 > 0) {\\n result = (result * 0x10000002C5C8601CC) >> 64;\\n }\\n if (x & 0x2000000000 > 0) {\\n result = (result * 0x1000000162E42FFF0) >> 64;\\n }\\n if (x & 0x1000000000 > 0) {\\n result = (result * 0x10000000B17217FBB) >> 64;\\n }\\n if (x & 0x800000000 > 0) {\\n result = (result * 0x1000000058B90BFCE) >> 64;\\n }\\n if (x & 0x400000000 > 0) {\\n result = (result * 0x100000002C5C85FE3) >> 64;\\n }\\n if (x & 0x200000000 > 0) {\\n result = (result * 0x10000000162E42FF1) >> 64;\\n }\\n if (x & 0x100000000 > 0) {\\n result = (result * 0x100000000B17217F8) >> 64;\\n }\\n if (x & 0x80000000 > 0) {\\n result = (result * 0x10000000058B90BFC) >> 64;\\n }\\n if (x & 0x40000000 > 0) {\\n result = (result * 0x1000000002C5C85FE) >> 64;\\n }\\n if (x & 0x20000000 > 0) {\\n result = (result * 0x100000000162E42FF) >> 64;\\n }\\n if (x & 0x10000000 > 0) {\\n result = (result * 0x1000000000B17217F) >> 64;\\n }\\n if (x & 0x8000000 > 0) {\\n result = (result * 0x100000000058B90C0) >> 64;\\n }\\n if (x & 0x4000000 > 0) {\\n result = (result * 0x10000000002C5C860) >> 64;\\n }\\n if (x & 0x2000000 > 0) {\\n result = (result * 0x1000000000162E430) >> 64;\\n }\\n if (x & 0x1000000 > 0) {\\n result = (result * 0x10000000000B17218) >> 64;\\n }\\n if (x & 0x800000 > 0) {\\n result = (result * 0x1000000000058B90C) >> 64;\\n }\\n if (x & 0x400000 > 0) {\\n result = (result * 0x100000000002C5C86) >> 64;\\n }\\n if (x & 0x200000 > 0) {\\n result = (result * 0x10000000000162E43) >> 64;\\n }\\n if (x & 0x100000 > 0) {\\n result = (result * 0x100000000000B1721) >> 64;\\n }\\n if (x & 0x80000 > 0) {\\n result = (result * 0x10000000000058B91) >> 64;\\n }\\n if (x & 0x40000 > 0) {\\n result = (result * 0x1000000000002C5C8) >> 64;\\n }\\n if (x & 0x20000 > 0) {\\n result = (result * 0x100000000000162E4) >> 64;\\n }\\n if (x & 0x10000 > 0) {\\n result = (result * 0x1000000000000B172) >> 64;\\n }\\n if (x & 0x8000 > 0) {\\n result = (result * 0x100000000000058B9) >> 64;\\n }\\n if (x & 0x4000 > 0) {\\n result = (result * 0x10000000000002C5D) >> 64;\\n }\\n if (x & 0x2000 > 0) {\\n result = (result * 0x1000000000000162E) >> 64;\\n }\\n if (x & 0x1000 > 0) {\\n result = (result * 0x10000000000000B17) >> 64;\\n }\\n if (x & 0x800 > 0) {\\n result = (result * 0x1000000000000058C) >> 64;\\n }\\n if (x & 0x400 > 0) {\\n result = (result * 0x100000000000002C6) >> 64;\\n }\\n if (x & 0x200 > 0) {\\n result = (result * 0x10000000000000163) >> 64;\\n }\\n if (x & 0x100 > 0) {\\n result = (result * 0x100000000000000B1) >> 64;\\n }\\n if (x & 0x80 > 0) {\\n result = (result * 0x10000000000000059) >> 64;\\n }\\n if (x & 0x40 > 0) {\\n result = (result * 0x1000000000000002C) >> 64;\\n }\\n if (x & 0x20 > 0) {\\n result = (result * 0x10000000000000016) >> 64;\\n }\\n if (x & 0x10 > 0) {\\n result = (result * 0x1000000000000000B) >> 64;\\n }\\n if (x & 0x8 > 0) {\\n result = (result * 0x10000000000000006) >> 64;\\n }\\n if (x & 0x4 > 0) {\\n result = (result * 0x10000000000000003) >> 64;\\n }\\n if (x & 0x2 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n if (x & 0x1 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n\\n // We're doing two things at the same time:\\n //\\n // 1. Multiply the result by 2^n + 1, where \\\"2^n\\\" is the integer part and the one is added to account for\\n // the fact that we initially set the result to 0.5. This is accomplished by subtracting from 191\\n // rather than 192.\\n // 2. Convert the result to the unsigned 60.18-decimal fixed-point format.\\n //\\n // This works because 2^(191-ip) = 2^ip / 2^191, where \\\"ip\\\" is the integer part \\\"2^n\\\".\\n result *= SCALE;\\n result >>= (191 - (x >> 64));\\n }\\n }\\n\\n /// @notice Finds the zero-based index of the first one in the binary representation of x.\\n /// @dev See the note on msb in the \\\"Find First Set\\\" Wikipedia article https://en.wikipedia.org/wiki/Find_first_set\\n /// @param x The uint256 number for which to find the index of the most significant bit.\\n /// @return msb The index of the most significant bit as an uint256.\\n function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\\n if (x >= 2**128) {\\n x >>= 128;\\n msb += 128;\\n }\\n if (x >= 2**64) {\\n x >>= 64;\\n msb += 64;\\n }\\n if (x >= 2**32) {\\n x >>= 32;\\n msb += 32;\\n }\\n if (x >= 2**16) {\\n x >>= 16;\\n msb += 16;\\n }\\n if (x >= 2**8) {\\n x >>= 8;\\n msb += 8;\\n }\\n if (x >= 2**4) {\\n x >>= 4;\\n msb += 4;\\n }\\n if (x >= 2**2) {\\n x >>= 2;\\n msb += 2;\\n }\\n if (x >= 2**1) {\\n // No need to shift x any more.\\n msb += 1;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.\\n ///\\n /// Requirements:\\n /// - The denominator cannot be zero.\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The multiplicand as an uint256.\\n /// @param y The multiplier as an uint256.\\n /// @param denominator The divisor as an uint256.\\n /// @return result The result as an uint256.\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n unchecked {\\n result = prod0 / denominator;\\n }\\n return result;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n if (prod1 >= denominator) {\\n revert PRBMath__MulDivOverflow(prod1, denominator);\\n }\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n unchecked {\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 lpotdod = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by lpotdod.\\n denominator := div(denominator, lpotdod)\\n\\n // Divide [prod1 prod0] by lpotdod.\\n prod0 := div(prod0, lpotdod)\\n\\n // Flip lpotdod such that it is 2^256 / lpotdod. If lpotdod is zero, then it becomes one.\\n lpotdod := add(div(sub(0, lpotdod), lpotdod), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * lpotdod;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f71e18) with full precision.\\n ///\\n /// @dev Variant of \\\"mulDiv\\\" with constant folding, i.e. in which the denominator is always 1e18. Before returning the\\n /// final result, we add 1 if (x * y) % SCALE >= HALF_SCALE. Without this, 6.6e-19 would be truncated to 0 instead of\\n /// being rounded to 1e-18. See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717.\\n ///\\n /// Requirements:\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - The body is purposely left uncommented; see the NatSpec comments in \\\"PRBMath.mulDiv\\\" to understand how this works.\\n /// - It is assumed that the result can never be type(uint256).max when x and y solve the following two equations:\\n /// 1. x * y = type(uint256).max * SCALE\\n /// 2. (x * y) % SCALE >= SCALE / 2\\n ///\\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function mulDivFixedPoint(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n uint256 prod0;\\n uint256 prod1;\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n if (prod1 >= SCALE) {\\n revert PRBMath__MulDivFixedPointOverflow(prod1);\\n }\\n\\n uint256 remainder;\\n uint256 roundUpUnit;\\n assembly {\\n remainder := mulmod(x, y, SCALE)\\n roundUpUnit := gt(remainder, 499999999999999999)\\n }\\n\\n if (prod1 == 0) {\\n unchecked {\\n result = (prod0 / SCALE) + roundUpUnit;\\n return result;\\n }\\n }\\n\\n assembly {\\n result := add(\\n mul(\\n or(\\n div(sub(prod0, remainder), SCALE_LPOTD),\\n mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, SCALE_LPOTD), SCALE_LPOTD), 1))\\n ),\\n SCALE_INVERSE\\n ),\\n roundUpUnit\\n )\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev An extension of \\\"mulDiv\\\" for signed numbers. Works by computing the signs and the absolute values separately.\\n ///\\n /// Requirements:\\n /// - None of the inputs can be type(int256).min.\\n /// - The result must fit within int256.\\n ///\\n /// @param x The multiplicand as an int256.\\n /// @param y The multiplier as an int256.\\n /// @param denominator The divisor as an int256.\\n /// @return result The result as an int256.\\n function mulDivSigned(\\n int256 x,\\n int256 y,\\n int256 denominator\\n ) internal pure returns (int256 result) {\\n if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {\\n revert PRBMath__MulDivSignedInputTooSmall();\\n }\\n\\n // Get hold of the absolute values of x, y and the denominator.\\n uint256 ax;\\n uint256 ay;\\n uint256 ad;\\n unchecked {\\n ax = x < 0 ? uint256(-x) : uint256(x);\\n ay = y < 0 ? uint256(-y) : uint256(y);\\n ad = denominator < 0 ? uint256(-denominator) : uint256(denominator);\\n }\\n\\n // Compute the absolute value of (x*y)\\u00f7denominator. The result must fit within int256.\\n uint256 rAbs = mulDiv(ax, ay, ad);\\n if (rAbs > uint256(type(int256).max)) {\\n revert PRBMath__MulDivSignedOverflow(rAbs);\\n }\\n\\n // Get the signs of x, y and the denominator.\\n uint256 sx;\\n uint256 sy;\\n uint256 sd;\\n assembly {\\n sx := sgt(x, sub(0, 1))\\n sy := sgt(y, sub(0, 1))\\n sd := sgt(denominator, sub(0, 1))\\n }\\n\\n // XOR over sx, sy and sd. This is checking whether there are one or three negative signs in the inputs.\\n // If yes, the result should be negative.\\n result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs);\\n }\\n\\n /// @notice Calculates the square root of x, rounding down.\\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The uint256 number for which to calculate the square root.\\n /// @return result The result as an uint256.\\n function sqrt(uint256 x) internal pure returns (uint256 result) {\\n if (x == 0) {\\n return 0;\\n }\\n\\n // Set the initial guess to the closest power of two that is higher than x.\\n uint256 xAux = uint256(x);\\n result = 1;\\n if (xAux >= 0x100000000000000000000000000000000) {\\n xAux >>= 128;\\n result <<= 64;\\n }\\n if (xAux >= 0x10000000000000000) {\\n xAux >>= 64;\\n result <<= 32;\\n }\\n if (xAux >= 0x100000000) {\\n xAux >>= 32;\\n result <<= 16;\\n }\\n if (xAux >= 0x10000) {\\n xAux >>= 16;\\n result <<= 8;\\n }\\n if (xAux >= 0x100) {\\n xAux >>= 8;\\n result <<= 4;\\n }\\n if (xAux >= 0x10) {\\n xAux >>= 4;\\n result <<= 2;\\n }\\n if (xAux >= 0x8) {\\n result <<= 1;\\n }\\n\\n // The operations can never overflow because the result is max 2^127 when it enters this block.\\n unchecked {\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1; // Seven iterations should be enough\\n uint256 roundedDownResult = x / result;\\n return result >= roundedDownResult ? roundedDownResult : result;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x62cbabae4910e168e99b9c2c3e3b5c9c7ad5e7abd961dcc63b7ea3d83d8ea87e\",\"license\":\"Unlicense\"}},\"version\":1}", + "metadata": "{\"compiler\":{\"version\":\"0.8.16+commit.07a7930e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IJBSplitsStore\",\"name\":\"_splitsStore\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IJBSplitsPayer\",\"name\":\"splitsPayer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"defaultSplitsProjectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"defaultSplitsDomain\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"defaultSplitsGroup\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"contract IJBSplitsStore\",\"name\":\"splitsStore\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"defaultProjectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"defaultBeneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"defaultPreferClaimedTokens\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"defaultMemo\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"defaultMetadata\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"preferAddToBalance\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"DeploySplitsPayer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_defaultSplitsProjectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_defaultSplitsDomain\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_defaultSplitsGroup\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_defaultProjectId\",\"type\":\"uint256\"},{\"internalType\":\"address payable\",\"name\":\"_defaultBeneficiary\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_defaultPreferClaimedTokens\",\"type\":\"bool\"},{\"internalType\":\"string\",\"name\":\"_defaultMemo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_defaultMetadata\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"_defaultPreferAddToBalance\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"deploySplitsPayer\",\"outputs\":[{\"internalType\":\"contract IJBSplitsPayer\",\"name\":\"splitsPayer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_defaultSplitsProjectId\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"preferClaimed\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"preferAddToBalance\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"percent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"lockedUntil\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBSplitAllocator\",\"name\":\"allocator\",\"type\":\"address\"}],\"internalType\":\"struct JBSplit[]\",\"name\":\"_defaultSplits\",\"type\":\"tuple[]\"},{\"internalType\":\"contract IJBSplitsStore\",\"name\":\"_splitsStore\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_defaultProjectId\",\"type\":\"uint256\"},{\"internalType\":\"address payable\",\"name\":\"_defaultBeneficiary\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_defaultPreferClaimedTokens\",\"type\":\"bool\"},{\"internalType\":\"string\",\"name\":\"_defaultMemo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_defaultMetadata\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"_defaultPreferAddToBalance\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"deploySplitsPayerWithSplits\",\"outputs\":[{\"internalType\":\"contract IJBSplitsPayer\",\"name\":\"splitsPayer\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Adheres to - IJBGasTokenERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\",\"kind\":\"dev\",\"methods\":{\"deploySplitsPayer(uint256,uint256,uint256,uint256,address,bool,string,bytes,bool,address)\":{\"params\":{\"_defaultBeneficiary\":\"The address that'll receive the project's tokens when the splits payer receives payments. \",\"_defaultMemo\":\"The memo that'll be forwarded with the splits payer's received payments. \",\"_defaultMetadata\":\"The metadata that'll be forwarded with the splits payer's received payments. \",\"_defaultPreferAddToBalance\":\"A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\",\"_defaultPreferClaimedTokens\":\"A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \",\"_defaultProjectId\":\"The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\",\"_defaultSplitsDomain\":\"The splits domain to payout when this contract receives direct payments.\",\"_defaultSplitsGroup\":\"The splits group to payout when this contract receives direct payments.\",\"_defaultSplitsProjectId\":\"The ID of project for which the default splits are stored.\",\"_owner\":\"The address that will own the splits payer.\"},\"returns\":{\"splitsPayer\":\"The splits payer contract.\"}},\"deploySplitsPayerWithSplits(uint256,(bool,bool,uint256,uint256,address,uint256,address)[],address,uint256,address,bool,string,bytes,bool,address)\":{\"details\":\"This contract must have Operator permissions over the SET_SPLITS permission of the specified `_defaultSplitsProjectId`.\",\"params\":{\"_defaultBeneficiary\":\"The address that'll receive the project's tokens when the splits payer receives payments. \",\"_defaultMemo\":\"The memo that'll be forwarded with the splits payer's received payments. \",\"_defaultMetadata\":\"The metadata that'll be forwarded with the splits payer's received payments. \",\"_defaultPreferAddToBalance\":\"A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\",\"_defaultPreferClaimedTokens\":\"A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \",\"_defaultProjectId\":\"The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\",\"_defaultSplits\":\"The splits to payout when this contract receives direct payments.\",\"_defaultSplitsProjectId\":\"The ID of project for which the default splits are stored.\",\"_owner\":\"The address that will own the splits payer.\",\"_splitsStore\":\"A contract that stores splits for each project.\"},\"returns\":{\"splitsPayer\":\"The splits payer contract.\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"deploySplitsPayer(uint256,uint256,uint256,uint256,address,bool,string,bytes,bool,address)\":{\"notice\":\" Allows anyone to deploy a new splits payer contract.\"},\"deploySplitsPayerWithSplits(uint256,(bool,bool,uint256,uint256,address,uint256,address)[],address,uint256,address,bool,string,bytes,bool,address)\":{\"notice\":\" Allows anyone to deploy a new splits payer contract.\"}},\"notice\":\" Deploys splits payer contracts.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/JBGasTokenERC20SplitsPayerDeployer.sol\":\"JBGasTokenERC20SplitsPayerDeployer\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0x24e0364e503a9bbde94c715d26573a76f14cd2a202d45f96f52134ab806b67b9\",\"license\":\"MIT\"},\"@openzeppelin/contracts/proxy/Clones.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/Clones.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for\\n * deploying minimal proxy contracts, also known as \\\"clones\\\".\\n *\\n * > To simply and cheaply clone contract functionality in an immutable way, this standard specifies\\n * > a minimal bytecode implementation that delegates all calls to a known, fixed address.\\n *\\n * The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2`\\n * (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the\\n * deterministic method.\\n *\\n * _Available since v3.4._\\n */\\nlibrary Clones {\\n /**\\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.\\n *\\n * This function uses the create opcode, which should never revert.\\n */\\n function clone(address implementation) internal returns (address instance) {\\n assembly {\\n let ptr := mload(0x40)\\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\\n mstore(add(ptr, 0x14), shl(0x60, implementation))\\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\\n instance := create(0, ptr, 0x37)\\n }\\n require(instance != address(0), \\\"ERC1167: create failed\\\");\\n }\\n\\n /**\\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.\\n *\\n * This function uses the create2 opcode and a `salt` to deterministically deploy\\n * the clone. Using the same `implementation` and `salt` multiple time will revert, since\\n * the clones cannot be deployed twice at the same address.\\n */\\n function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) {\\n assembly {\\n let ptr := mload(0x40)\\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\\n mstore(add(ptr, 0x14), shl(0x60, implementation))\\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\\n instance := create2(0, ptr, 0x37, salt)\\n }\\n require(instance != address(0), \\\"ERC1167: create2 failed\\\");\\n }\\n\\n /**\\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\\n */\\n function predictDeterministicAddress(\\n address implementation,\\n bytes32 salt,\\n address deployer\\n ) internal pure returns (address predicted) {\\n assembly {\\n let ptr := mload(0x40)\\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\\n mstore(add(ptr, 0x14), shl(0x60, implementation))\\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf3ff00000000000000000000000000000000)\\n mstore(add(ptr, 0x38), shl(0x60, deployer))\\n mstore(add(ptr, 0x4c), salt)\\n mstore(add(ptr, 0x6c), keccak256(ptr, 0x37))\\n predicted := keccak256(add(ptr, 0x37), 0x55)\\n }\\n }\\n\\n /**\\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\\n */\\n function predictDeterministicAddress(address implementation, bytes32 salt)\\n internal\\n view\\n returns (address predicted)\\n {\\n return predictDeterministicAddress(implementation, salt, address(this));\\n }\\n}\\n\",\"keccak256\":\"0x1cc0efb01cbf008b768fd7b334786a6e358809198bb7e67f1c530af4957c6a21\",\"license\":\"MIT\"},\"@openzeppelin/contracts/security/ReentrancyGuard.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuard {\\n // Booleans are more expensive than uint256 or any type that takes up a full\\n // word because each write operation emits an extra SLOAD to first read the\\n // slot's contents, replace the bits taken up by the boolean, and then write\\n // back. This is the compiler's defense against contract upgrades and\\n // pointer aliasing, and it cannot be disabled.\\n\\n // The values being non-zero value makes deployment a bit more expensive,\\n // but in exchange the refund on every call to nonReentrant will be lower in\\n // amount. Since refunds are capped to a percentage of the total\\n // transaction's gas, it is best to keep them low in cases like this one, to\\n // increase the likelihood of the full refund coming into effect.\\n uint256 private constant _NOT_ENTERED = 1;\\n uint256 private constant _ENTERED = 2;\\n\\n uint256 private _status;\\n\\n constructor() {\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and making it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n // On the first call to nonReentrant, _notEntered will be true\\n require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n _status = _ENTERED;\\n\\n _;\\n\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n _status = _NOT_ENTERED;\\n }\\n}\\n\",\"keccak256\":\"0x0e9621f60b2faabe65549f7ed0f24e8853a45c1b7990d47e8160e523683f3935\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address sender,\\n address recipient,\\n uint256 amount\\n ) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0x61437cb513a887a1bbad006e7b1c8b414478427d33de47c5600af3c748f108da\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(\\n IERC20 token,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(\\n IERC20 token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) {\\n // Return data is optional\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xc3d946432c0ddbb1f846a0d3985be71299df331b91d06732152117f62f0be2b5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool _approved) external;\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x516a22876c1fab47f49b1bc22b4614491cd05338af8bd2e7b382da090a079990\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3777e696b62134e6177440dbe6e6601c0c156a443f57167194b67e75527439de\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"@paulrberg/contracts/math/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\nimport \\\"prb-math/contracts/PRBMath.sol\\\";\\n\",\"keccak256\":\"0x42821345981bc0434a90ba2268a2f5278dfe9e38166981d72fc7f3b776a29495\",\"license\":\"Unlicense\"},\"contracts/JBGasTokenERC20ProjectPayer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport '@openzeppelin/contracts/access/Ownable.sol';\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\\nimport './interfaces/IJBProjectPayer.sol';\\nimport './libraries/JBTokens.sol';\\n\\n/** \\n @notice \\n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\\n\\n @dev\\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\\n\\n @dev\\n Adheres to -\\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n\\n @dev\\n Inherits from -\\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\\n ERC165: Introspection on interface adherance. \\n*/\\ncontract JBGasTokenERC20ProjectPayer is Ownable, ERC165, IJBProjectPayer {\\n using SafeERC20 for IERC20;\\n\\n //*********************************************************************//\\n // -------------------------- custom errors -------------------------- //\\n //*********************************************************************//\\n error INCORRECT_DECIMAL_AMOUNT();\\n error ALREADY_INITIALIZED();\\n error NO_MSG_VALUE_ALLOWED();\\n error TERMINAL_NOT_FOUND();\\n\\n //*********************************************************************//\\n // ------------------- public immutable properties ------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice \\n A contract storing directories of terminals and controllers for each project.\\n */\\n IJBDirectory public immutable override directory;\\n\\n /**\\n @notice \\n The deployer associated with this implementation. Used to rule out double initialization.\\n */\\n address public immutable override projectPayerDeployer;\\n\\n //*********************************************************************//\\n // --------------------- public stored properties -------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n The ID of the project that should be used to forward this contract's received payments.\\n */\\n uint256 public override defaultProjectId;\\n\\n /** \\n @notice \\n The beneficiary that should be used in the payment made when this contract receives payments.\\n */\\n address payable public override defaultBeneficiary;\\n\\n /** \\n @notice \\n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\\n */\\n bool public override defaultPreferClaimedTokens;\\n\\n /** \\n @notice \\n The memo that should be used in the payment made when this contract receives payments.\\n */\\n string public override defaultMemo;\\n\\n /** \\n @notice \\n The metadata that should be used in the payment made when this contract receives payments.\\n */\\n bytes public override defaultMetadata;\\n\\n /**\\n @notice \\n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\\n */\\n bool public override defaultPreferAddToBalance;\\n\\n //*********************************************************************//\\n // ------------------------- public views ---------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Indicates if this contract adheres to the specified interface.\\n\\n @dev \\n See {IERC165-supportsInterface}.\\n\\n @param _interfaceId The ID of the interface to check for adherance to.\\n */\\n function supportsInterface(bytes4 _interfaceId)\\n public\\n view\\n virtual\\n override(ERC165, IERC165)\\n returns (bool)\\n {\\n return\\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\\n }\\n\\n //*********************************************************************//\\n // -------------------------- constructors --------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @dev This is the constructor of the implementation. The directory is shared between project payers and is\\n immutable. If a new JBDirectory is needed, a new JBProjectPayerDeployer should be deployed.\\n @param _directory A contract storing directories of terminals and controllers for each project.\\n */\\n constructor(IJBDirectory _directory) {\\n directory = _directory;\\n projectPayerDeployer = msg.sender;\\n }\\n\\n /** \\n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\\n @param _defaultBeneficiary The address that'll receive the project's tokens. \\n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \\n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\\n @param _owner The address that will own the contract.\\n */\\n function initialize(\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string memory _defaultMemo,\\n bytes memory _defaultMetadata,\\n bool _defaultPreferAddToBalance,\\n address _owner\\n ) public {\\n if(msg.sender != projectPayerDeployer) revert ALREADY_INITIALIZED();\\n\\n defaultProjectId = _defaultProjectId;\\n defaultBeneficiary = _defaultBeneficiary;\\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\\n defaultMemo = _defaultMemo;\\n defaultMetadata = _defaultMetadata;\\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\\n _transferOwnership(_owner);\\n }\\n\\n //*********************************************************************//\\n // ------------------------- default receive ------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Received funds are paid to the default project ID using the stored default properties.\\n\\n @dev\\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\\n\\n @dev\\n This function is called automatically when the contract receives an ETH payment.\\n */\\n receive() external payable virtual override {\\n if (defaultPreferAddToBalance)\\n _addToBalanceOf(\\n defaultProjectId,\\n JBTokens.GAS_TOKEN,\\n address(this).balance,\\n 18, // balance is a fixed point number with 18 decimals.\\n defaultMemo,\\n defaultMetadata\\n );\\n else\\n _pay(\\n defaultProjectId,\\n JBTokens.GAS_TOKEN,\\n address(this).balance,\\n 18, // balance is a fixed point number with 18 decimals.\\n defaultBeneficiary == address(0) ? tx.origin : defaultBeneficiary,\\n 0, // Can't determine expectation of returned tokens ahead of time.\\n defaultPreferClaimedTokens,\\n defaultMemo,\\n defaultMetadata\\n );\\n }\\n\\n //*********************************************************************//\\n // ---------------------- external transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\\n\\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\\n @param _beneficiary The address that'll receive the project's tokens. \\n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \\n @param _memo The memo that'll be used. \\n @param _metadata The metadata that'll be sent. \\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\\n */\\n function setDefaultValues(\\n uint256 _projectId,\\n address payable _beneficiary,\\n bool _preferClaimedTokens,\\n string memory _memo,\\n bytes memory _metadata,\\n bool _defaultPreferAddToBalance\\n ) external virtual override onlyOwner {\\n // Set the default project ID if it has changed.\\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\\n\\n // Set the default beneficiary if it has changed.\\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\\n\\n // Set the default claimed token preference if it has changed.\\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\\n defaultPreferClaimedTokens = _preferClaimedTokens;\\n\\n // Set the default memo if it has changed.\\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\\n defaultMemo = _memo;\\n\\n // Set the default metadata if it has changed.\\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\\n defaultMetadata = _metadata;\\n\\n // Set the add to balance preference if it has changed.\\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\\n\\n emit SetDefaultValues(\\n _projectId,\\n _beneficiary,\\n _preferClaimedTokens,\\n _memo,\\n _metadata,\\n _defaultPreferAddToBalance,\\n msg.sender\\n );\\n }\\n\\n //*********************************************************************//\\n // ----------------------- public transactions ----------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n Make a payment to the specified project.\\n\\n @param _projectId The ID of the project that is being paid.\\n @param _token The token being paid in.\\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\\n @param _beneficiary The address who will receive tokens from the payment.\\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\\n */\\n function pay(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) public payable virtual override {\\n // ETH shouldn't be sent if the token isn't ETH.\\n if (address(_token) != JBTokens.GAS_TOKEN) {\\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\\n\\n // Get a reference to the balance before receiving tokens.\\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\\n\\n // Transfer tokens to this contract from the msg sender.\\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\\n\\n // The amount should reflect the change in balance.\\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\\n } else {\\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\\n _amount = msg.value;\\n _decimals = 18;\\n }\\n\\n _pay(\\n _projectId,\\n _token,\\n _amount,\\n _decimals,\\n _beneficiary,\\n _minReturnedTokens,\\n _preferClaimedTokens,\\n _memo,\\n _metadata\\n );\\n }\\n\\n /** \\n @notice \\n Add to the balance of the specified project.\\n\\n @param _projectId The ID of the project that is being paid.\\n @param _token The token being paid in.\\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Extra data to pass along to the terminal.\\n */\\n function addToBalanceOf(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) public payable virtual override {\\n // ETH shouldn't be sent if the token isn't ETH.\\n if (address(_token) != JBTokens.GAS_TOKEN) {\\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\\n\\n // Get a reference to the balance before receiving tokens.\\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\\n\\n // Transfer tokens to this contract from the msg sender.\\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\\n\\n // The amount should reflect the change in balance.\\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\\n } else {\\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\\n _amount = msg.value;\\n _decimals = 18;\\n }\\n\\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\\n }\\n\\n //*********************************************************************//\\n // ---------------------- internal transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n Make a payment to the specified project.\\n\\n @param _projectId The ID of the project that is being paid.\\n @param _token The token being paid in.\\n @param _amount The amount of tokens being paid, as a fixed point number. \\n @param _decimals The number of decimals in the `_amount` fixed point number. \\n @param _beneficiary The address who will receive tokens from the payment.\\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _metadata Bytes to send along to the data source and delegate, if provided.\\n */\\n function _pay(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string memory _memo,\\n bytes memory _metadata\\n ) internal virtual {\\n // Find the terminal for the specified project.\\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\\n\\n // There must be a terminal.\\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\\n\\n // The amount's decimals must match the terminal's expected decimals.\\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\\n\\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).safeApprove(address(_terminal), _amount);\\n\\n // If the token is ETH, send it in msg.value.\\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\\n\\n // Send funds to the terminal.\\n // If the token is ETH, send it in msg.value.\\n _terminal.pay{value: _payableValue}(\\n _projectId,\\n _amount, // ignored if the token is JBTokens.GAS_TOKEN.\\n _token,\\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\\n ? defaultBeneficiary\\n : tx.origin,\\n _minReturnedTokens,\\n _preferClaimedTokens,\\n _memo,\\n _metadata\\n );\\n }\\n\\n /** \\n @notice \\n Add to the balance of the specified project.\\n\\n @param _projectId The ID of the project that is being paid.\\n @param _token The token being paid in.\\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Extra data to pass along to the terminal.\\n */\\n function _addToBalanceOf(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n string memory _memo,\\n bytes memory _metadata\\n ) internal virtual {\\n // Find the terminal for the specified project.\\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\\n\\n // There must be a terminal.\\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\\n\\n // The amount's decimals must match the terminal's expected decimals.\\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\\n\\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).safeApprove(address(_terminal), _amount);\\n\\n // If the token is ETH, send it in msg.value.\\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\\n\\n // Add to balance so tokens don't get issued.\\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\\n }\\n}\\n\",\"keccak256\":\"0xcbadf8e217bb9c43d18161ce576235277834988ea7cb51d58b5a794914e9156c\",\"license\":\"MIT\"},\"contracts/JBGasTokenERC20SplitsPayer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport '@openzeppelin/contracts/utils/Address.sol';\\nimport '@paulrberg/contracts/math/PRBMath.sol';\\nimport './interfaces/IJBSplitsPayer.sol';\\nimport './interfaces/IJBSplitsStore.sol';\\nimport './libraries/JBConstants.sol';\\nimport './JBGasTokenERC20ProjectPayer.sol';\\n\\n/** \\n @notice \\n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\\n\\n @dev\\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\\n\\n @dev\\n Adheres to -\\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n\\n @dev\\n Inherits from -\\n JBGasTokenERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\\n*/\\ncontract JBGasTokenERC20SplitsPayer is JBGasTokenERC20ProjectPayer, ReentrancyGuard, IJBSplitsPayer {\\n using SafeERC20 for IERC20;\\n\\n //*********************************************************************//\\n // ---------------- public immutable stored properties --------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The contract that stores splits for each project.\\n */\\n IJBSplitsStore public immutable override splitsStore;\\n\\n //*********************************************************************//\\n // --------------------- public stored properties -------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The ID of project for which the default splits are stored. \\n */\\n uint256 public override defaultSplitsProjectId;\\n\\n /**\\n @notice\\n The domain within which the default splits are stored. \\n */\\n uint256 public override defaultSplitsDomain;\\n\\n /**\\n @notice\\n The group within which the default splits are stored. \\n */\\n uint256 public override defaultSplitsGroup;\\n\\n //*********************************************************************//\\n // -------------------------- public views --------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Indicates if this contract adheres to the specified interface.\\n\\n @dev \\n See {IERC165-supportsInterface}.\\n\\n @param _interfaceId The ID of the interface to check for adherance to.\\n\\n @return A flag indicating if this contract adheres to the specified interface.\\n */\\n function supportsInterface(bytes4 _interfaceId)\\n public\\n view\\n virtual\\n override(JBGasTokenERC20ProjectPayer, IERC165)\\n returns (bool)\\n {\\n return\\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\\n }\\n\\n //*********************************************************************//\\n // -------------------------- constructor ---------------------------- //\\n //*********************************************************************//\\n/**\\n @param _splitsStore A contract that stores splits for each project.\\n*/\\n constructor(\\n IJBSplitsStore _splitsStore\\n )\\n JBGasTokenERC20ProjectPayer(\\n _splitsStore.directory()\\n )\\n {\\n splitsStore = _splitsStore;\\n }\\n /**\\n @dev The re-initialize check is done in the inherited paroject payer\\n \\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\\n @param _defaultBeneficiary The address that'll receive the project's tokens. \\n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \\n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\\n @param _owner The address that will own the contract.\\n */\\n function initialize(\\n uint256 _defaultSplitsProjectId,\\n uint256 _defaultSplitsDomain,\\n uint256 _defaultSplitsGroup,\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string memory _defaultMemo,\\n bytes memory _defaultMetadata,\\n bool _preferAddToBalance,\\n address _owner\\n ) external override {\\n\\n super.initialize(\\n _defaultProjectId,\\n _defaultBeneficiary,\\n _defaultPreferClaimedTokens,\\n _defaultMemo,\\n _defaultMetadata,\\n _preferAddToBalance,\\n _owner\\n );\\n\\n defaultSplitsProjectId = _defaultSplitsProjectId;\\n defaultSplitsDomain = _defaultSplitsDomain;\\n defaultSplitsGroup = _defaultSplitsGroup;\\n }\\n\\n\\n\\n //*********************************************************************//\\n // ------------------------- default receive ------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Received funds are paid to the default split group using the stored default properties.\\n\\n @dev\\n This function is called automatically when the contract receives an ETH payment.\\n */\\n receive() external payable virtual override nonReentrant {\\n // Pay the splits and get a reference to the amount leftover.\\n uint256 _leftoverAmount = _payToSplits(\\n defaultSplitsProjectId,\\n defaultSplitsDomain,\\n defaultSplitsGroup,\\n JBTokens.GAS_TOKEN,\\n address(this).balance,\\n 18, // decimals.\\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\\n );\\n\\n // If there is no leftover amount, nothing left to pay.\\n if (_leftoverAmount == 0) return;\\n\\n // If there's a default project ID, try to pay it.\\n if (defaultProjectId != 0)\\n if (defaultPreferAddToBalance)\\n // Pay the project by adding to its balance if prefered.\\n _addToBalanceOf(\\n defaultProjectId,\\n JBTokens.GAS_TOKEN,\\n _leftoverAmount,\\n 18, // decimals.\\n defaultMemo,\\n defaultMetadata\\n );\\n // Otherwise, issue a payment to the project.\\n else\\n _pay(\\n defaultProjectId,\\n JBTokens.GAS_TOKEN,\\n _leftoverAmount,\\n 18, // decimals.\\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\\n 0, // min returned tokens.\\n defaultPreferClaimedTokens,\\n defaultMemo,\\n defaultMetadata\\n );\\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\\n else\\n Address.sendValue(\\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(tx.origin),\\n _leftoverAmount\\n );\\n }\\n\\n //*********************************************************************//\\n // ---------------------- external transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Sets the splits in the splits store that payments this contract receives will be split between.\\n\\n @param _projectId The ID of project for which the default splits are stored. \\n @param _domain The domain within which the default splits are stored. \\n @param _group The group within which the default splits are stored. \\n @param _groupedSplits The split groups to set.\\n */\\n function setDefaultSplits(\\n uint256 _projectId,\\n uint256 _domain,\\n uint256 _group,\\n JBGroupedSplits[] memory _groupedSplits\\n ) external virtual override onlyOwner {\\n // Set the splits in the store.\\n splitsStore.set(_projectId, _domain, _groupedSplits);\\n\\n // Set the splits reference.\\n setDefaultSplitsReference(_projectId, _domain, _group);\\n }\\n\\n //*********************************************************************//\\n // ----------------------- public transactions ----------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Sets the location of the splits that payments this contract receives will be split between.\\n\\n @param _projectId The ID of project for which the default splits are stored. \\n @param _domain The domain within which the default splits are stored. \\n @param _group The group within which the default splits are stored. \\n */\\n function setDefaultSplitsReference(\\n uint256 _projectId,\\n uint256 _domain,\\n uint256 _group\\n ) public virtual override onlyOwner {\\n // Set the default splits project ID if it's changing.\\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\\n\\n // Set the default splits domain if it's changing.\\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\\n\\n // Set the default splits group if it's changing.\\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\\n\\n emit SetDefaultSplitsReference(_projectId, _domain, _group, msg.sender);\\n }\\n\\n /** \\n @notice \\n Make a payment to the specified project after first splitting the amount among the stored default splits.\\n\\n @param _projectId The ID of the project that is being paid after.\\n @param _token The token being paid in.\\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\\n */\\n function pay(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) public payable virtual override nonReentrant {\\n // ETH shouldn't be sent if the token isn't ETH.\\n if (address(_token) != JBTokens.GAS_TOKEN) {\\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\\n\\n // Get a reference to the balance before receiving tokens.\\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\\n\\n // Transfer tokens to this contract from the msg sender.\\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\\n\\n // The amount should reflect the change in balance.\\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\\n } else {\\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\\n _amount = msg.value;\\n _decimals = 18;\\n }\\n\\n // Pay the splits and get a reference to the amount leftover.\\n uint256 _leftoverAmount = _payToSplits(\\n defaultSplitsProjectId,\\n defaultSplitsDomain,\\n defaultSplitsGroup,\\n _token,\\n _amount,\\n _decimals,\\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\\n );\\n\\n // Pay any leftover amount.\\n if (_leftoverAmount > 0) {\\n // If there's a default project ID, try to pay it.\\n if (_projectId != 0) {\\n _pay(\\n _projectId,\\n _token,\\n _leftoverAmount,\\n _decimals,\\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\\n ? defaultBeneficiary\\n : tx.origin,\\n _minReturnedTokens,\\n _preferClaimedTokens,\\n _memo,\\n _metadata\\n );\\n }\\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\\n else {\\n // Transfer the ETH.\\n if (_token == JBTokens.GAS_TOKEN)\\n Address.sendValue(\\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\\n _beneficiary != address(0) ? payable(_beneficiary) : defaultBeneficiary != address(0)\\n ? defaultBeneficiary\\n : payable(tx.origin),\\n _leftoverAmount\\n );\\n // Or, transfer the ERC20.\\n else\\n IERC20(_token).safeTransfer(\\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\\n ? defaultBeneficiary\\n : tx.origin,\\n _leftoverAmount\\n );\\n }\\n }\\n\\n emit Pay(\\n _projectId,\\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\\n ? defaultBeneficiary\\n : tx.origin,\\n _token,\\n _amount,\\n _decimals,\\n _leftoverAmount,\\n _minReturnedTokens,\\n _preferClaimedTokens,\\n _memo,\\n _metadata,\\n msg.sender\\n );\\n }\\n\\n /** \\n @notice \\n Add to the balance of the specified project after first splitting the amount among the stored default splits.\\n\\n @param _projectId The ID of the project that is being paid after.\\n @param _token The token being paid in.\\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\\n @param _memo A memo to pass along to the emitted event. \\n @param _metadata Extra data to pass along to the terminal.\\n */\\n function addToBalanceOf(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) public payable virtual override nonReentrant {\\n // ETH shouldn't be sent if this terminal's token isn't ETH.\\n if (address(_token) != JBTokens.GAS_TOKEN) {\\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\\n\\n // Get a reference to the balance before receiving tokens.\\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\\n\\n // Transfer tokens to this contract from the msg sender.\\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\\n\\n // The amount should reflect the change in balance.\\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\\n } else {\\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\\n _amount = msg.value;\\n _decimals = 18;\\n }\\n\\n // Pay the splits and get a reference to the amount leftover.\\n uint256 _leftoverAmount = _payToSplits(\\n defaultSplitsProjectId,\\n defaultSplitsDomain,\\n defaultSplitsGroup,\\n _token,\\n _amount,\\n _decimals,\\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\\n );\\n\\n // Distribute any leftover amount.\\n if (_leftoverAmount > 0) {\\n // If there's a default project ID, try to add to its balance.\\n if (_projectId != 0)\\n // Add to the project's balance.\\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\\n\\n // Otherwise, send a payment to the beneficiary.\\n else {\\n // Transfer the ETH.\\n if (_token == JBTokens.GAS_TOKEN)\\n Address.sendValue(\\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(tx.origin),\\n _leftoverAmount\\n );\\n // Or, transfer the ERC20.\\n else\\n IERC20(_token).safeTransfer(\\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\\n _leftoverAmount\\n );\\n }\\n }\\n\\n emit AddToBalance(\\n _projectId,\\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\\n _token,\\n _amount,\\n _decimals,\\n _leftoverAmount,\\n _memo,\\n _metadata,\\n msg.sender\\n );\\n }\\n\\n //*********************************************************************//\\n // ---------------------- internal transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n Split an amount between all splits.\\n\\n @param _splitsProjectId The ID of the project to which the splits belong.\\n @param _splitsDomain The splits domain to which the group belongs.\\n @param _splitsGroup The splits group to pay.\\n @param _token The token the amonut being split is in.\\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\\n @param _decimals The number of decimals in the `_amount` fixed point number. \\n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\\n\\n @return leftoverAmount The amount leftover after all splits were paid.\\n */\\n function _payToSplits(\\n uint256 _splitsProjectId,\\n uint256 _splitsDomain,\\n uint256 _splitsGroup,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n address _defaultBeneficiary\\n ) internal virtual returns (uint256 leftoverAmount) {\\n // Pay the splits.\\n leftoverAmount = _payTo(\\n splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup),\\n _token,\\n _amount,\\n _decimals,\\n _defaultBeneficiary\\n );\\n emit DistributeToSplitGroup(_splitsProjectId, _splitsDomain, _splitsGroup, msg.sender);\\n }\\n\\n /** \\n @notice \\n Split an amount between all splits.\\n\\n @param _splits The splits.\\n @param _token The token the amonut being split is in.\\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\\n @param _decimals The number of decimals in the `_amount` fixed point number. \\n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\\n\\n @return leftoverAmount The amount leftover after all splits were paid.\\n */\\n function _payTo(\\n JBSplit[] memory _splits,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n address _defaultBeneficiary\\n ) internal virtual returns (uint256 leftoverAmount) {\\n // Set the leftover amount to the initial balance.\\n leftoverAmount = _amount;\\n\\n // Settle between all splits.\\n for (uint256 i; i < _splits.length; ) {\\n // Get a reference to the split being iterated on.\\n JBSplit memory _split = _splits[i];\\n\\n // The amount to send towards the split.\\n uint256 _splitAmount = PRBMath.mulDiv(\\n _amount,\\n _split.percent,\\n JBConstants.SPLITS_TOTAL_PERCENT\\n );\\n\\n if (_splitAmount > 0) {\\n // Transfer tokens to the split.\\n // If there's an allocator set, transfer to its `allocate` function.\\n if (_split.allocator != IJBSplitAllocator(address(0))) {\\n // Create the data to send to the allocator.\\n JBSplitAllocationData memory _data = JBSplitAllocationData(\\n _token,\\n _splitAmount,\\n _decimals,\\n defaultProjectId,\\n 0,\\n _split\\n );\\n\\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\\n if (_token != JBTokens.GAS_TOKEN)\\n IERC20(_token).safeApprove(address(_split.allocator), _splitAmount);\\n\\n // If the token is ETH, send it in msg.value.\\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _splitAmount : 0;\\n\\n // Trigger the allocator's `allocate` function.\\n _split.allocator.allocate{value: _payableValue}(_data);\\n\\n // Otherwise, if a project is specified, make a payment to it.\\n } else if (_split.projectId != 0) {\\n if (_split.preferAddToBalance)\\n _addToBalanceOf(\\n _split.projectId,\\n _token,\\n _splitAmount,\\n _decimals,\\n defaultMemo,\\n defaultMetadata\\n );\\n else\\n _pay(\\n _split.projectId,\\n _token,\\n _splitAmount,\\n _decimals,\\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\\n 0,\\n _split.preferClaimed,\\n defaultMemo,\\n defaultMetadata\\n );\\n } else {\\n // Transfer the ETH.\\n if (_token == JBTokens.GAS_TOKEN)\\n Address.sendValue(\\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\\n _split.beneficiary != address(0) ? _split.beneficiary : payable(_defaultBeneficiary),\\n _splitAmount\\n );\\n // Or, transfer the ERC20.\\n else {\\n IERC20(_token).safeTransfer(\\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\\n _splitAmount\\n );\\n }\\n }\\n\\n // Subtract from the amount to be sent to the beneficiary.\\n leftoverAmount = leftoverAmount - _splitAmount;\\n }\\n\\n emit DistributeToSplit(_split, _splitAmount, _defaultBeneficiary, msg.sender);\\n\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x19b81077f19b544d6ad5c6b945584fd9187c774f0f85e2965475ade2da15ae42\",\"license\":\"MIT\"},\"contracts/JBGasTokenERC20SplitsPayerDeployer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport { Clones } from '@openzeppelin/contracts/proxy/Clones.sol';\\n\\nimport './interfaces/IJBGasTokenERC20SplitsPayerDeployer.sol';\\nimport './structs/JBSplit.sol';\\nimport './structs/JBGroupedSplits.sol';\\nimport './JBGasTokenERC20SplitsPayer.sol';\\n\\n/** \\n @notice \\n Deploys splits payer contracts.\\n\\n @dev\\n Adheres to -\\n IJBGasTokenERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n*/\\ncontract JBGasTokenERC20SplitsPayerDeployer is IJBGasTokenERC20SplitsPayerDeployer {\\n\\n address immutable implementation;\\n\\n IJBSplitsStore immutable splitsStore;\\n\\n constructor(IJBSplitsStore _splitsStore) {\\n implementation = address(new JBGasTokenERC20SplitsPayer(_splitsStore));\\n splitsStore = _splitsStore;\\n }\\n\\n //*********************************************************************//\\n // ---------------------- external transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n Allows anyone to deploy a new splits payer contract.\\n\\n @dev\\n This contract must have Operator permissions over the SET_SPLITS permission of the specified `_defaultSplitsProjectId`.\\n\\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\\n @param _defaultSplits The splits to payout when this contract receives direct payments.\\n @param _splitsStore A contract that stores splits for each project.\\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \\n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \\n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \\n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\\n @param _owner The address that will own the splits payer.\\n\\n @return splitsPayer The splits payer contract.\\n */\\n function deploySplitsPayerWithSplits(\\n uint256 _defaultSplitsProjectId,\\n JBSplit[] memory _defaultSplits,\\n IJBSplitsStore _splitsStore,\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string memory _defaultMemo,\\n bytes memory _defaultMetadata,\\n bool _defaultPreferAddToBalance,\\n address _owner\\n ) external override returns (IJBSplitsPayer splitsPayer) {\\n // Use this contract's address as the domain.\\n uint256 _domain = uint256(uint160(address(this)));\\n\\n // Create the random hash using data unique to this instance that'll be used as the storage domain.\\n uint256 _group = uint256(keccak256(abi.encodePacked(msg.sender, block.number)));\\n\\n // Set the splits in the store.\\n JBGroupedSplits[] memory _groupedSplits;\\n _groupedSplits = new JBGroupedSplits[](1);\\n _groupedSplits[0] = JBGroupedSplits(_group, _defaultSplits);\\n _splitsStore.set(_defaultSplitsProjectId, _domain, _groupedSplits);\\n\\n return\\n deploySplitsPayer(\\n _defaultSplitsProjectId,\\n _domain,\\n _group,\\n _defaultProjectId,\\n _defaultBeneficiary,\\n _defaultPreferClaimedTokens,\\n _defaultMemo,\\n _defaultMetadata,\\n _defaultPreferAddToBalance,\\n _owner\\n );\\n }\\n\\n //*********************************************************************//\\n // ---------------------- public transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n Allows anyone to deploy a new splits payer contract.\\n\\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \\n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \\n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \\n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\\n @param _owner The address that will own the splits payer.\\n\\n @return splitsPayer The splits payer contract.\\n */\\n function deploySplitsPayer(\\n uint256 _defaultSplitsProjectId,\\n uint256 _defaultSplitsDomain,\\n uint256 _defaultSplitsGroup,\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string memory _defaultMemo,\\n bytes memory _defaultMetadata,\\n bool _defaultPreferAddToBalance,\\n address _owner\\n ) public override returns (IJBSplitsPayer splitsPayer) {\\n\\n // Deploy the splits payer.\\n splitsPayer = IJBSplitsPayer(payable(Clones.clone(implementation)));\\n\\n splitsPayer.initialize(\\n _defaultSplitsProjectId,\\n _defaultSplitsDomain,\\n _defaultSplitsGroup,\\n _defaultProjectId,\\n _defaultBeneficiary,\\n _defaultPreferClaimedTokens,\\n _defaultMemo,\\n _defaultMetadata,\\n _defaultPreferAddToBalance,\\n _owner\\n );\\n\\n emit DeploySplitsPayer(\\n splitsPayer,\\n _defaultSplitsProjectId,\\n _defaultSplitsDomain,\\n _defaultSplitsGroup,\\n splitsStore,\\n _defaultProjectId,\\n _defaultBeneficiary,\\n _defaultPreferClaimedTokens,\\n _defaultMemo,\\n _defaultMetadata,\\n _defaultPreferAddToBalance,\\n _owner,\\n msg.sender\\n );\\n }\\n}\\n\",\"keccak256\":\"0x1d772589f0079d573ea80929092e23a4b2bc9a41f0e930dc1efb10d7fc731d81\",\"license\":\"MIT\"},\"contracts/enums/JBBallotState.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nenum JBBallotState {\\n Active,\\n Approved,\\n Failed\\n}\\n\",\"keccak256\":\"0x891fcac63470398b3a11239da7feba6b07d640809fcefd2404303b823d7378f8\",\"license\":\"MIT\"},\"contracts/interfaces/IJBDirectory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBProjects.sol';\\n\\ninterface IJBDirectory {\\n event SetController(uint256 indexed projectId, address indexed controller, address caller);\\n\\n event AddTerminal(uint256 indexed projectId, IJBPaymentTerminal indexed terminal, address caller);\\n\\n event SetTerminals(uint256 indexed projectId, IJBPaymentTerminal[] terminals, address caller);\\n\\n event SetPrimaryTerminal(\\n uint256 indexed projectId,\\n address indexed token,\\n IJBPaymentTerminal indexed terminal,\\n address caller\\n );\\n\\n event SetIsAllowedToSetFirstController(address indexed addr, bool indexed flag, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function controllerOf(uint256 _projectId) external view returns (address);\\n\\n function isAllowedToSetFirstController(address _address) external view returns (bool);\\n\\n function terminalsOf(uint256 _projectId) external view returns (IJBPaymentTerminal[] memory);\\n\\n function isTerminalOf(uint256 _projectId, IJBPaymentTerminal _terminal)\\n external\\n view\\n returns (bool);\\n\\n function primaryTerminalOf(uint256 _projectId, address _token)\\n external\\n view\\n returns (IJBPaymentTerminal);\\n\\n function setControllerOf(uint256 _projectId, address _controller) external;\\n\\n function setTerminalsOf(uint256 _projectId, IJBPaymentTerminal[] calldata _terminals) external;\\n\\n function setPrimaryTerminalOf(\\n uint256 _projectId,\\n address _token,\\n IJBPaymentTerminal _terminal\\n ) external;\\n\\n function setIsAllowedToSetFirstController(address _address, bool _flag) external;\\n}\\n\",\"keccak256\":\"0x715321646db00514d1355ed43c40cd3f01e94959552fd07797b315d9c49cdb1d\",\"license\":\"MIT\"},\"contracts/interfaces/IJBGasTokenERC20SplitsPayerDeployer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBSplitsPayer.sol';\\nimport './IJBSplitsStore.sol';\\n\\ninterface IJBGasTokenERC20SplitsPayerDeployer {\\n event DeploySplitsPayer(\\n IJBSplitsPayer indexed splitsPayer,\\n uint256 defaultSplitsProjectId,\\n uint256 defaultSplitsDomain,\\n uint256 defaultSplitsGroup,\\n IJBSplitsStore splitsStore,\\n uint256 defaultProjectId,\\n address defaultBeneficiary,\\n bool defaultPreferClaimedTokens,\\n string defaultMemo,\\n bytes defaultMetadata,\\n bool preferAddToBalance,\\n address owner,\\n address caller\\n );\\n\\n function deploySplitsPayer(\\n uint256 _defaultSplitsProjectId,\\n uint256 _defaultSplitsDomain,\\n uint256 _defaultSplitsGroup,\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string calldata _defaultMemo,\\n bytes calldata _defaultMetadata,\\n bool _preferAddToBalance,\\n address _owner\\n ) external returns (IJBSplitsPayer splitsPayer);\\n\\n function deploySplitsPayerWithSplits(\\n uint256 _defaultSplitsProjectId,\\n JBSplit[] memory _defaultSplits,\\n IJBSplitsStore _splitsStore,\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string memory _defaultMemo,\\n bytes memory _defaultMetadata,\\n bool _defaultPreferAddToBalance,\\n address _owner\\n ) external returns (IJBSplitsPayer splitsPayer);\\n}\\n\",\"keccak256\":\"0xc476797aa84a54530cdbaff6a9e8c2fc8bf90a051dd51a17a00c51345db2798c\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleBallot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../enums/JBBallotState.sol';\\n\\ninterface IJBFundingCycleBallot is IERC165 {\\n function duration() external view returns (uint256);\\n\\n function stateOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n uint256 _start\\n ) external view returns (JBBallotState);\\n}\\n\",\"keccak256\":\"0x49553a56209237846bc400cf27f260824a6bd06fd8094a7eb5abb9de75779598\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../enums/JBBallotState.sol';\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBFundingCycleData.sol';\\n\\ninterface IJBFundingCycleStore {\\n event Configure(\\n uint256 indexed configuration,\\n uint256 indexed projectId,\\n JBFundingCycleData data,\\n uint256 metadata,\\n uint256 mustStartAtOrAfter,\\n address caller\\n );\\n\\n event Init(uint256 indexed configuration, uint256 indexed projectId, uint256 indexed basedOn);\\n\\n function latestConfigurationOf(uint256 _projectId) external view returns (uint256);\\n\\n function get(uint256 _projectId, uint256 _configuration)\\n external\\n view\\n returns (JBFundingCycle memory);\\n\\n function latestConfiguredOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBBallotState ballotState);\\n\\n function queuedOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentBallotStateOf(uint256 _projectId) external view returns (JBBallotState);\\n\\n function configureFor(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n uint256 _metadata,\\n uint256 _mustStartAtOrAfter\\n ) external returns (JBFundingCycle memory fundingCycle);\\n}\\n\",\"keccak256\":\"0xaead823851433be0c2ddc8f8086813e6cd647de3a1bc0f7570a5d6b38c378b5a\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\n\\ninterface IJBPaymentTerminal is IERC165 {\\n function acceptsToken(address _token, uint256 _projectId) external view returns (bool);\\n\\n function currencyForToken(address _token) external view returns (uint256);\\n\\n function decimalsForToken(address _token) external view returns (uint256);\\n\\n // Return value must be a fixed point number with 18 decimals.\\n function currentEthOverflowOf(uint256 _projectId) external view returns (uint256);\\n\\n function pay(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable returns (uint256 beneficiaryTokenCount);\\n\\n function addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable;\\n}\\n\",\"keccak256\":\"0xb7826f5ed609359ce322c09e83236c47ba385df1c3cad3607e56fd0a2e00eee2\",\"license\":\"MIT\"},\"contracts/interfaces/IJBProjectPayer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './IJBDirectory.sol';\\n\\ninterface IJBProjectPayer is IERC165 {\\n event SetDefaultValues(\\n uint256 indexed projectId,\\n address indexed beneficiary,\\n bool preferClaimedTokens,\\n string memo,\\n bytes metadata,\\n bool preferAddToBalance,\\n address caller\\n );\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function projectPayerDeployer() external view returns (address);\\n\\n function defaultProjectId() external view returns (uint256);\\n\\n function defaultBeneficiary() external view returns (address payable);\\n\\n function defaultPreferClaimedTokens() external view returns (bool);\\n\\n function defaultMemo() external view returns (string memory);\\n\\n function defaultMetadata() external view returns (bytes memory);\\n\\n function defaultPreferAddToBalance() external view returns (bool);\\n\\n function initialize(\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string memory _defaultMemo,\\n bytes memory _defaultMetadata,\\n bool _defaultPreferAddToBalance,\\n address _owner\\n ) external;\\n\\n function setDefaultValues(\\n uint256 _projectId,\\n address payable _beneficiary,\\n bool _preferClaimedTokens,\\n string memory _memo,\\n bytes memory _metadata,\\n bool _defaultPreferAddToBalance\\n ) external;\\n\\n function pay(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string memory _memo,\\n bytes memory _metadata\\n ) external payable;\\n\\n function addToBalanceOf(\\n uint256 _projectId,\\n address _token,\\n uint256 _amount,\\n uint256 _decimals,\\n string memory _memo,\\n bytes memory _metadata\\n ) external payable;\\n\\n receive() external payable;\\n}\\n\",\"keccak256\":\"0x85f4cbd5482e26618994f742c149a5bd3cb3dc39dbeba85b21c36b3215007df6\",\"license\":\"MIT\"},\"contracts/interfaces/IJBProjects.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBTokenUriResolver.sol';\\n\\ninterface IJBProjects is IERC721 {\\n event Create(\\n uint256 indexed projectId,\\n address indexed owner,\\n JBProjectMetadata metadata,\\n address caller\\n );\\n\\n event SetMetadata(uint256 indexed projectId, JBProjectMetadata metadata, address caller);\\n\\n event SetTokenUriResolver(IJBTokenUriResolver indexed resolver, address caller);\\n\\n function count() external view returns (uint256);\\n\\n function metadataContentOf(uint256 _projectId, uint256 _domain)\\n external\\n view\\n returns (string memory);\\n\\n function tokenUriResolver() external view returns (IJBTokenUriResolver);\\n\\n function createFor(address _owner, JBProjectMetadata calldata _metadata)\\n external\\n returns (uint256 projectId);\\n\\n function setMetadataOf(uint256 _projectId, JBProjectMetadata calldata _metadata) external;\\n\\n function setTokenUriResolver(IJBTokenUriResolver _newResolver) external;\\n}\\n\",\"keccak256\":\"0x7cfc021d0bd7e73b1ba8f4845d7d35e3419d6a14d3d25ca3a8010e7f91062fe4\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSplitAllocator.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport '../structs/JBSplitAllocationData.sol';\\n\\n/**\\n @title\\n Split allocator\\n\\n @notice\\n Provide a way to process a single split with extra logic\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n\\n @dev\\n The contract address should be set as an allocator in the adequate split\\n*/\\ninterface IJBSplitAllocator is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.distributePayoutOf(..), during the processing of the split including it\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control. The token and/or eth are optimistically transfered\\n to the allocator for its logic.\\n \\n @param _data the data passed by the terminal, as a JBSplitAllocationData struct:\\n address token;\\n uint256 amount;\\n uint256 decimals;\\n uint256 projectId;\\n uint256 group;\\n JBSplit split;\\n */\\n function allocate(JBSplitAllocationData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0x5efb6f51fc161f42ff58989386ad99028e4039a0ba897d66f358c3dfcf686105\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSplitsPayer.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBSplit.sol';\\nimport './../structs/JBGroupedSplits.sol';\\nimport './IJBSplitsStore.sol';\\n\\ninterface IJBSplitsPayer is IERC165 {\\n event SetDefaultSplitsReference(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n address caller\\n );\\n event Pay(\\n uint256 indexed projectId,\\n address beneficiary,\\n address token,\\n uint256 amount,\\n uint256 decimals,\\n uint256 leftoverAmount,\\n uint256 minReturnedTokens,\\n bool preferClaimedTokens,\\n string memo,\\n bytes metadata,\\n address caller\\n );\\n\\n event AddToBalance(\\n uint256 indexed projectId,\\n address beneficiary,\\n address token,\\n uint256 amount,\\n uint256 decimals,\\n uint256 leftoverAmount,\\n string memo,\\n bytes metadata,\\n address caller\\n );\\n\\n event DistributeToSplitGroup(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n address caller\\n );\\n\\n event DistributeToSplit(\\n JBSplit split,\\n uint256 amount,\\n address defaultBeneficiary,\\n address caller\\n );\\n\\n function defaultSplitsProjectId() external view returns (uint256);\\n\\n function defaultSplitsDomain() external view returns (uint256);\\n\\n function defaultSplitsGroup() external view returns (uint256);\\n\\n function splitsStore() external view returns (IJBSplitsStore);\\n\\n function initialize(\\n uint256 _defaultSplitsProjectId,\\n uint256 _defaultSplitsDomain,\\n uint256 _defaultSplitsGroup,\\n uint256 _defaultProjectId,\\n address payable _defaultBeneficiary,\\n bool _defaultPreferClaimedTokens,\\n string memory _defaultMemo,\\n bytes memory _defaultMetadata,\\n bool _preferAddToBalance,\\n address _owner\\n ) external;\\n\\n function setDefaultSplitsReference(\\n uint256 _projectId,\\n uint256 _domain,\\n uint256 _group\\n ) external;\\n\\n function setDefaultSplits(\\n uint256 _projectId,\\n uint256 _domain,\\n uint256 _group,\\n JBGroupedSplits[] memory _splitsGroup\\n ) external;\\n}\\n\",\"keccak256\":\"0xb37aebcf7b3db4d026d635212ff27fca7467e5d6c0084d8331819f41555d4f20\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSplitsStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBGroupedSplits.sol';\\nimport './../structs/JBSplit.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBProjects.sol';\\n\\ninterface IJBSplitsStore {\\n event SetSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n address caller\\n );\\n\\n function projects() external view returns (IJBProjects);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function splitsOf(\\n uint256 _projectId,\\n uint256 _domain,\\n uint256 _group\\n ) external view returns (JBSplit[] memory);\\n\\n function set(\\n uint256 _projectId,\\n uint256 _domain,\\n JBGroupedSplits[] memory _groupedSplits\\n ) external;\\n}\\n\",\"keccak256\":\"0x66dab3dd394e318b850401ca92c2963b906cc0ad5562fa5d4f6f850175d1c77a\",\"license\":\"MIT\"},\"contracts/interfaces/IJBTokenUriResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBTokenUriResolver {\\n function getUri(uint256 _projectId) external view returns (string memory tokenUri);\\n}\\n\",\"keccak256\":\"0xd267fd8ca7c21c2c71794acdb9a98314c33a35fc559e0bf0897a6686d196d174\",\"license\":\"MIT\"},\"contracts/libraries/JBConstants.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/**\\n @notice\\n Global constants used across Juicebox contracts.\\n*/\\nlibrary JBConstants {\\n uint256 public constant MAX_RESERVED_RATE = 10_000;\\n uint256 public constant MAX_REDEMPTION_RATE = 10_000;\\n uint256 public constant MAX_DISCOUNT_RATE = 1_000_000_000;\\n uint256 public constant SPLITS_TOTAL_PERCENT = 1_000_000_000;\\n uint256 public constant MAX_FEE = 1_000_000_000;\\n uint256 public constant MAX_FEE_DISCOUNT = 1_000_000_000;\\n}\\n\",\"keccak256\":\"0x34362846a1cd428a8bdedf4ab6857e11402f345cb87b994b2e7fb6d2474b808d\",\"license\":\"MIT\"},\"contracts/libraries/JBTokens.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBTokens {\\n /** \\n @notice \\n The ETH token address in Juicebox is represented by 0x000000000000000000000000000000000000EEEe.\\n */\\n address public constant ETH = address(0x000000000000000000000000000000000000EEEe);\\n}\\n\",\"keccak256\":\"0xecf82992f7b827766aa55f16872517a646521eef414d8cc9786617ea377e5463\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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.\\n @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.\\n @member basedOn The `configuration` of the funding cycle that was active when this cycle was created.\\n @member start The timestamp marking the moment from which the funding cycle is considered active. It is a unix timestamp measured in seconds.\\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n @member metadata Extra data that can be associated with a funding cycle.\\n*/\\nstruct JBFundingCycle {\\n uint256 number;\\n uint256 configuration;\\n uint256 basedOn;\\n uint256 start;\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n uint256 metadata;\\n}\\n\",\"keccak256\":\"0xcdd3ac9b6fa67e62ada88d09b73bc35ade1cd77d43db712289266a788928b4c2\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycleData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n*/\\nstruct JBFundingCycleData {\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n}\\n\",\"keccak256\":\"0x2aa6368bf4dfc5797e8b02a978293de0c777fae2658de2c825a103587240f3b0\",\"license\":\"MIT\"},\"contracts/structs/JBGroupedSplits.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBSplit.sol';\\n\\n/** \\n @member group The group indentifier.\\n @member splits The splits to associate with the group.\\n*/\\nstruct JBGroupedSplits {\\n uint256 group;\\n JBSplit[] splits;\\n}\\n\",\"keccak256\":\"0x80be1b220da4ac04851ea540ebb94c1ec2b0442ec5bd1e88fdf78a56becd8b5a\",\"license\":\"MIT\"},\"contracts/structs/JBProjectMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member content The metadata content.\\n @member domain The domain within which the metadata applies.\\n*/\\nstruct JBProjectMetadata {\\n string content;\\n uint256 domain;\\n}\\n\",\"keccak256\":\"0x90ad7b1014c0a9f945fe7a2efde9d5de41e40574fa27969070b1d2ff52033ea0\",\"license\":\"MIT\"},\"contracts/structs/JBSplit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBSplitAllocator.sol';\\n\\n/** \\n @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.\\n @member preferAddToBalance A flag indicating if a distribution to a project should prefer triggering it's addToBalance function instead of its pay function.\\n @member percent The percent of the whole group that this split occupies. This number is out of `JBConstants.SPLITS_TOTAL_PERCENT`.\\n @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.\\n @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.\\n @member lockedUntil Specifies if the split should be unchangeable until the specified time, with the exception of extending the locked period.\\n @member allocator If an allocator is specified, funds will be sent to the allocator contract along with all properties of this split.\\n*/\\nstruct JBSplit {\\n bool preferClaimed;\\n bool preferAddToBalance;\\n uint256 percent;\\n uint256 projectId;\\n address payable beneficiary;\\n uint256 lockedUntil;\\n IJBSplitAllocator allocator;\\n}\\n\",\"keccak256\":\"0xc80a16606da8abf76d0f73abc38aee041e24f29342c1939018f70c286e89f105\",\"license\":\"MIT\"},\"contracts/structs/JBSplitAllocationData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBSplit.sol';\\n\\n/** \\n @member token The token being sent to the split allocator.\\n @member amount The amount being sent to the split allocator, as a fixed point number.\\n @member decimals The number of decimals in the amount.\\n @member projectId The project to which the split belongs.\\n @member group The group to which the split belongs.\\n @member split The split that caused the allocation.\\n*/\\nstruct JBSplitAllocationData {\\n address token;\\n uint256 amount;\\n uint256 decimals;\\n uint256 projectId;\\n uint256 group;\\n JBSplit split;\\n}\\n\",\"keccak256\":\"0x39f5c41bd31d36774744698ac94484b6cab62d7038df2f29d947668959782e63\",\"license\":\"MIT\"},\"prb-math/contracts/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivFixedPointOverflow(uint256 prod1);\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivOverflow(uint256 prod1, uint256 denominator);\\n\\n/// @notice Emitted when one of the inputs is type(int256).min.\\nerror PRBMath__MulDivSignedInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows int256.\\nerror PRBMath__MulDivSignedOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is MIN_SD59x18.\\nerror PRBMathSD59x18__AbsInputTooSmall();\\n\\n/// @notice Emitted when ceiling a number overflows SD59x18.\\nerror PRBMathSD59x18__CeilOverflow(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__DivInputTooSmall();\\n\\n/// @notice Emitted when one of the intermediary unsigned results overflows SD59x18.\\nerror PRBMathSD59x18__DivOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathSD59x18__ExpInputTooBig(int256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathSD59x18__Exp2InputTooBig(int256 x);\\n\\n/// @notice Emitted when flooring a number underflows SD59x18.\\nerror PRBMathSD59x18__FloorUnderflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format overflows SD59x18.\\nerror PRBMathSD59x18__FromIntOverflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format underflows SD59x18.\\nerror PRBMathSD59x18__FromIntUnderflow(int256 x);\\n\\n/// @notice Emitted when the product of the inputs is negative.\\nerror PRBMathSD59x18__GmNegativeProduct(int256 x, int256 y);\\n\\n/// @notice Emitted when multiplying the inputs overflows SD59x18.\\nerror PRBMathSD59x18__GmOverflow(int256 x, int256 y);\\n\\n/// @notice Emitted when the input is less than or equal to zero.\\nerror PRBMathSD59x18__LogInputTooSmall(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__MulInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__MulOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__PowuOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is negative.\\nerror PRBMathSD59x18__SqrtNegativeInput(int256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows SD59x18.\\nerror PRBMathSD59x18__SqrtOverflow(int256 x);\\n\\n/// @notice Emitted when addition overflows UD60x18.\\nerror PRBMathUD60x18__AddOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when ceiling a number overflows UD60x18.\\nerror PRBMathUD60x18__CeilOverflow(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathUD60x18__ExpInputTooBig(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathUD60x18__Exp2InputTooBig(uint256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format format overflows UD60x18.\\nerror PRBMathUD60x18__FromUintOverflow(uint256 x);\\n\\n/// @notice Emitted when multiplying the inputs overflows UD60x18.\\nerror PRBMathUD60x18__GmOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when the input is less than 1.\\nerror PRBMathUD60x18__LogInputTooSmall(uint256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows UD60x18.\\nerror PRBMathUD60x18__SqrtOverflow(uint256 x);\\n\\n/// @notice Emitted when subtraction underflows UD60x18.\\nerror PRBMathUD60x18__SubUnderflow(uint256 x, uint256 y);\\n\\n/// @dev Common mathematical functions used in both PRBMathSD59x18 and PRBMathUD60x18. Note that this shared library\\n/// does not always assume the signed 59.18-decimal fixed-point or the unsigned 60.18-decimal fixed-point\\n/// representation. When it does not, it is explicitly mentioned in the NatSpec documentation.\\nlibrary PRBMath {\\n /// STRUCTS ///\\n\\n struct SD59x18 {\\n int256 value;\\n }\\n\\n struct UD60x18 {\\n uint256 value;\\n }\\n\\n /// STORAGE ///\\n\\n /// @dev How many trailing decimals can be represented.\\n uint256 internal constant SCALE = 1e18;\\n\\n /// @dev Largest power of two divisor of SCALE.\\n uint256 internal constant SCALE_LPOTD = 262144;\\n\\n /// @dev SCALE inverted mod 2^256.\\n uint256 internal constant SCALE_INVERSE =\\n 78156646155174841979727994598816262306175212592076161876661_508869554232690281;\\n\\n /// FUNCTIONS ///\\n\\n /// @notice Calculates the binary exponent of x using the binary fraction method.\\n /// @dev Has to use 192.64-bit fixed-point numbers.\\n /// See https://ethereum.stackexchange.com/a/96594/24693.\\n /// @param x The exponent as an unsigned 192.64-bit fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp2(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n // Start from 0.5 in the 192.64-bit fixed-point format.\\n result = 0x800000000000000000000000000000000000000000000000;\\n\\n // Multiply the result by root(2, 2^-i) when the bit at position i is 1. None of the intermediary results overflows\\n // because the initial result is 2^191 and all magic factors are less than 2^65.\\n if (x & 0x8000000000000000 > 0) {\\n result = (result * 0x16A09E667F3BCC909) >> 64;\\n }\\n if (x & 0x4000000000000000 > 0) {\\n result = (result * 0x1306FE0A31B7152DF) >> 64;\\n }\\n if (x & 0x2000000000000000 > 0) {\\n result = (result * 0x1172B83C7D517ADCE) >> 64;\\n }\\n if (x & 0x1000000000000000 > 0) {\\n result = (result * 0x10B5586CF9890F62A) >> 64;\\n }\\n if (x & 0x800000000000000 > 0) {\\n result = (result * 0x1059B0D31585743AE) >> 64;\\n }\\n if (x & 0x400000000000000 > 0) {\\n result = (result * 0x102C9A3E778060EE7) >> 64;\\n }\\n if (x & 0x200000000000000 > 0) {\\n result = (result * 0x10163DA9FB33356D8) >> 64;\\n }\\n if (x & 0x100000000000000 > 0) {\\n result = (result * 0x100B1AFA5ABCBED61) >> 64;\\n }\\n if (x & 0x80000000000000 > 0) {\\n result = (result * 0x10058C86DA1C09EA2) >> 64;\\n }\\n if (x & 0x40000000000000 > 0) {\\n result = (result * 0x1002C605E2E8CEC50) >> 64;\\n }\\n if (x & 0x20000000000000 > 0) {\\n result = (result * 0x100162F3904051FA1) >> 64;\\n }\\n if (x & 0x10000000000000 > 0) {\\n result = (result * 0x1000B175EFFDC76BA) >> 64;\\n }\\n if (x & 0x8000000000000 > 0) {\\n result = (result * 0x100058BA01FB9F96D) >> 64;\\n }\\n if (x & 0x4000000000000 > 0) {\\n result = (result * 0x10002C5CC37DA9492) >> 64;\\n }\\n if (x & 0x2000000000000 > 0) {\\n result = (result * 0x1000162E525EE0547) >> 64;\\n }\\n if (x & 0x1000000000000 > 0) {\\n result = (result * 0x10000B17255775C04) >> 64;\\n }\\n if (x & 0x800000000000 > 0) {\\n result = (result * 0x1000058B91B5BC9AE) >> 64;\\n }\\n if (x & 0x400000000000 > 0) {\\n result = (result * 0x100002C5C89D5EC6D) >> 64;\\n }\\n if (x & 0x200000000000 > 0) {\\n result = (result * 0x10000162E43F4F831) >> 64;\\n }\\n if (x & 0x100000000000 > 0) {\\n result = (result * 0x100000B1721BCFC9A) >> 64;\\n }\\n if (x & 0x80000000000 > 0) {\\n result = (result * 0x10000058B90CF1E6E) >> 64;\\n }\\n if (x & 0x40000000000 > 0) {\\n result = (result * 0x1000002C5C863B73F) >> 64;\\n }\\n if (x & 0x20000000000 > 0) {\\n result = (result * 0x100000162E430E5A2) >> 64;\\n }\\n if (x & 0x10000000000 > 0) {\\n result = (result * 0x1000000B172183551) >> 64;\\n }\\n if (x & 0x8000000000 > 0) {\\n result = (result * 0x100000058B90C0B49) >> 64;\\n }\\n if (x & 0x4000000000 > 0) {\\n result = (result * 0x10000002C5C8601CC) >> 64;\\n }\\n if (x & 0x2000000000 > 0) {\\n result = (result * 0x1000000162E42FFF0) >> 64;\\n }\\n if (x & 0x1000000000 > 0) {\\n result = (result * 0x10000000B17217FBB) >> 64;\\n }\\n if (x & 0x800000000 > 0) {\\n result = (result * 0x1000000058B90BFCE) >> 64;\\n }\\n if (x & 0x400000000 > 0) {\\n result = (result * 0x100000002C5C85FE3) >> 64;\\n }\\n if (x & 0x200000000 > 0) {\\n result = (result * 0x10000000162E42FF1) >> 64;\\n }\\n if (x & 0x100000000 > 0) {\\n result = (result * 0x100000000B17217F8) >> 64;\\n }\\n if (x & 0x80000000 > 0) {\\n result = (result * 0x10000000058B90BFC) >> 64;\\n }\\n if (x & 0x40000000 > 0) {\\n result = (result * 0x1000000002C5C85FE) >> 64;\\n }\\n if (x & 0x20000000 > 0) {\\n result = (result * 0x100000000162E42FF) >> 64;\\n }\\n if (x & 0x10000000 > 0) {\\n result = (result * 0x1000000000B17217F) >> 64;\\n }\\n if (x & 0x8000000 > 0) {\\n result = (result * 0x100000000058B90C0) >> 64;\\n }\\n if (x & 0x4000000 > 0) {\\n result = (result * 0x10000000002C5C860) >> 64;\\n }\\n if (x & 0x2000000 > 0) {\\n result = (result * 0x1000000000162E430) >> 64;\\n }\\n if (x & 0x1000000 > 0) {\\n result = (result * 0x10000000000B17218) >> 64;\\n }\\n if (x & 0x800000 > 0) {\\n result = (result * 0x1000000000058B90C) >> 64;\\n }\\n if (x & 0x400000 > 0) {\\n result = (result * 0x100000000002C5C86) >> 64;\\n }\\n if (x & 0x200000 > 0) {\\n result = (result * 0x10000000000162E43) >> 64;\\n }\\n if (x & 0x100000 > 0) {\\n result = (result * 0x100000000000B1721) >> 64;\\n }\\n if (x & 0x80000 > 0) {\\n result = (result * 0x10000000000058B91) >> 64;\\n }\\n if (x & 0x40000 > 0) {\\n result = (result * 0x1000000000002C5C8) >> 64;\\n }\\n if (x & 0x20000 > 0) {\\n result = (result * 0x100000000000162E4) >> 64;\\n }\\n if (x & 0x10000 > 0) {\\n result = (result * 0x1000000000000B172) >> 64;\\n }\\n if (x & 0x8000 > 0) {\\n result = (result * 0x100000000000058B9) >> 64;\\n }\\n if (x & 0x4000 > 0) {\\n result = (result * 0x10000000000002C5D) >> 64;\\n }\\n if (x & 0x2000 > 0) {\\n result = (result * 0x1000000000000162E) >> 64;\\n }\\n if (x & 0x1000 > 0) {\\n result = (result * 0x10000000000000B17) >> 64;\\n }\\n if (x & 0x800 > 0) {\\n result = (result * 0x1000000000000058C) >> 64;\\n }\\n if (x & 0x400 > 0) {\\n result = (result * 0x100000000000002C6) >> 64;\\n }\\n if (x & 0x200 > 0) {\\n result = (result * 0x10000000000000163) >> 64;\\n }\\n if (x & 0x100 > 0) {\\n result = (result * 0x100000000000000B1) >> 64;\\n }\\n if (x & 0x80 > 0) {\\n result = (result * 0x10000000000000059) >> 64;\\n }\\n if (x & 0x40 > 0) {\\n result = (result * 0x1000000000000002C) >> 64;\\n }\\n if (x & 0x20 > 0) {\\n result = (result * 0x10000000000000016) >> 64;\\n }\\n if (x & 0x10 > 0) {\\n result = (result * 0x1000000000000000B) >> 64;\\n }\\n if (x & 0x8 > 0) {\\n result = (result * 0x10000000000000006) >> 64;\\n }\\n if (x & 0x4 > 0) {\\n result = (result * 0x10000000000000003) >> 64;\\n }\\n if (x & 0x2 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n if (x & 0x1 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n\\n // We're doing two things at the same time:\\n //\\n // 1. Multiply the result by 2^n + 1, where \\\"2^n\\\" is the integer part and the one is added to account for\\n // the fact that we initially set the result to 0.5. This is accomplished by subtracting from 191\\n // rather than 192.\\n // 2. Convert the result to the unsigned 60.18-decimal fixed-point format.\\n //\\n // This works because 2^(191-ip) = 2^ip / 2^191, where \\\"ip\\\" is the integer part \\\"2^n\\\".\\n result *= SCALE;\\n result >>= (191 - (x >> 64));\\n }\\n }\\n\\n /// @notice Finds the zero-based index of the first one in the binary representation of x.\\n /// @dev See the note on msb in the \\\"Find First Set\\\" Wikipedia article https://en.wikipedia.org/wiki/Find_first_set\\n /// @param x The uint256 number for which to find the index of the most significant bit.\\n /// @return msb The index of the most significant bit as an uint256.\\n function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\\n if (x >= 2**128) {\\n x >>= 128;\\n msb += 128;\\n }\\n if (x >= 2**64) {\\n x >>= 64;\\n msb += 64;\\n }\\n if (x >= 2**32) {\\n x >>= 32;\\n msb += 32;\\n }\\n if (x >= 2**16) {\\n x >>= 16;\\n msb += 16;\\n }\\n if (x >= 2**8) {\\n x >>= 8;\\n msb += 8;\\n }\\n if (x >= 2**4) {\\n x >>= 4;\\n msb += 4;\\n }\\n if (x >= 2**2) {\\n x >>= 2;\\n msb += 2;\\n }\\n if (x >= 2**1) {\\n // No need to shift x any more.\\n msb += 1;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.\\n ///\\n /// Requirements:\\n /// - The denominator cannot be zero.\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The multiplicand as an uint256.\\n /// @param y The multiplier as an uint256.\\n /// @param denominator The divisor as an uint256.\\n /// @return result The result as an uint256.\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n unchecked {\\n result = prod0 / denominator;\\n }\\n return result;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n if (prod1 >= denominator) {\\n revert PRBMath__MulDivOverflow(prod1, denominator);\\n }\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n unchecked {\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 lpotdod = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by lpotdod.\\n denominator := div(denominator, lpotdod)\\n\\n // Divide [prod1 prod0] by lpotdod.\\n prod0 := div(prod0, lpotdod)\\n\\n // Flip lpotdod such that it is 2^256 / lpotdod. If lpotdod is zero, then it becomes one.\\n lpotdod := add(div(sub(0, lpotdod), lpotdod), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * lpotdod;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f71e18) with full precision.\\n ///\\n /// @dev Variant of \\\"mulDiv\\\" with constant folding, i.e. in which the denominator is always 1e18. Before returning the\\n /// final result, we add 1 if (x * y) % SCALE >= HALF_SCALE. Without this, 6.6e-19 would be truncated to 0 instead of\\n /// being rounded to 1e-18. See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717.\\n ///\\n /// Requirements:\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - The body is purposely left uncommented; see the NatSpec comments in \\\"PRBMath.mulDiv\\\" to understand how this works.\\n /// - It is assumed that the result can never be type(uint256).max when x and y solve the following two equations:\\n /// 1. x * y = type(uint256).max * SCALE\\n /// 2. (x * y) % SCALE >= SCALE / 2\\n ///\\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function mulDivFixedPoint(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n uint256 prod0;\\n uint256 prod1;\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n if (prod1 >= SCALE) {\\n revert PRBMath__MulDivFixedPointOverflow(prod1);\\n }\\n\\n uint256 remainder;\\n uint256 roundUpUnit;\\n assembly {\\n remainder := mulmod(x, y, SCALE)\\n roundUpUnit := gt(remainder, 499999999999999999)\\n }\\n\\n if (prod1 == 0) {\\n unchecked {\\n result = (prod0 / SCALE) + roundUpUnit;\\n return result;\\n }\\n }\\n\\n assembly {\\n result := add(\\n mul(\\n or(\\n div(sub(prod0, remainder), SCALE_LPOTD),\\n mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, SCALE_LPOTD), SCALE_LPOTD), 1))\\n ),\\n SCALE_INVERSE\\n ),\\n roundUpUnit\\n )\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev An extension of \\\"mulDiv\\\" for signed numbers. Works by computing the signs and the absolute values separately.\\n ///\\n /// Requirements:\\n /// - None of the inputs can be type(int256).min.\\n /// - The result must fit within int256.\\n ///\\n /// @param x The multiplicand as an int256.\\n /// @param y The multiplier as an int256.\\n /// @param denominator The divisor as an int256.\\n /// @return result The result as an int256.\\n function mulDivSigned(\\n int256 x,\\n int256 y,\\n int256 denominator\\n ) internal pure returns (int256 result) {\\n if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {\\n revert PRBMath__MulDivSignedInputTooSmall();\\n }\\n\\n // Get hold of the absolute values of x, y and the denominator.\\n uint256 ax;\\n uint256 ay;\\n uint256 ad;\\n unchecked {\\n ax = x < 0 ? uint256(-x) : uint256(x);\\n ay = y < 0 ? uint256(-y) : uint256(y);\\n ad = denominator < 0 ? uint256(-denominator) : uint256(denominator);\\n }\\n\\n // Compute the absolute value of (x*y)\\u00f7denominator. The result must fit within int256.\\n uint256 rAbs = mulDiv(ax, ay, ad);\\n if (rAbs > uint256(type(int256).max)) {\\n revert PRBMath__MulDivSignedOverflow(rAbs);\\n }\\n\\n // Get the signs of x, y and the denominator.\\n uint256 sx;\\n uint256 sy;\\n uint256 sd;\\n assembly {\\n sx := sgt(x, sub(0, 1))\\n sy := sgt(y, sub(0, 1))\\n sd := sgt(denominator, sub(0, 1))\\n }\\n\\n // XOR over sx, sy and sd. This is checking whether there are one or three negative signs in the inputs.\\n // If yes, the result should be negative.\\n result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs);\\n }\\n\\n /// @notice Calculates the square root of x, rounding down.\\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The uint256 number for which to calculate the square root.\\n /// @return result The result as an uint256.\\n function sqrt(uint256 x) internal pure returns (uint256 result) {\\n if (x == 0) {\\n return 0;\\n }\\n\\n // Set the initial guess to the closest power of two that is higher than x.\\n uint256 xAux = uint256(x);\\n result = 1;\\n if (xAux >= 0x100000000000000000000000000000000) {\\n xAux >>= 128;\\n result <<= 64;\\n }\\n if (xAux >= 0x10000000000000000) {\\n xAux >>= 64;\\n result <<= 32;\\n }\\n if (xAux >= 0x100000000) {\\n xAux >>= 32;\\n result <<= 16;\\n }\\n if (xAux >= 0x10000) {\\n xAux >>= 16;\\n result <<= 8;\\n }\\n if (xAux >= 0x100) {\\n xAux >>= 8;\\n result <<= 4;\\n }\\n if (xAux >= 0x10) {\\n xAux >>= 4;\\n result <<= 2;\\n }\\n if (xAux >= 0x8) {\\n result <<= 1;\\n }\\n\\n // The operations can never overflow because the result is max 2^127 when it enters this block.\\n unchecked {\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1; // Seven iterations should be enough\\n uint256 roundedDownResult = x / result;\\n return result >= roundedDownResult ? roundedDownResult : result;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x62cbabae4910e168e99b9c2c3e3b5c9c7ad5e7abd961dcc63b7ea3d83d8ea87e\",\"license\":\"Unlicense\"}},\"version\":1}", "bytecode": "0x60c060405234801561001057600080fd5b506040516147ad3803806147ad83398101604081905261002f9161008d565b8060405161003c90610080565b6001600160a01b039091168152602001604051809103906000f080158015610068573d6000803e3d6000fd5b506001600160a01b039081166080521660a0526100bd565b613b7e80610c2f83390190565b60006020828403121561009f57600080fd5b81516001600160a01b03811681146100b657600080fd5b9392505050565b60805160a051610b4e6100e1600039600061018b0152600060910152610b4e6000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80631a2a1a201461003b5780632d3fb8a314610077575b600080fd5b61004e6100493660046105b5565b61008a565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b61004e61008536600461077a565b6101e0565b60006100b57f000000000000000000000000000000000000000000000000000000000000000061035a565b6040517fec818c8900000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff82169063ec818c899061011c908e908e908e908e908e908e908e908e908e908e90600401610870565b600060405180830381600087803b15801561013657600080fd5b505af115801561014a573d6000803e3d6000fd5b505050508073ffffffffffffffffffffffffffffffffffffffff167f9d8d9335be0008f50a6547966dd6a854fd9df1f0be7838b8a445b562513627448c8c8c7f00000000000000000000000000000000000000000000000000000000000000008d8d8d8d8d8d8d336040516101ca9c9b9a999897969594939291906108fa565b60405180910390a29a9950505050505050505050565b6040517fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003360601b16602082015243603482015260009030908290605401604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815282825280516020909101206001808452838301909252925060609190816020015b60408051808201909152600081526060602082015281526020019060019003908161026a57905050905060405180604001604052808381526020018e815250816000815181106102bc576102bc6109c6565b60200260200101819052508b73ffffffffffffffffffffffffffffffffffffffff1663f2da44b68f85846040518463ffffffff1660e01b8152600401610304939291906109f5565b600060405180830381600087803b15801561031e57600080fd5b505af1158015610332573d6000803e3d6000fd5b505050506103488e84848e8e8e8e8e8e8e61008a565b9e9d5050505050505050505050505050565b60006040517f3d602d80600a3d3981f3363d3d373d3d3d363d7300000000000000000000000081528260601b60148201527f5af43d82803e903d91602b57fd5bf3000000000000000000000000000000000060288201526037816000f091505073ffffffffffffffffffffffffffffffffffffffff811661043b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f455243313136373a20637265617465206661696c656400000000000000000000604482015260640160405180910390fd5b919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461046257600080fd5b50565b803561043b81610440565b8035801515811461043b57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160e0810167ffffffffffffffff811182821017156104d2576104d2610480565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561051f5761051f610480565b604052919050565b600082601f83011261053857600080fd5b813567ffffffffffffffff81111561055257610552610480565b61058360207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016104d8565b81815284602083860101111561059857600080fd5b816020850160208301376000918101602001919091529392505050565b6000806000806000806000806000806101408b8d0312156105d557600080fd5b8a35995060208b0135985060408b0135975060608b013596506105fa60808c01610465565b955061060860a08c01610470565b945060c08b013567ffffffffffffffff8082111561062557600080fd5b6106318e838f01610527565b955060e08d013591508082111561064757600080fd5b506106548d828e01610527565b9350506106646101008c01610470565b91506106736101208c01610465565b90509295989b9194979a5092959850565b600082601f83011261069557600080fd5b8135602067ffffffffffffffff8211156106b1576106b1610480565b6106bf818360051b016104d8565b82815260e092830285018201928282019190878511156106de57600080fd5b8387015b8581101561076d5781818a0312156106fa5760008081fd5b6107026104af565b61070b82610470565b8152610718868301610470565b81870152604082810135908201526060808301359082015260808083013561073f81610440565b9082015260a0828101359082015260c08083013561075c81610440565b9082015284529284019281016106e2565b5090979650505050505050565b6000806000806000806000806000806101408b8d03121561079a57600080fd5b8a35995060208b013567ffffffffffffffff808211156107b957600080fd5b6107c58e838f01610684565b9a506107d360408e01610465565b995060608d013598506107e860808e01610465565b97506107f660a08e01610470565b965060c08d013591508082111561062557600080fd5b6000815180845260005b8181101561083257602081850181015186830182015201610816565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60006101408c83528b60208401528a604084015289606084015273ffffffffffffffffffffffffffffffffffffffff808a16608085015288151560a08501528160c08501526108c18285018961080c565b915083820360e08501526108d5828861080c565b925085151561010085015280851661012085015250509b9a5050505050505050505050565b60006101808e83528d60208401528c604084015273ffffffffffffffffffffffffffffffffffffffff808d1660608501528b6080850152808b1660a08501525088151560c08401528060e08401526109548184018961080c565b9050828103610100840152610969818861080c565b91505084151561012083015261099861014083018573ffffffffffffffffffffffffffffffffffffffff169052565b73ffffffffffffffffffffffffffffffffffffffff83166101608301529d9c50505050505050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060608083018684526020868186015260408381870152828751808552608094508488019150848160051b890101848a0160005b83811015610b06578a83037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff800185528151805184528701518784018790528051878501819052908801906000908b8601905b80831015610af15783518051151583528b81015115158c8401528a8101518b8401528d8101518e8401528c81015173ffffffffffffffffffffffffffffffffffffffff9081168e85015260a0808301519085015260c0918201511690830152928a01926001929092019160e090910190610a7c565b50968901969450505090860190600101610a2a565b50909c9b50505050505050505050505056fea26469706673582212200ce553bd906a6acfb51f721c67147d428b61e4bb20e8c11fdbe007a2536e8b7364736f6c6343000810003360e06040523480156200001157600080fd5b5060405162003b7e38038062003b7e83398101604081905262000034916200012e565b806001600160a01b031663c41c2f246040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000073573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200009991906200012e565b620000a433620000c5565b6001600160a01b039081166080523360a05260016006551660c05262000155565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146200012b57600080fd5b50565b6000602082840312156200014157600080fd5b81516200014e8162000115565b9392505050565b60805160a05160c0516139d6620001a8600039600081816105910152818161086e0152611c330152600081816106630152611cc70152600081816107c00152818161096f0152610bd301526139d66000f3fe6080604052600436106101845760003560e01c8063715018a6116100d6578063ae16f56a1161007f578063c41c2f2411610059578063c41c2f24146107ae578063ec818c89146107e2578063f2fde38b1461080257600080fd5b8063ae16f56a14610759578063b96053df14610779578063c0048ca51461078e57600080fd5b80638da5cb5b116100b05780638da5cb5b146106ef57806393b7f1541461070d578063a4919eb11461072757600080fd5b8063715018a6146106a55780637e646549146106ba5780638293fee6146106dc57600080fd5b80633ce9830b1161013857806354ab58af1161011257806354ab58af1461063157806364d3ed271461065157806371277d571461068557600080fd5b80633ce9830b146105ef578063421a2fb5146106055780635380cf8f1461061b57600080fd5b80630e45f78e116101695780630e45f78e1461055f5780632bdfe0041461057f5780633c212b1c146105cb57600080fd5b806301ffc9a71461051557806309a6b7e51461054a57600080fd5b36610510576002600654036101e05760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b60026006819055600754600854600954925460009361022893929161eeee9047906012906001600160a01b03166102175732610822565b6002546001600160a01b0316610822565b9050806000036102385750610507565b600154156104d85760055460ff16156103775761037260015461eeee83601260038054610264906128dd565b80601f0160208091040260200160405190810160405280929190818152602001828054610290906128dd565b80156102dd5780601f106102b2576101008083540402835291602001916102dd565b820191906000526020600020905b8154815290600101906020018083116102c057829003601f168201915b5050505050600480546102ef906128dd565b80601f016020809104026020016040519081016040528092919081815260200182805461031b906128dd565b80156103685780601f1061033d57610100808354040283529160200191610368565b820191906000526020600020905b81548152906001019060200180831161034b57829003601f168201915b505050505061092d565b610505565b600154600254610372919061eeee9084906012906001600160a01b031661039e57326103ab565b6002546001600160a01b03165b6000600260149054906101000a900460ff16600380546103ca906128dd565b80601f01602080910402602001604051908101604052809291908181526020018280546103f6906128dd565b80156104435780601f1061041857610100808354040283529160200191610443565b820191906000526020600020905b81548152906001019060200180831161042657829003601f168201915b505050505060048054610455906128dd565b80601f0160208091040260200160405190810160405280929190818152602001828054610481906128dd565b80156104ce5780601f106104a3576101008083540402835291602001916104ce565b820191906000526020600020905b8154815290600101906020018083116104b157829003601f168201915b5050505050610b91565b600254610505906001600160a01b03166104f257326104ff565b6002546001600160a01b03165b82610e52565b505b60016006819055005b600080fd5b34801561052157600080fd5b50610535610530366004612930565b610f70565b60405190151581526020015b60405180910390f35b61055d6105583660046129e0565b610fcc565b005b34801561056b57600080fd5b5061055d61057a366004612bb4565b61135f565b34801561058b57600080fd5b506105b37f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610541565b3480156105d757600080fd5b506105e160095481565b604051908152602001610541565b3480156105fb57600080fd5b506105e160015481565b34801561061157600080fd5b506105e160075481565b34801561062757600080fd5b506105e160085481565b34801561063d57600080fd5b506002546105b3906001600160a01b031681565b34801561065d57600080fd5b506105b37f000000000000000000000000000000000000000000000000000000000000000081565b34801561069157600080fd5b5061055d6106a0366004612c5a565b6115c2565b3480156106b157600080fd5b5061055d611687565b3480156106c657600080fd5b506106cf6116ed565b6040516105419190612cd6565b61055d6106ea366004612ce9565b61177b565b3480156106fb57600080fd5b506000546001600160a01b03166105b3565b34801561071957600080fd5b506005546105359060ff1681565b34801561073357600080fd5b506002546105359074010000000000000000000000000000000000000000900460ff1681565b34801561076557600080fd5b5061055d610774366004612de9565b611ba9565b34801561078557600080fd5b506106cf611caf565b34801561079a57600080fd5b5061055d6107a9366004613031565b611cbc565b3480156107ba57600080fd5b506105b37f000000000000000000000000000000000000000000000000000000000000000081565b3480156107ee57600080fd5b5061055d6107fd3660046130eb565b611dcb565b34801561080e57600080fd5b5061055d61081d3660046131ba565b611df2565b6040517f69e11cc50000000000000000000000000000000000000000000000000000000081526004810188905260248101879052604481018690526000906108e6906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906369e11cc590606401600060405180830381865afa1580156108b5573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108dd91908101906131d7565b86868686611ed4565b604051338152909150869088908a907f2522c1d6a5eb94bdf38d0007aadcdd12c34a8b834b915ab71117e8c0a7e5df809060200160405180910390a4979650505050505050565b6040517f86202650000000000000000000000000000000000000000000000000000000008152600481018790526001600160a01b0386811660248301526000917f000000000000000000000000000000000000000000000000000000000000000090911690638620265090604401602060405180830381865afa1580156109b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109dc91906132e1565b90506001600160a01b038116610a1e576040517ffba10dd600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fb7bad1b10000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015285919083169063b7bad1b190602401602060405180830381865afa158015610a80573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aa491906132fe565b14610adb576040517fb972592400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03861661eeee14610b0157610b016001600160a01b038716828761220f565b60006001600160a01b03871661eeee14610b1c576000610b1e565b855b9050816001600160a01b0316630cf8e858828a898b89896040518763ffffffff1660e01b8152600401610b55959493929190613317565b6000604051808303818588803b158015610b6e57600080fd5b505af1158015610b82573d6000803e3d6000fd5b50505050505050505050505050565b6040517f86202650000000000000000000000000000000000000000000000000000000008152600481018a90526001600160a01b0389811660248301526000917f000000000000000000000000000000000000000000000000000000000000000090911690638620265090604401602060405180830381865afa158015610c1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c4091906132e1565b90506001600160a01b038116610c82576040517ffba10dd600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fb7bad1b10000000000000000000000000000000000000000000000000000000081526001600160a01b038a8116600483015288919083169063b7bad1b190602401602060405180830381865afa158015610ce4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d0891906132fe565b14610d3f576040517fb972592400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600160a01b03891661eeee14610d6557610d656001600160a01b038a16828a61220f565b60006001600160a01b038a1661eeee14610d80576000610d82565b885b9050816001600160a01b0316631ebc263f828d8c8e60006001600160a01b03168d6001600160a01b031603610dd8576002546001600160a01b0316610dc75732610dda565b6002546001600160a01b0316610dda565b8c5b8c8c8c8c6040518a63ffffffff1660e01b8152600401610e01989796959493929190613363565b60206040518083038185885af1158015610e1f573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610e4491906132fe565b505050505050505050505050565b80471015610ea25760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e636500000060448201526064016101d7565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114610eef576040519150601f19603f3d011682016040523d82523d6000602084013e610ef4565b606091505b5050905080610f6b5760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d6179206861766520726576657274656400000000000060648201526084016101d7565b505050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f35d42f96000000000000000000000000000000000000000000000000000000001480610fc65750610fc6826123bd565b92915050565b60026006540361101e5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016101d7565b60026006556001600160a01b03871661eeee1461119d57341561106d576040517fbcfd35be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038916906370a0823190602401602060405180830381865afa1580156110cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110f191906132fe565b90506111086001600160a01b03891633308a612454565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015281906001600160a01b038a16906370a0823190602401602060405180830381865afa158015611167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061118b91906132fe565b61119591906133cd565b9650506111a5565b349550601294505b6007546008546009546002546000936111d593909290918c908c908c906001600160a01b03166102175732610822565b905080156112e157881561125f5761125a8989838989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8d018190048102820181019092528b815292508b91508a908190840183828082843760009201919091525061092d92505050565b6112e1565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11126001600160a01b038916016112a95760025461125a906001600160a01b03166104f257326104ff565b6002546112e1906001600160a01b03166112c357326112d0565b6002546001600160a01b03165b6001600160a01b038a1690836124a5565b60025489907f5f17f788c7f8d3fd7332fb1e6c42a67accbf9bb129ac8e4389fe693b506369f1906001600160a01b031661131b5732611328565b6002546001600160a01b03165b8a8a8a868b8b8b8b336040516113479a99989796959493929190613432565b60405180910390a25050600160065550505050505050565b6000546001600160a01b031633146113b95760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016101d7565b60015486146113c85760018690555b6002546001600160a01b0386811691161461141157600280547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0387161790555b600260149054906101000a900460ff1615158415151461146f57600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000861515021790555b60036040516020016114819190613532565b60405160208183030381529060405280519060200120836040516020016114a8919061353e565b60405160208183030381529060405280519060200120146114d15760036114cf84826135a8565b505b60046040516020016114e39190613532565b604051602081830303815290604052805190602001208260405160200161150a919061353e565b604051602081830303815290604052805190602001201461153357600461153183826135a8565b505b60055460ff1615158115151461157057600580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168215151790555b846001600160a01b0316867f36b1c5cef608e320317b9ee5155756634c65fe7055b424ce57e2f6c59eec794786868686336040516115b29594939291906136a4565b60405180910390a3505050505050565b6000546001600160a01b0316331461161c5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016101d7565b600754831461162b5760078390555b600854821461163a5760088290555b60095481146116495760098190555b6040513381528190839085907f5ef5a6931855992f84842284a6bba50d74bfe8654238b4d6325427473a90f3a59060200160405180910390a4505050565b6000546001600160a01b031633146116e15760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016101d7565b6116eb60006124ee565b565b600480546116fa906128dd565b80601f0160208091040260200160405190810160405280929190818152602001828054611726906128dd565b80156117735780601f1061174857610100808354040283529160200191611773565b820191906000526020600020905b81548152906001019060200180831161175657829003601f168201915b505050505081565b6002600654036117cd5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016101d7565b60026006556001600160a01b038a1661eeee1461194c57341561181c576040517fbcfd35be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038c16906370a0823190602401602060405180830381865afa15801561187c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118a091906132fe565b90506118b76001600160a01b038c1633308d612454565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015281906001600160a01b038d16906370a0823190602401602060405180830381865afa158015611916573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061193a91906132fe565b61194491906133cd565b995050611954565b349850601297505b60075460085460095460025460009361198493909290918f908f908f906001600160a01b03166102175732610822565b90508015611b12578b15611a5857611a538c8c838c6001600160a01b038d166119ce576002546001600160a01b03166119bd57326119d0565b6002546001600160a01b03166119d0565b8c5b8c8c8c8c8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610b9192505050565b611b12565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11126001600160a01b038c1601611ac757611a536001600160a01b038916611ac0576002546001600160a01b0316611aaf57326104ff565b6002546001600160a01b03166104ff565b8882610e52565b611b126001600160a01b038916611aff576002546001600160a01b0316611aee5732611b01565b6002546001600160a01b0316611b01565b885b6001600160a01b038d1690836124a5565b8b7f72877920bfc936c0f18c54961abe3105d7d2990103eaa013cd8420fecacb0b606001600160a01b038a16611b69576002546001600160a01b0316611b585732611b6b565b6002546001600160a01b0316611b6b565b895b8d8d8d868d8d8d8d8d8d33604051611b8e9c9b9a999897969594939291906136f4565b60405180910390a25050600160065550505050505050505050565b6000546001600160a01b03163314611c035760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016101d7565b6040517ff2da44b60000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063f2da44b690611c6c90879087908690600401613774565b600060405180830381600087803b158015611c8657600080fd5b505af1158015611c9a573d6000803e3d6000fd5b50505050611ca98484846115c2565b50505050565b600380546116fa906128dd565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614611d1e576040517f439a74c900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018790556002805486151574010000000000000000000000000000000000000000027fffffffffffffffffffffff0000000000000000000000000000000000000000009091166001600160a01b038916171790556003611d7f85826135a8565b506004611d8c84826135a8565b50600580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016831515179055611dc2816124ee565b50505050505050565b611dda87878787878787611cbc565b50505060079690965550505060089190915560095550565b6000546001600160a01b03163314611e4c5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016101d7565b6001600160a01b038116611ec85760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016101d7565b611ed1816124ee565b50565b8260005b8651811015612205576000878281518110611ef557611ef561389d565b602002602001015190506000611f14878360400151633b9aca00612556565b905080156121be5760c08201516001600160a01b0316156120ae576040805160c0810182526001600160a01b038a168082526020820184905291810188905260015460608201526000608082015260a081018490529061eeee14611f8c5760c0830151611f8c906001600160a01b038b16908461220f565b60006001600160a01b038a1661eeee14611fa7576000611fa9565b825b60c080860151604080517f9d740bfa00000000000000000000000000000000000000000000000000000000815286516001600160a01b03908116600483015260208089015160248401528389015160448401526060808a015160648501526080808b0151608486015260a0808c01518051151560a488015293840151151560c48701529583015160e486015290820151610104850152810151821661012484015292830151610144830152919093015181166101648401529293509190911690639d740bfa908390610184016000604051808303818588803b15801561208e57600080fd5b505af11580156120a2573d6000803e3d6000fd5b505050505050506121b1565b606082015115612128578160200151156120df576120da826060015189838960038054610264906128dd565b6121b1565b6120da826060015189838960006001600160a01b031687608001516001600160a01b03160361210e5789612114565b86608001515b60008860000151600380546103ca906128dd565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11126001600160a01b0389160161217f5760808201516120da906001600160a01b031661217457856104ff565b826080015182610e52565b60808201516121b1906001600160a01b031661219b57856112d0565b82608001516001600160a01b038a1690836124a5565b6121bb81856133cd565b93505b7ff44ffe151def7bd57d653ffdd625b5cfff3e6992ad5b8eb1f021cdaca6599544828287336040516121f394939291906138cc565b60405180910390a15050600101611ed8565b5095945050505050565b8015806122a257506040517fdd62ed3e0000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa15801561227c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122a091906132fe565b155b6123145760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527f20746f206e6f6e2d7a65726f20616c6c6f77616e63650000000000000000000060648201526084016101d7565b6040516001600160a01b038316602482015260448101829052610f6b9084907f095ea7b300000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152612660565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7ddb72fc000000000000000000000000000000000000000000000000000000001480610fc657507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831614610fc6565b6040516001600160a01b0380851660248301528316604482015260648101829052611ca99085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401612359565b6040516001600160a01b038316602482015260448101829052610f6b9084907fa9059cbb0000000000000000000000000000000000000000000000000000000090606401612359565b600080546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600080807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff858709858702925082811083820303915050806000036125ae578382816125a4576125a4613954565b0492505050612659565b8381106125f1576040517f773cc18c00000000000000000000000000000000000000000000000000000000815260048101829052602481018590526044016101d7565b600084868809851960019081018716968790049682860381900495909211909303600082900391909104909201919091029190911760038402600290811880860282030280860282030280860282030280860282030280860282030280860290910302029150505b9392505050565b60006126b5826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166127459092919063ffffffff16565b805190915015610f6b57808060200190518101906126d39190613983565b610f6b5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016101d7565b6060612754848460008561275c565b949350505050565b6060824710156127d45760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016101d7565b6001600160a01b0385163b61282b5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016101d7565b600080866001600160a01b03168587604051612847919061353e565b60006040518083038185875af1925050503d8060008114612884576040519150601f19603f3d011682016040523d82523d6000602084013e612889565b606091505b50915091506128998282866128a4565b979650505050505050565b606083156128b3575081612659565b8251156128c35782518084602001fd5b8160405162461bcd60e51b81526004016101d79190612cd6565b600181811c908216806128f157607f821691505b60208210810361292a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60006020828403121561294257600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461265957600080fd5b6001600160a01b0381168114611ed157600080fd5b803561299281612972565b919050565b60008083601f8401126129a957600080fd5b50813567ffffffffffffffff8111156129c157600080fd5b6020830191508360208285010111156129d957600080fd5b9250929050565b60008060008060008060008060c0898b0312156129fc57600080fd5b883597506020890135612a0e81612972565b96506040890135955060608901359450608089013567ffffffffffffffff80821115612a3957600080fd5b612a458c838d01612997565b909650945060a08b0135915080821115612a5e57600080fd5b50612a6b8b828c01612997565b999c989b5096995094979396929594505050565b8015158114611ed157600080fd5b803561299281612a7f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715612aea57612aea612a98565b60405290565b60405160e0810167ffffffffffffffff81118282101715612aea57612aea612a98565b604051601f8201601f1916810167ffffffffffffffff81118282101715612b3c57612b3c612a98565b604052919050565b600082601f830112612b5557600080fd5b813567ffffffffffffffff811115612b6f57612b6f612a98565b612b826020601f19601f84011601612b13565b818152846020838601011115612b9757600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060c08789031215612bcd57600080fd5b863595506020870135612bdf81612972565b94506040870135612bef81612a7f565b9350606087013567ffffffffffffffff80821115612c0c57600080fd5b612c188a838b01612b44565b94506080890135915080821115612c2e57600080fd5b50612c3b89828a01612b44565b92505060a0870135612c4c81612a7f565b809150509295509295509295565b600080600060608486031215612c6f57600080fd5b505081359360208301359350604090920135919050565b60005b83811015612ca1578181015183820152602001612c89565b50506000910152565b60008151808452612cc2816020860160208601612c86565b601f01601f19169290920160200192915050565b6020815260006126596020830184612caa565b60008060008060008060008060008060006101208c8e031215612d0b57600080fd5b8b359a50612d1c60208d0135612972565b60208c0135995060408c0135985060608c01359750612d3e60808d0135612972565b60808c0135965060a08c01359550612d5860c08d01612a8d565b945067ffffffffffffffff8060e08e01351115612d7457600080fd5b612d848e60e08f01358f01612997565b90955093506101008d0135811015612d9b57600080fd5b50612dad8d6101008e01358e01612997565b81935080925050509295989b509295989b9093969950565b600067ffffffffffffffff821115612ddf57612ddf612a98565b5060051b60200190565b60008060008060808587031215612dff57600080fd5b84359350602085013592506040850135915067ffffffffffffffff60608601351115612e2a57600080fd5b85601f606087013587010112612e3f57600080fd5b612e57612e526060870135870135612dc5565b612b13565b6060860135860180358083526020808401939260059290921b90910101881015612e8057600080fd5b602060608801358801015b60608801358801803560051b016020018110156130245767ffffffffffffffff81351115612eb857600080fd5b6040601f19823560608b01358b01018b03011215612ed557600080fd5b612edd612ac7565b606089013589018235016020810135825267ffffffffffffffff6040909101351115612f0857600080fd5b60608901358901823501604081013501603f81018b13612f2757600080fd5b612f37612e526020830135612dc5565b602082810135808352908201919060e00283016040018d1015612f5957600080fd5b604083015b604060e060208601350285010181101561300b5760e0818f031215612f8257600080fd5b612f8a612af0565b612f948235612a7f565b81358152612fa56020830135612a7f565b602082013560208201526040820135604082015260608201356060820152612fd06080830135612972565b6080820135608082015260a082013560a0820152612ff160c0830135612972565b60c08281013590820152835260209092019160e001612f5e565b5060208481019190915292865250509283019201612e8b565b5094979396509194505050565b600080600080600080600060e0888a03121561304c57600080fd5b87359650602088013561305e81612972565b9550604088013561306e81612a7f565b9450606088013567ffffffffffffffff8082111561308b57600080fd5b6130978b838c01612b44565b955060808a01359150808211156130ad57600080fd5b506130ba8a828b01612b44565b93505060a08801356130cb81612a7f565b915060c08801356130db81612972565b8091505092959891949750929550565b6000806000806000806000806000806101408b8d03121561310b57600080fd5b8a35995060208b0135985060408b0135975060608b0135965061313060808c01612987565b955061313e60a08c01612a8d565b945060c08b013567ffffffffffffffff8082111561315b57600080fd5b6131678e838f01612b44565b955060e08d013591508082111561317d57600080fd5b5061318a8d828e01612b44565b93505061319a6101008c01612a8d565b91506131a96101208c01612987565b90509295989b9194979a5092959850565b6000602082840312156131cc57600080fd5b813561265981612972565b600060208083850312156131ea57600080fd5b825167ffffffffffffffff81111561320157600080fd5b8301601f8101851361321257600080fd5b8051613220612e5282612dc5565b81815260e0918202830184019184820191908884111561323f57600080fd5b938501935b838510156132d55780858a03121561325c5760008081fd5b613264612af0565b855161326f81612a7f565b81528587015161327e81612a7f565b8188015260408681015190820152606080870151908201526080808701516132a581612972565b9082015260a0868101519082015260c0808701516132c281612972565b9082015283529384019391850191613244565b50979650505050505050565b6000602082840312156132f357600080fd5b815161265981612972565b60006020828403121561331057600080fd5b5051919050565b8581528460208201526001600160a01b038416604082015260a06060820152600061334560a0830185612caa565b82810360808401526133578185612caa565b98975050505050505050565b60006101008a83528960208401526001600160a01b03808a16604085015280891660608501525086608084015285151560a08401528060c08401526133aa81840186612caa565b905082810360e08401526133be8185612caa565b9b9a5050505050505050505050565b81810381811115610fc6577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818352818160208501375060006020828401015260006020601f19601f840116840101905092915050565b60006101006001600160a01b03808e168452808d1660208501528b60408501528a60608501528960808501528160a0850152613471828501898b613407565b915083820360c0850152613486828789613407565b925080851660e085015250509b9a5050505050505050505050565b600081546134ae816128dd565b600182811680156134c657600181146134f957613528565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0084168752821515830287019450613528565b8560005260208060002060005b8581101561351f5781548a820152908401908201613506565b50505082870194505b5050505092915050565b600061265982846134a1565b60008251613550818460208701612c86565b9190910192915050565b601f821115610f6b57600081815260208120601f850160051c810160208610156135815750805b601f850160051c820191505b818110156135a05782815560010161358d565b505050505050565b815167ffffffffffffffff8111156135c2576135c2612a98565b6135d6816135d084546128dd565b8461355a565b602080601f83116001811461362957600084156135f35750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556135a0565b600085815260208120601f198616915b8281101561365857888601518255948401946001909101908401613639565b508582101561369457878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b851515815260a0602082015260006136bf60a0830187612caa565b82810360408401526136d18187612caa565b941515606084015250506001600160a01b03919091166080909101529392505050565b60006001600160a01b03808f168352808e1660208401528c60408401528b60608401528a60808401528960a084015288151560c084015261014060e08401526137426101408401888a613407565b838103610100850152613756818789613407565b925050808416610120840152509d9c50505050505050505050505050565b60006060808301868452602086818601526040838187015282875180855260808801915060808160051b89010194508389016000805b8381101561388b578a88037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff800185528251805189528701518789018790528051878a018190529088019083908b8b01905b8083101561387657613860828551805115158252602081015115156020830152604081015160408301526060810151606083015260808101516001600160a01b03808216608085015260a083015160a08501528060c08401511660c085015250505050565b60e0820191508a840193506001830192506137fb565b509950505093860193918601916001016137aa565b50959c9b505050505050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b610140810161392d8287805115158252602081015115156020830152604081015160408301526060810151606083015260808101516001600160a01b03808216608085015260a083015160a08501528060c08401511660c085015250505050565b60e08201949094526001600160a01b03928316610100820152911661012090910152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006020828403121561399557600080fd5b815161265981612a7f56fea26469706673582212208c9af2b4648981cff6fb1cbd7aa3f4bb5ce48d5a26e15246a6f617cd311d398764736f6c63430008100033", "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80631a2a1a201461003b5780632d3fb8a314610077575b600080fd5b61004e6100493660046105b5565b61008a565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b61004e61008536600461077a565b6101e0565b60006100b57f000000000000000000000000000000000000000000000000000000000000000061035a565b6040517fec818c8900000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff82169063ec818c899061011c908e908e908e908e908e908e908e908e908e908e90600401610870565b600060405180830381600087803b15801561013657600080fd5b505af115801561014a573d6000803e3d6000fd5b505050508073ffffffffffffffffffffffffffffffffffffffff167f9d8d9335be0008f50a6547966dd6a854fd9df1f0be7838b8a445b562513627448c8c8c7f00000000000000000000000000000000000000000000000000000000000000008d8d8d8d8d8d8d336040516101ca9c9b9a999897969594939291906108fa565b60405180910390a29a9950505050505050505050565b6040517fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003360601b16602082015243603482015260009030908290605401604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815282825280516020909101206001808452838301909252925060609190816020015b60408051808201909152600081526060602082015281526020019060019003908161026a57905050905060405180604001604052808381526020018e815250816000815181106102bc576102bc6109c6565b60200260200101819052508b73ffffffffffffffffffffffffffffffffffffffff1663f2da44b68f85846040518463ffffffff1660e01b8152600401610304939291906109f5565b600060405180830381600087803b15801561031e57600080fd5b505af1158015610332573d6000803e3d6000fd5b505050506103488e84848e8e8e8e8e8e8e61008a565b9e9d5050505050505050505050505050565b60006040517f3d602d80600a3d3981f3363d3d373d3d3d363d7300000000000000000000000081528260601b60148201527f5af43d82803e903d91602b57fd5bf3000000000000000000000000000000000060288201526037816000f091505073ffffffffffffffffffffffffffffffffffffffff811661043b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f455243313136373a20637265617465206661696c656400000000000000000000604482015260640160405180910390fd5b919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461046257600080fd5b50565b803561043b81610440565b8035801515811461043b57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160e0810167ffffffffffffffff811182821017156104d2576104d2610480565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561051f5761051f610480565b604052919050565b600082601f83011261053857600080fd5b813567ffffffffffffffff81111561055257610552610480565b61058360207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016104d8565b81815284602083860101111561059857600080fd5b816020850160208301376000918101602001919091529392505050565b6000806000806000806000806000806101408b8d0312156105d557600080fd5b8a35995060208b0135985060408b0135975060608b013596506105fa60808c01610465565b955061060860a08c01610470565b945060c08b013567ffffffffffffffff8082111561062557600080fd5b6106318e838f01610527565b955060e08d013591508082111561064757600080fd5b506106548d828e01610527565b9350506106646101008c01610470565b91506106736101208c01610465565b90509295989b9194979a5092959850565b600082601f83011261069557600080fd5b8135602067ffffffffffffffff8211156106b1576106b1610480565b6106bf818360051b016104d8565b82815260e092830285018201928282019190878511156106de57600080fd5b8387015b8581101561076d5781818a0312156106fa5760008081fd5b6107026104af565b61070b82610470565b8152610718868301610470565b81870152604082810135908201526060808301359082015260808083013561073f81610440565b9082015260a0828101359082015260c08083013561075c81610440565b9082015284529284019281016106e2565b5090979650505050505050565b6000806000806000806000806000806101408b8d03121561079a57600080fd5b8a35995060208b013567ffffffffffffffff808211156107b957600080fd5b6107c58e838f01610684565b9a506107d360408e01610465565b995060608d013598506107e860808e01610465565b97506107f660a08e01610470565b965060c08d013591508082111561062557600080fd5b6000815180845260005b8181101561083257602081850181015186830182015201610816565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60006101408c83528b60208401528a604084015289606084015273ffffffffffffffffffffffffffffffffffffffff808a16608085015288151560a08501528160c08501526108c18285018961080c565b915083820360e08501526108d5828861080c565b925085151561010085015280851661012085015250509b9a5050505050505050505050565b60006101808e83528d60208401528c604084015273ffffffffffffffffffffffffffffffffffffffff808d1660608501528b6080850152808b1660a08501525088151560c08401528060e08401526109548184018961080c565b9050828103610100840152610969818861080c565b91505084151561012083015261099861014083018573ffffffffffffffffffffffffffffffffffffffff169052565b73ffffffffffffffffffffffffffffffffffffffff83166101608301529d9c50505050505050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060608083018684526020868186015260408381870152828751808552608094508488019150848160051b890101848a0160005b83811015610b06578a83037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff800185528151805184528701518784018790528051878501819052908801906000908b8601905b80831015610af15783518051151583528b81015115158c8401528a8101518b8401528d8101518e8401528c81015173ffffffffffffffffffffffffffffffffffffffff9081168e85015260a0808301519085015260c0918201511690830152928a01926001929092019160e090910190610a7c565b50968901969450505090860190600101610a2a565b50909c9b50505050505050505050505056fea26469706673582212200ce553bd906a6acfb51f721c67147d428b61e4bb20e8c11fdbe007a2536e8b7364736f6c63430008100033", "devdoc": { - "details": "Adheres to - IJBETHERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.", + "details": "Adheres to - IJBGasTokenERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.", "kind": "dev", "methods": { "deploySplitsPayer(uint256,uint256,uint256,uint256,address,bool,string,bytes,bool,address)": { diff --git a/deployments/mainnet/JBETHPaymentTerminal.json b/deployments/mainnet/JBETHPaymentTerminal.json index dfe8ddaaa..cc607362e 100644 --- a/deployments/mainnet/JBETHPaymentTerminal.json +++ b/deployments/mainnet/JBETHPaymentTerminal.json @@ -1717,7 +1717,7 @@ ], "numDeployments": 1, "solcInputHash": "7f5ae5369c2a685c882e67f75315b841", - "metadata": "{\"compiler\":{\"version\":\"0.8.16+commit.07a7930e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_baseWeightCurrency\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBOperatorStore\",\"name\":\"_operatorStore\",\"type\":\"address\"},{\"internalType\":\"contract IJBProjects\",\"name\":\"_projects\",\"type\":\"address\"},{\"internalType\":\"contract IJBDirectory\",\"name\":\"_directory\",\"type\":\"address\"},{\"internalType\":\"contract IJBSplitsStore\",\"name\":\"_splitsStore\",\"type\":\"address\"},{\"internalType\":\"contract IJBPrices\",\"name\":\"_prices\",\"type\":\"address\"},{\"internalType\":\"contract IJBSingleTokenPaymentTerminalStore\",\"name\":\"_store\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"FEE_TOO_HIGH\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INADEQUATE_DISTRIBUTION_AMOUNT\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INADEQUATE_RECLAIM_AMOUNT\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INADEQUATE_TOKEN_COUNT\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NO_MSG_VALUE_ALLOWED\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PAY_TO_ZERO_ADDRESS\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"prod1\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"denominator\",\"type\":\"uint256\"}],\"name\":\"PRBMath__MulDivOverflow\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PROJECT_TERMINAL_MISMATCH\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"REDEEM_TO_ZERO_ADDRESS\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TERMINAL_IN_SPLIT_ZERO_ADDRESS\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TERMINAL_TOKENS_INCOMPATIBLE\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UNAUTHORIZED\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"refundedFees\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AddToBalance\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IJBPayDelegate\",\"name\":\"delegate\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"currentFundingCycleConfiguration\",\"type\":\"uint256\"},{\"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\"},{\"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\":\"forwardedAmount\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"projectTokenCount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"preferClaimedTokens\",\"type\":\"bool\"},{\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"struct JBDidPayData\",\"name\":\"data\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"delegatedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"DelegateDidPay\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IJBRedemptionDelegate\",\"name\":\"delegate\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"currentFundingCycleConfiguration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"projectTokenCount\",\"type\":\"uint256\"},{\"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\":\"reclaimedAmount\",\"type\":\"tuple\"},{\"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\":\"forwardedAmount\",\"type\":\"tuple\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"struct JBDidRedeemData\",\"name\":\"data\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"delegatedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"DelegateDidRedeem\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleConfiguration\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleNumber\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"distributedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"beneficiaryDistributionAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"DistributePayouts\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"domain\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"group\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"preferClaimed\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"preferAddToBalance\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"percent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"lockedUntil\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBSplitAllocator\",\"name\":\"allocator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"struct JBSplit\",\"name\":\"split\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"DistributeToPayoutSplit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"feeDiscount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"HoldFee\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"contract IJBPaymentTerminal\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Migrate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleConfiguration\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleNumber\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"beneficiaryTokenCount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Pay\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"wasHeld\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"ProcessFee\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleConfiguration\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleNumber\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenCount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"reclaimedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"RedeemTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"refundedFees\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"leftoverAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"RefundHeldFees\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"SetFee\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IJBFeeGauge\",\"name\":\"feeGauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"SetFeeGauge\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"addrs\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"flag\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"SetFeelessAddress\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleConfiguration\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleNumber\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"distributedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"netDistributedamount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"UseAllowance\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"}],\"name\":\"acceptsToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"addToBalanceOf\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"baseWeightCurrency\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currency\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"currencyForToken\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"}],\"name\":\"currentEthOverflowOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"decimalsForToken\",\"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\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_currency\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_minReturnedTokens\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"}],\"name\":\"distributePayoutsOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"netLeftoverDistributionAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"feeGauge\",\"outputs\":[{\"internalType\":\"contract IJBFeeGauge\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"}],\"name\":\"heldFeesOf\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"fee\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"feeDiscount\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"internalType\":\"struct JBFee[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isFeelessAddress\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBPaymentTerminal\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"migrate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"operatorStore\",\"outputs\":[{\"internalType\":\"contract IJBOperatorStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_minReturnedTokens\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"_preferClaimedTokens\",\"type\":\"bool\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"pay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"payoutSplitsGroup\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"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\"}],\"name\":\"processFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"projects\",\"outputs\":[{\"internalType\":\"contract IJBProjects\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_holder\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_tokenCount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_minReturnedTokens\",\"type\":\"uint256\"},{\"internalType\":\"address payable\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"redeemTokensOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"reclaimAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_fee\",\"type\":\"uint256\"}],\"name\":\"setFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IJBFeeGauge\",\"name\":\"_feeGauge\",\"type\":\"address\"}],\"name\":\"setFeeGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_flag\",\"type\":\"bool\"}],\"name\":\"setFeelessAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"splitsStore\",\"outputs\":[{\"internalType\":\"contract IJBSplitsStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"store\",\"outputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminalStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_currency\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_minReturnedTokens\",\"type\":\"uint256\"},{\"internalType\":\"address payable\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"}],\"name\":\"useAllowanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"netDistributedAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Inherits from - JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\",\"kind\":\"dev\",\"methods\":{\"acceptsToken(address,uint256)\":{\"params\":{\"_projectId\":\"The project ID to check for token acceptance.\",\"_token\":\"The token to check if this terminal accepts or not.\"},\"returns\":{\"_0\":\"The flag.\"}},\"addToBalanceOf(uint256,uint256,address,string,bytes)\":{\"params\":{\"_amount\":\"The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\",\"_memo\":\"A memo to pass along to the emitted event.\",\"_metadata\":\"Extra data to pass along to the emitted event.\",\"_projectId\":\"The ID of the project to which the funds received belong.\",\"_token\":\"The token being paid. This terminal ignores this property since it only manages one currency. \"}},\"constructor\":{\"params\":{\"_baseWeightCurrency\":\"The currency to base token issuance on.\",\"_directory\":\"A contract storing directories of terminals and controllers for each project.\",\"_operatorStore\":\"A contract storing operator assignments.\",\"_owner\":\"The address that will own this contract.\",\"_prices\":\"A contract that exposes price feeds.\",\"_projects\":\"A contract which mints ERC-721's that represent project ownership and transfers.\",\"_splitsStore\":\"A contract that stores splits for each project.\",\"_store\":\"A contract that stores the terminal's data.\"}},\"currencyForToken(address)\":{\"params\":{\"_token\":\"The token to check for the currency of.\"},\"returns\":{\"_0\":\"The currency index.\"}},\"currentEthOverflowOf(uint256)\":{\"details\":\"The current overflow is represented as a fixed point number with 18 decimals.\",\"params\":{\"_projectId\":\"The ID of the project to get overflow for.\"},\"returns\":{\"_0\":\"The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\"}},\"decimalsForToken(address)\":{\"params\":{\"_token\":\"The token to check for the decimals of.\"},\"returns\":{\"_0\":\"The number of decimals for the token.\"}},\"distributePayoutsOf(uint256,uint256,uint256,address,uint256,string)\":{\"details\":\"Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\",\"params\":{\"_amount\":\"The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\",\"_currency\":\"The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\",\"_memo\":\"A memo to pass along to the emitted event.\",\"_minReturnedTokens\":\"The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\",\"_projectId\":\"The ID of the project having its payouts distributed.\",\"_token\":\"The token being distributed. This terminal ignores this property since it only manages one token. \"},\"returns\":{\"netLeftoverDistributionAmount\":\"The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\"}},\"heldFeesOf(uint256)\":{\"params\":{\"_projectId\":\"The ID of the project for which fees are being held.\"},\"returns\":{\"_0\":\"An array of fees that are being held.\"}},\"migrate(uint256,address)\":{\"details\":\"Only a project's owner or a designated operator can migrate it.\",\"params\":{\"_projectId\":\"The ID of the project being migrated.\",\"_to\":\"The terminal contract that will gain the project's funds.\"},\"returns\":{\"balance\":\"The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pay(uint256,uint256,address,address,uint256,bool,string,bytes)\":{\"params\":{\"_amount\":\"The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\",\"_beneficiary\":\"The address to mint tokens for and pass along to the funding cycle's data source and delegate.\",\"_memo\":\"A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\",\"_metadata\":\"Bytes to send along to the data source, delegate, and emitted event, if provided.\",\"_minReturnedTokens\":\"The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\",\"_preferClaimedTokens\":\"A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\",\"_projectId\":\"The ID of the project being paid.\",\"_token\":\"The token being paid. This terminal ignores this property since it only manages one token. \"},\"returns\":{\"_0\":\"The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\"}},\"processFees(uint256)\":{\"details\":\"Only a project owner, an operator, or the contract's owner can process held fees.\",\"params\":{\"_projectId\":\"The ID of the project whos held fees should be processed.\"}},\"redeemTokensOf(address,uint256,uint256,address,uint256,address,string,bytes)\":{\"details\":\"Only a token holder or a designated operator can redeem its tokens.\",\"params\":{\"_beneficiary\":\"The address to send the terminal tokens to.\",\"_holder\":\"The account to redeem tokens for.\",\"_memo\":\"A memo to pass along to the emitted event.\",\"_metadata\":\"Bytes to send along to the data source, delegate, and emitted event, if provided.\",\"_minReturnedTokens\":\"The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\",\"_projectId\":\"The ID of the project to which the tokens being redeemed belong.\",\"_token\":\"The token being reclaimed. This terminal ignores this property since it only manages one token. \",\"_tokenCount\":\"The number of project tokens to redeem, as a fixed point number with 18 decimals.\"},\"returns\":{\"reclaimAmount\":\"The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"setFee(uint256)\":{\"details\":\"Only the owner of this contract can change the fee.\",\"params\":{\"_fee\":\"The new fee, out of MAX_FEE.\"}},\"setFeeGauge(address)\":{\"details\":\"Only the owner of this contract can change the fee gauge.\",\"params\":{\"_feeGauge\":\"The new fee gauge.\"}},\"setFeelessAddress(address,bool)\":{\"details\":\"Only the owner of this contract can set addresses as feeless.\",\"params\":{\"_address\":\"The address that can be paid towards while still bypassing fees.\",\"_flag\":\"A flag indicating whether the terminal should be feeless or not.\"}},\"supportsInterface(bytes4)\":{\"details\":\" See {IERC165-supportsInterface}.\",\"params\":{\"_interfaceId\":\"The ID of the interface to check for adherance to.\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"useAllowanceOf(uint256,uint256,uint256,address,uint256,address,string)\":{\"details\":\"Only a project's owner or a designated operator can use its allowance.Incurs the protocol fee.\",\"params\":{\"_amount\":\"The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\",\"_beneficiary\":\"The address to send the funds to.\",\"_currency\":\"The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\",\"_memo\":\"A memo to pass along to the emitted event.\",\"_minReturnedTokens\":\"The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\",\"_projectId\":\"The ID of the project to use the allowance of.\",\"_token\":\"The token being distributed. This terminal ignores this property since it only manages one token. \"},\"returns\":{\"netDistributedAmount\":\"The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\"}}},\"version\":1},\"userdoc\":{\"errors\":{\"PRBMath__MulDivOverflow(uint256,uint256)\":[{\"notice\":\"Emitted when the result overflows uint256.\"}]},\"kind\":\"user\",\"methods\":{\"acceptsToken(address,uint256)\":{\"notice\":\"A flag indicating if this terminal accepts the specified token.\"},\"addToBalanceOf(uint256,uint256,address,string,bytes)\":{\"notice\":\"Receives funds belonging to the specified project.\"},\"baseWeightCurrency()\":{\"notice\":\"The currency to base token issuance on.\"},\"currency()\":{\"notice\":\"The currency to use when resolving price feeds for this terminal.\"},\"currencyForToken(address)\":{\"notice\":\"The currency that should be used for the specified token.\"},\"currentEthOverflowOf(uint256)\":{\"notice\":\"Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\"},\"decimals()\":{\"notice\":\"The number of decimals the token fixed point amounts are expected to have.\"},\"decimalsForToken(address)\":{\"notice\":\"The decimals that should be used in fixed number accounting for the specified token.\"},\"directory()\":{\"notice\":\"The directory of terminals and controllers for projects.\"},\"distributePayoutsOf(uint256,uint256,uint256,address,uint256,string)\":{\"notice\":\"Distributes payouts for a project with the distribution limit of its current funding cycle.\"},\"fee()\":{\"notice\":\"The platform fee percent.\"},\"feeGauge()\":{\"notice\":\"The data source that returns a discount to apply to a project's fee.\"},\"heldFeesOf(uint256)\":{\"notice\":\"The fees that are currently being held to be processed later for each project.\"},\"isFeelessAddress(address)\":{\"notice\":\"Addresses that can be paid towards from this terminal without incurring a fee.\"},\"migrate(uint256,address)\":{\"notice\":\"Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\"},\"operatorStore()\":{\"notice\":\" A contract storing operator assignments.\"},\"pay(uint256,uint256,address,address,uint256,bool,string,bytes)\":{\"notice\":\"Contribute tokens to a project.\"},\"payoutSplitsGroup()\":{\"notice\":\"The group that payout splits coming from this terminal are identified by.\"},\"prices()\":{\"notice\":\"The contract that exposes price feeds.\"},\"processFees(uint256)\":{\"notice\":\"Process any fees that are being held for the project.\"},\"projects()\":{\"notice\":\"Mints ERC-721's that represent project ownership and transfers.\"},\"redeemTokensOf(address,uint256,uint256,address,uint256,address,string,bytes)\":{\"notice\":\"Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\"},\"setFee(uint256)\":{\"notice\":\"Allows the fee to be updated.\"},\"setFeeGauge(address)\":{\"notice\":\"Allows the fee gauge to be updated.\"},\"setFeelessAddress(address,bool)\":{\"notice\":\"Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\"},\"splitsStore()\":{\"notice\":\"The contract that stores splits for each project.\"},\"store()\":{\"notice\":\"The contract that stores and manages the terminal's data.\"},\"supportsInterface(bytes4)\":{\"notice\":\"Indicates if this contract adheres to the specified interface.\"},\"token()\":{\"notice\":\"The token that this terminal accepts.\"},\"useAllowanceOf(uint256,uint256,uint256,address,uint256,address,string)\":{\"notice\":\"Allows a project to send funds from its overflow up to the preconfigured allowance.\"}},\"notice\":\"Manages all inflows and outflows of ETH funds into the protocol ecosystem.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/JBETHPaymentTerminal.sol\":\"JBETHPaymentTerminal\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0x24e0364e503a9bbde94c715d26573a76f14cd2a202d45f96f52134ab806b67b9\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool _approved) external;\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x516a22876c1fab47f49b1bc22b4614491cd05338af8bd2e7b382da090a079990\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3777e696b62134e6177440dbe6e6601c0c156a443f57167194b67e75527439de\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"@paulrberg/contracts/math/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\nimport \\\"prb-math/contracts/PRBMath.sol\\\";\\n\",\"keccak256\":\"0x42821345981bc0434a90ba2268a2f5278dfe9e38166981d72fc7f3b776a29495\",\"license\":\"Unlicense\"},\"contracts/JBETHPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport '@openzeppelin/contracts/utils/Address.sol';\\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\\nimport './libraries/JBSplitsGroups.sol';\\n\\n/**\\n @notice\\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\\n\\n @dev\\n Inherits from -\\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\\n*/\\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\\n //*********************************************************************//\\n // -------------------------- internal views ------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Checks the balance of tokens in this contract.\\n\\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\\n */\\n function _balance() internal view override returns (uint256) {\\n return address(this).balance;\\n }\\n\\n //*********************************************************************//\\n // -------------------------- constructor ---------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @param _baseWeightCurrency The currency to base token issuance on.\\n @param _operatorStore A contract storing operator assignments.\\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\\n @param _directory A contract storing directories of terminals and controllers for each project.\\n @param _splitsStore A contract that stores splits for each project.\\n @param _prices A contract that exposes price feeds.\\n @param _store A contract that stores the terminal's data.\\n @param _owner The address that will own this contract.\\n */\\n constructor(\\n uint256 _baseWeightCurrency,\\n IJBOperatorStore _operatorStore,\\n IJBProjects _projects,\\n IJBDirectory _directory,\\n IJBSplitsStore _splitsStore,\\n IJBPrices _prices,\\n IJBSingleTokenPaymentTerminalStore _store,\\n address _owner\\n )\\n JBPayoutRedemptionPaymentTerminal(\\n JBTokens.ETH,\\n 18, // 18 decimals.\\n JBCurrencies.ETH,\\n _baseWeightCurrency,\\n JBSplitsGroups.ETH_PAYOUT,\\n _operatorStore,\\n _projects,\\n _directory,\\n _splitsStore,\\n _prices,\\n _store,\\n _owner\\n )\\n // solhint-disable-next-line no-empty-blocks\\n {\\n\\n }\\n\\n //*********************************************************************//\\n // ---------------------- internal transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Transfers tokens.\\n\\n @param _from The address from which the transfer should originate.\\n @param _to The address to which the transfer should go.\\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\\n */\\n function _transferFrom(\\n address _from,\\n address payable _to,\\n uint256 _amount\\n ) internal override {\\n _from; // Prevents unused var compiler and natspec complaints.\\n\\n Address.sendValue(_to, _amount);\\n }\\n}\\n\",\"keccak256\":\"0x6afb443f7efddb2ecd7023237f6e1684c4281a1fad43e4e1b34fa0d50b407384\",\"license\":\"MIT\"},\"contracts/abstract/JBOperatable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport './../interfaces/IJBOperatable.sol';\\n\\n/** \\n @notice\\n Modifiers to allow access to functions based on the message sender's operator status.\\n\\n @dev\\n Adheres to -\\n IJBOperatable: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n*/\\nabstract contract JBOperatable is IJBOperatable {\\n //*********************************************************************//\\n // --------------------------- custom errors -------------------------- //\\n //*********************************************************************//\\n error UNAUTHORIZED();\\n\\n //*********************************************************************//\\n // ---------------------------- modifiers ---------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Only allows the speficied account or an operator of the account to proceed. \\n\\n @param _account The account to check for.\\n @param _domain The domain namespace to look for an operator within. \\n @param _permissionIndex The index of the permission to check for. \\n */\\n modifier requirePermission(\\n address _account,\\n uint256 _domain,\\n uint256 _permissionIndex\\n ) {\\n _requirePermission(_account, _domain, _permissionIndex);\\n _;\\n }\\n\\n /** \\n @notice\\n Only allows the speficied account, an operator of the account to proceed, or a truthy override flag. \\n\\n @param _account The account to check for.\\n @param _domain The domain namespace to look for an operator within. \\n @param _permissionIndex The index of the permission to check for. \\n @param _override A condition to force allowance for.\\n */\\n modifier requirePermissionAllowingOverride(\\n address _account,\\n uint256 _domain,\\n uint256 _permissionIndex,\\n bool _override\\n ) {\\n _requirePermissionAllowingOverride(_account, _domain, _permissionIndex, _override);\\n _;\\n }\\n\\n //*********************************************************************//\\n // ---------------- public immutable stored properties --------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n A contract storing operator assignments.\\n */\\n IJBOperatorStore public immutable override operatorStore;\\n\\n //*********************************************************************//\\n // -------------------------- constructor ---------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @param _operatorStore A contract storing operator assignments.\\n */\\n constructor(IJBOperatorStore _operatorStore) {\\n operatorStore = _operatorStore;\\n }\\n\\n //*********************************************************************//\\n // -------------------------- internal views ------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Require the message sender is either the account or has the specified permission.\\n\\n @param _account The account to allow.\\n @param _domain The domain namespace within which the permission index will be checked.\\n @param _permissionIndex The permission index that an operator must have within the specified domain to be allowed.\\n */\\n function _requirePermission(\\n address _account,\\n uint256 _domain,\\n uint256 _permissionIndex\\n ) internal view {\\n if (\\n msg.sender != _account &&\\n !operatorStore.hasPermission(msg.sender, _account, _domain, _permissionIndex) &&\\n !operatorStore.hasPermission(msg.sender, _account, 0, _permissionIndex)\\n ) revert UNAUTHORIZED();\\n }\\n\\n /** \\n @notice\\n Require the message sender is either the account, has the specified permission, or the override condition is true.\\n\\n @param _account The account to allow.\\n @param _domain The domain namespace within which the permission index will be checked.\\n @param _domain The permission index that an operator must have within the specified domain to be allowed.\\n @param _override The override condition to allow.\\n */\\n function _requirePermissionAllowingOverride(\\n address _account,\\n uint256 _domain,\\n uint256 _permissionIndex,\\n bool _override\\n ) internal view {\\n if (\\n !_override &&\\n msg.sender != _account &&\\n !operatorStore.hasPermission(msg.sender, _account, _domain, _permissionIndex) &&\\n !operatorStore.hasPermission(msg.sender, _account, 0, _permissionIndex)\\n ) revert UNAUTHORIZED();\\n }\\n}\\n\",\"keccak256\":\"0x9e62cac5c464eb973f881cf6c373b95aab31d2ddbeb048ee7ad82b5c9ab28add\",\"license\":\"MIT\"},\"contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport '@openzeppelin/contracts/access/Ownable.sol';\\nimport '@paulrberg/contracts/math/PRBMath.sol';\\nimport './../interfaces/IJBController.sol';\\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal.sol';\\nimport './../libraries/JBConstants.sol';\\nimport './../libraries/JBCurrencies.sol';\\nimport './../libraries/JBFixedPointNumber.sol';\\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\\nimport './../libraries/JBOperations.sol';\\nimport './../libraries/JBTokens.sol';\\nimport './../structs/JBPayDelegateAllocation.sol';\\nimport './../structs/JBTokenAmount.sol';\\nimport './JBOperatable.sol';\\nimport './JBSingleTokenPaymentTerminal.sol';\\n\\n/**\\n @notice\\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\\n\\n @dev\\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\\n\\n @dev\\n Adheres to -\\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n\\n @dev\\n Inherits from -\\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\\n*/\\nabstract contract JBPayoutRedemptionPaymentTerminal is\\n JBSingleTokenPaymentTerminal,\\n JBOperatable,\\n Ownable,\\n IJBPayoutRedemptionPaymentTerminal\\n{\\n // A library that parses the packed funding cycle metadata into a friendlier format.\\n using JBFundingCycleMetadataResolver for JBFundingCycle;\\n\\n //*********************************************************************//\\n // --------------------------- custom errors ------------------------- //\\n //*********************************************************************//\\n error FEE_TOO_HIGH();\\n error INADEQUATE_DISTRIBUTION_AMOUNT();\\n error INADEQUATE_RECLAIM_AMOUNT();\\n error INADEQUATE_TOKEN_COUNT();\\n error NO_MSG_VALUE_ALLOWED();\\n error PAY_TO_ZERO_ADDRESS();\\n error PROJECT_TERMINAL_MISMATCH();\\n error REDEEM_TO_ZERO_ADDRESS();\\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\\n error TERMINAL_TOKENS_INCOMPATIBLE();\\n\\n //*********************************************************************//\\n // ---------------------------- modifiers ---------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n A modifier that verifies this terminal is a terminal of provided project ID.\\n */\\n modifier isTerminalOf(uint256 _projectId) {\\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\\n _;\\n }\\n\\n //*********************************************************************//\\n // --------------------- internal stored constants ------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Maximum fee that can be set for a funding cycle configuration.\\n\\n @dev\\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\\n */\\n uint256 internal constant _FEE_CAP = 50_000_000;\\n\\n /**\\n @notice\\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\\n */\\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\\n\\n //*********************************************************************//\\n // --------------------- internal stored properties ------------------ //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Fees that are being held to be processed later.\\n\\n _projectId The ID of the project for which fees are being held.\\n */\\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\\n\\n //*********************************************************************//\\n // ---------------- public immutable stored properties --------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Mints ERC-721's that represent project ownership and transfers.\\n */\\n IJBProjects public immutable override projects;\\n\\n /**\\n @notice\\n The directory of terminals and controllers for projects.\\n */\\n IJBDirectory public immutable override directory;\\n\\n /**\\n @notice\\n The contract that stores splits for each project.\\n */\\n IJBSplitsStore public immutable override splitsStore;\\n\\n /**\\n @notice\\n The contract that exposes price feeds.\\n */\\n IJBPrices public immutable override prices;\\n\\n /**\\n @notice\\n The contract that stores and manages the terminal's data.\\n */\\n IJBSingleTokenPaymentTerminalStore public immutable override store;\\n\\n /**\\n @notice\\n The currency to base token issuance on.\\n\\n @dev\\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\\n */\\n uint256 public immutable override baseWeightCurrency;\\n\\n /**\\n @notice\\n The group that payout splits coming from this terminal are identified by.\\n */\\n uint256 public immutable override payoutSplitsGroup;\\n\\n //*********************************************************************//\\n // --------------------- public stored properties -------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The platform fee percent.\\n\\n @dev\\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\\n */\\n uint256 public override fee = 25_000_000; // 2.5%\\n\\n /**\\n @notice\\n The data source that returns a discount to apply to a project's fee.\\n */\\n IJBFeeGauge public override feeGauge;\\n\\n /**\\n @notice\\n Addresses that can be paid towards from this terminal without incurring a fee.\\n\\n @dev\\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\\n\\n _address The address that can be paid toward.\\n */\\n mapping(address => bool) public override isFeelessAddress;\\n\\n //*********************************************************************//\\n // ------------------------- external views -------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\\n\\n @dev\\n The current overflow is represented as a fixed point number with 18 decimals.\\n\\n @param _projectId The ID of the project to get overflow for.\\n\\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\\n */\\n function currentEthOverflowOf(uint256 _projectId)\\n external\\n view\\n virtual\\n override\\n returns (uint256)\\n {\\n // Get this terminal's current overflow.\\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\\n\\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\\n uint256 _adjustedOverflow = (decimals == 18)\\n ? _overflow\\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\\n\\n // Return the amount converted to ETH.\\n return\\n (currency == JBCurrencies.ETH)\\n ? _adjustedOverflow\\n : PRBMath.mulDiv(\\n _adjustedOverflow,\\n 10**decimals,\\n prices.priceFor(currency, JBCurrencies.ETH, decimals)\\n );\\n }\\n\\n /**\\n @notice\\n The fees that are currently being held to be processed later for each project.\\n\\n @param _projectId The ID of the project for which fees are being held.\\n\\n @return An array of fees that are being held.\\n */\\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\\n return _heldFeesOf[_projectId];\\n }\\n\\n //*********************************************************************//\\n // -------------------------- public views --------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Indicates if this contract adheres to the specified interface.\\n\\n @dev \\n See {IERC165-supportsInterface}.\\n\\n @param _interfaceId The ID of the interface to check for adherance to.\\n */\\n function supportsInterface(bytes4 _interfaceId)\\n public\\n view\\n virtual\\n override(JBSingleTokenPaymentTerminal, IERC165)\\n returns (bool)\\n {\\n return\\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\\n _interfaceId == type(IJBOperatable).interfaceId ||\\n super.supportsInterface(_interfaceId);\\n }\\n\\n //*********************************************************************//\\n // -------------------------- internal views ------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Checks the balance of tokens in this contract.\\n\\n @return The contract's balance.\\n */\\n function _balance() internal view virtual returns (uint256);\\n\\n //*********************************************************************//\\n // -------------------------- constructor ---------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @param _token The token that this terminal manages.\\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\\n @param _currency The currency that this terminal's token adheres to for price feeds.\\n @param _baseWeightCurrency The currency to base token issuance on.\\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\\n @param _operatorStore A contract storing operator assignments.\\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\\n @param _directory A contract storing directories of terminals and controllers for each project.\\n @param _splitsStore A contract that stores splits for each project.\\n @param _prices A contract that exposes price feeds.\\n @param _store A contract that stores the terminal's data.\\n @param _owner The address that will own this contract.\\n */\\n constructor(\\n // payable constructor save the gas used to check msg.value==0\\n address _token,\\n uint256 _decimals,\\n uint256 _currency,\\n uint256 _baseWeightCurrency,\\n uint256 _payoutSplitsGroup,\\n IJBOperatorStore _operatorStore,\\n IJBProjects _projects,\\n IJBDirectory _directory,\\n IJBSplitsStore _splitsStore,\\n IJBPrices _prices,\\n IJBSingleTokenPaymentTerminalStore _store,\\n address _owner\\n )\\n payable\\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\\n JBOperatable(_operatorStore)\\n {\\n baseWeightCurrency = _baseWeightCurrency;\\n payoutSplitsGroup = _payoutSplitsGroup;\\n projects = _projects;\\n directory = _directory;\\n splitsStore = _splitsStore;\\n prices = _prices;\\n store = _store;\\n\\n transferOwnership(_owner);\\n }\\n\\n //*********************************************************************//\\n // ---------------------- external transactions ---------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Contribute tokens to a project.\\n\\n @param _projectId The ID of the project being paid.\\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\\n\\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\\n */\\n function pay(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n // ETH shouldn't be sent if this terminal's token isn't ETH.\\n if (token != JBTokens.ETH) {\\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\\n\\n // Get a reference to the balance before receiving tokens.\\n uint256 _balanceBefore = _balance();\\n\\n // Transfer tokens to this terminal from the msg sender.\\n _transferFrom(msg.sender, payable(address(this)), _amount);\\n\\n // The amount should reflect the change in balance.\\n _amount = _balance() - _balanceBefore;\\n }\\n // If this terminal's token is ETH, override _amount with msg.value.\\n else _amount = msg.value;\\n\\n return\\n _pay(\\n _amount,\\n msg.sender,\\n _projectId,\\n _beneficiary,\\n _minReturnedTokens,\\n _preferClaimedTokens,\\n _memo,\\n _metadata\\n );\\n }\\n\\n /**\\n @notice\\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\\n\\n @dev\\n Only a token holder or a designated operator can redeem its tokens.\\n\\n @param _holder The account to redeem tokens for.\\n @param _projectId The ID of the project to which the tokens being redeemed belong.\\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\\n @param _beneficiary The address to send the terminal tokens to.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\\n\\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\\n */\\n function redeemTokensOf(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n address _token,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string memory _memo,\\n bytes memory _metadata\\n )\\n external\\n virtual\\n override\\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\\n returns (uint256 reclaimAmount)\\n {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n return\\n _redeemTokensOf(\\n _holder,\\n _projectId,\\n _tokenCount,\\n _minReturnedTokens,\\n _beneficiary,\\n _memo,\\n _metadata\\n );\\n }\\n\\n /**\\n @notice\\n Distributes payouts for a project with the distribution limit of its current funding cycle.\\n\\n @dev\\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\\n\\n @dev\\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\\n\\n @dev\\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\\n\\n @param _projectId The ID of the project having its payouts distributed.\\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\\n @param _memo A memo to pass along to the emitted event.\\n\\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\\n */\\n function distributePayoutsOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n address _token,\\n uint256 _minReturnedTokens,\\n string calldata _memo\\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\\n }\\n\\n /**\\n @notice\\n Allows a project to send funds from its overflow up to the preconfigured allowance.\\n\\n @dev\\n Only a project's owner or a designated operator can use its allowance.\\n\\n @dev\\n Incurs the protocol fee.\\n\\n @param _projectId The ID of the project to use the allowance of.\\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\\n @param _beneficiary The address to send the funds to.\\n @param _memo A memo to pass along to the emitted event.\\n\\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\\n */\\n function useAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n address _token,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string memory _memo\\n )\\n external\\n virtual\\n override\\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\\n returns (uint256 netDistributedAmount)\\n {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\\n }\\n\\n /**\\n @notice\\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\\n\\n @dev\\n Only a project's owner or a designated operator can migrate it.\\n\\n @param _projectId The ID of the project being migrated.\\n @param _to The terminal contract that will gain the project's funds.\\n\\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\\n */\\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\\n external\\n virtual\\n override\\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\\n returns (uint256 balance)\\n {\\n // The terminal being migrated to must accept the same token as this terminal.\\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\\n\\n // Record the migration in the store.\\n balance = store.recordMigration(_projectId);\\n\\n // Transfer the balance if needed.\\n if (balance > 0) {\\n // Trigger any inherited pre-transfer logic.\\n _beforeTransferTo(address(_to), balance);\\n\\n // If this terminal's token is ETH, send it in msg.value.\\n uint256 _payableValue = token == JBTokens.ETH ? balance : 0;\\n\\n // Withdraw the balance to transfer to the new terminal;\\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\\n }\\n\\n emit Migrate(_projectId, _to, balance, msg.sender);\\n }\\n\\n /**\\n @notice\\n Receives funds belonging to the specified project.\\n\\n @param _projectId The ID of the project to which the funds received belong.\\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Extra data to pass along to the emitted event.\\n */\\n function addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable virtual override isTerminalOf(_projectId) {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\\n if (token != JBTokens.ETH) {\\n // Amount must be greater than 0.\\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\\n\\n // Get a reference to the balance before receiving tokens.\\n uint256 _balanceBefore = _balance();\\n\\n // Transfer tokens to this terminal from the msg sender.\\n _transferFrom(msg.sender, payable(address(this)), _amount);\\n\\n // The amount should reflect the change in balance.\\n _amount = _balance() - _balanceBefore;\\n }\\n // If the terminal's token is ETH, override `_amount` with msg.value.\\n else _amount = msg.value;\\n\\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\\n }\\n\\n /**\\n @notice\\n Process any fees that are being held for the project.\\n\\n @dev\\n Only a project owner, an operator, or the contract's owner can process held fees.\\n\\n @param _projectId The ID of the project whos held fees should be processed.\\n */\\n function processFees(uint256 _projectId)\\n external\\n virtual\\n override\\n requirePermissionAllowingOverride(\\n projects.ownerOf(_projectId),\\n _projectId,\\n JBOperations.PROCESS_FEES,\\n msg.sender == owner()\\n )\\n {\\n // Get a reference to the project's held fees.\\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\\n\\n // Delete the held fees.\\n delete _heldFeesOf[_projectId];\\n\\n // Push array length in stack\\n uint256 _heldFeeLength = _heldFees.length;\\n\\n // Process each fee.\\n for (uint256 _i; _i < _heldFeeLength; ) {\\n // Get the fee amount.\\n uint256 _amount = _feeAmount(\\n _heldFees[_i].amount,\\n _heldFees[_i].fee,\\n _heldFees[_i].feeDiscount\\n );\\n\\n // Process the fee.\\n _processFee(_amount, _heldFees[_i].beneficiary);\\n\\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n\\n /**\\n @notice\\n Allows the fee to be updated.\\n\\n @dev\\n Only the owner of this contract can change the fee.\\n\\n @param _fee The new fee, out of MAX_FEE.\\n */\\n function setFee(uint256 _fee) external virtual override onlyOwner {\\n // The provided fee must be within the max.\\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\\n\\n // Store the new fee.\\n fee = _fee;\\n\\n emit SetFee(_fee, msg.sender);\\n }\\n\\n /**\\n @notice\\n Allows the fee gauge to be updated.\\n\\n @dev\\n Only the owner of this contract can change the fee gauge.\\n\\n @param _feeGauge The new fee gauge.\\n */\\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\\n // Store the new fee gauge.\\n feeGauge = _feeGauge;\\n\\n emit SetFeeGauge(_feeGauge, msg.sender);\\n }\\n\\n /**\\n @notice\\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\\n\\n @dev\\n Only the owner of this contract can set addresses as feeless.\\n\\n @param _address The address that can be paid towards while still bypassing fees.\\n @param _flag A flag indicating whether the terminal should be feeless or not.\\n */\\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\\n // Set the flag value.\\n isFeelessAddress[_address] = _flag;\\n\\n emit SetFeelessAddress(_address, _flag, msg.sender);\\n }\\n\\n //*********************************************************************//\\n // ---------------------- internal transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Transfers tokens.\\n\\n @param _from The address from which the transfer should originate.\\n @param _to The address to which the transfer should go.\\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\\n */\\n function _transferFrom(\\n address _from,\\n address payable _to,\\n uint256 _amount\\n ) internal virtual {\\n _from; // Prevents unused var compiler and natspec complaints.\\n _to; // Prevents unused var compiler and natspec complaints.\\n _amount; // Prevents unused var compiler and natspec complaints.\\n }\\n\\n /** \\n @notice\\n Logic to be triggered before transferring tokens from this terminal.\\n\\n @param _to The address to which the transfer is going.\\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\\n */\\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\\n _to; // Prevents unused var compiler and natspec complaints.\\n _amount; // Prevents unused var compiler and natspec complaints.\\n }\\n\\n /**\\n @notice\\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\\n\\n @dev\\n Only a token holder or a designated operator can redeem its tokens.\\n\\n @param _holder The account to redeem tokens for.\\n @param _projectId The ID of the project to which the tokens being redeemed belong.\\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\\n @param _beneficiary The address to send the terminal tokens to.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\\n\\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\\n */\\n function _redeemTokensOf(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string memory _memo,\\n bytes memory _metadata\\n ) internal returns (uint256 reclaimAmount) {\\n // Can't send reclaimed funds to the zero address.\\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\\n\\n // Define variables that will be needed outside the scoped section below.\\n // Keep a reference to the funding cycle during which the redemption is being made.\\n JBFundingCycle memory _fundingCycle;\\n\\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\\n {\\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\\n\\n // Record the redemption.\\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\\n _holder,\\n _projectId,\\n _tokenCount,\\n _memo,\\n _metadata\\n );\\n\\n // The amount being reclaimed must be at least as much as was expected.\\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\\n\\n // Burn the project tokens.\\n if (_tokenCount > 0)\\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\\n _holder,\\n _projectId,\\n _tokenCount,\\n '',\\n false\\n );\\n\\n // If delegate allocations were specified by the data source, fulfill them.\\n if (_delegateAllocations.length != 0) {\\n // Keep a reference to the token amount being forwarded to the delegate.\\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\\n\\n JBDidRedeemData memory _data = JBDidRedeemData(\\n _holder,\\n _projectId,\\n _fundingCycle.configuration,\\n _tokenCount,\\n JBTokenAmount(token, reclaimAmount, decimals, currency),\\n _forwardedAmount,\\n _beneficiary,\\n _memo,\\n _metadata\\n );\\n\\n uint256 _numDelegates = _delegateAllocations.length;\\n\\n for (uint256 _i; _i < _numDelegates; ) {\\n // Get a reference to the delegate being iterated on.\\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\\n\\n // Trigger any inherited pre-transfer logic.\\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\\n\\n // Keep track of the msg.value to use in the delegate call\\n uint256 _payableValue;\\n\\n // If this terminal's token is ETH, send it in msg.value.\\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\\n\\n // Pass the correct token forwardedAmount to the delegate\\n _data.forwardedAmount.value = _delegateAllocation.amount;\\n\\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\\n\\n emit DelegateDidRedeem(\\n _delegateAllocation.delegate,\\n _data,\\n _delegateAllocation.amount,\\n msg.sender\\n );\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n }\\n\\n // Send the reclaimed funds to the beneficiary.\\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\\n\\n emit RedeemTokens(\\n _fundingCycle.configuration,\\n _fundingCycle.number,\\n _projectId,\\n _holder,\\n _beneficiary,\\n _tokenCount,\\n reclaimAmount,\\n _memo,\\n _metadata,\\n msg.sender\\n );\\n }\\n\\n /**\\n @notice\\n Distributes payouts for a project with the distribution limit of its current funding cycle.\\n\\n @dev\\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\\n\\n @dev\\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\\n\\n @dev\\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\\n\\n @param _projectId The ID of the project having its payouts distributed.\\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\\n @param _memo A memo to pass along to the emitted event.\\n\\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\\n */\\n function _distributePayoutsOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n uint256 _minReturnedTokens,\\n string calldata _memo\\n ) internal returns (uint256 netLeftoverDistributionAmount) {\\n // Record the distribution.\\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\\n _projectId,\\n _amount,\\n _currency\\n );\\n\\n // The amount being distributed must be at least as much as was expected.\\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\\n\\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\\n // and receive any extra distributable funds not allocated to payout splits.\\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\\n\\n // Define variables that will be needed outside the scoped section below.\\n // Keep a reference to the fee amount that was paid.\\n uint256 _fee;\\n\\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\\n {\\n // Get the amount of discount that should be applied to any fees taken.\\n // If the fee is zero, set the discount to 100% for convenience.\\n uint256 _feeDiscount = fee == 0\\n ? JBConstants.MAX_FEE_DISCOUNT\\n : _currentFeeDiscount(_projectId);\\n\\n // The amount distributed that is eligible for incurring fees.\\n uint256 _feeEligibleDistributionAmount;\\n\\n // The amount leftover after distributing to the splits.\\n uint256 _leftoverDistributionAmount;\\n\\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\\n _projectId,\\n _fundingCycle.configuration,\\n payoutSplitsGroup,\\n _distributedAmount,\\n _feeDiscount\\n );\\n\\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\\n unchecked {\\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\\n }\\n }\\n\\n // Take the fee.\\n _fee = _feeEligibleDistributionAmount != 0\\n ? _takeFeeFrom(\\n _projectId,\\n _fundingCycle,\\n _feeEligibleDistributionAmount,\\n _projectOwner,\\n _feeDiscount\\n )\\n : 0;\\n\\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\\n if (_leftoverDistributionAmount != 0) {\\n // Subtract the fee from the net leftover amount.\\n netLeftoverDistributionAmount =\\n _leftoverDistributionAmount -\\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\\n\\n // Transfer the amount to the project owner.\\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\\n }\\n }\\n\\n emit DistributePayouts(\\n _fundingCycle.configuration,\\n _fundingCycle.number,\\n _projectId,\\n _projectOwner,\\n _amount,\\n _distributedAmount,\\n _fee,\\n netLeftoverDistributionAmount,\\n _memo,\\n msg.sender\\n );\\n }\\n\\n /**\\n @notice\\n Allows a project to send funds from its overflow up to the preconfigured allowance.\\n\\n @dev\\n Only a project's owner or a designated operator can use its allowance.\\n\\n @dev\\n Incurs the protocol fee.\\n\\n @param _projectId The ID of the project to use the allowance of.\\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\\n @param _beneficiary The address to send the funds to.\\n @param _memo A memo to pass along to the emitted event.\\n\\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\\n */\\n function _useAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string memory _memo\\n ) internal returns (uint256 netDistributedAmount) {\\n // Record the use of the allowance.\\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\\n _projectId,\\n _amount,\\n _currency\\n );\\n\\n // The amount being withdrawn must be at least as much as was expected.\\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\\n\\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\\n {\\n // Keep a reference to the fee amount that was paid.\\n uint256 _fee;\\n\\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\\n address _projectOwner = projects.ownerOf(_projectId);\\n\\n // Get the amount of discount that should be applied to any fees taken.\\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\\n ? JBConstants.MAX_FEE_DISCOUNT\\n : _currentFeeDiscount(_projectId);\\n\\n // Take a fee from the `_distributedAmount`, if needed.\\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\\n ? 0\\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\\n\\n unchecked {\\n // The net amount is the withdrawn amount without the fee.\\n netDistributedAmount = _distributedAmount - _fee;\\n }\\n\\n // Transfer any remaining balance to the beneficiary.\\n if (netDistributedAmount > 0)\\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\\n }\\n\\n emit UseAllowance(\\n _fundingCycle.configuration,\\n _fundingCycle.number,\\n _projectId,\\n _beneficiary,\\n _amount,\\n _distributedAmount,\\n netDistributedAmount,\\n _memo,\\n msg.sender\\n );\\n }\\n\\n /**\\n @notice\\n Pays out splits for a project's funding cycle configuration.\\n\\n @param _projectId The ID of the project for which payout splits are being distributed.\\n @param _domain The domain of the splits to distribute the payout between.\\n @param _group The group of the splits to distribute the payout between.\\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\\n\\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\\n */\\n function _distributeToPayoutSplitsOf(\\n uint256 _projectId,\\n uint256 _domain,\\n uint256 _group,\\n uint256 _amount,\\n uint256 _feeDiscount\\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\\n // Set the leftover amount to the initial amount.\\n leftoverAmount = _amount;\\n // The total percentage available to split\\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\\n\\n // Get a reference to the project's payout splits.\\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\\n\\n // Transfer between all splits.\\n for (uint256 _i; _i < _splits.length; ) {\\n // Get a reference to the split being iterated on.\\n JBSplit memory _split = _splits[_i];\\n\\n // The amount to send towards the split.\\n uint256 _payoutAmount = _split.percent == leftoverPercentage\\n ? leftoverAmount\\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\\n\\n // Decrement the leftover percentage.\\n leftoverPercentage -= _split.percent;\\n\\n // The payout amount substracting any applicable incurred fees.\\n uint256 _netPayoutAmount;\\n\\n if (_payoutAmount > 0) {\\n // Transfer tokens to the split.\\n // If there's an allocator set, transfer to its `allocate` function.\\n if (_split.allocator != IJBSplitAllocator(address(0))) {\\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\\n if (\\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\\n isFeelessAddress[address(_split.allocator)]\\n )\\n _netPayoutAmount = _payoutAmount;\\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\\n else {\\n unchecked {\\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\\n }\\n\\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\\n feeEligibleDistributionAmount += _payoutAmount;\\n }\\n\\n // Trigger any inherited pre-transfer logic.\\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\\n\\n // Create the data to send to the allocator.\\n JBSplitAllocationData memory _data = JBSplitAllocationData(\\n token,\\n _netPayoutAmount,\\n decimals,\\n _projectId,\\n _group,\\n _split\\n );\\n\\n // Trigger the allocator's `allocate` function.\\n // If this terminal's token is ETH, send it in msg.value.\\n _split.allocator.allocate{value: token == JBTokens.ETH ? _netPayoutAmount : 0}(_data);\\n\\n // Otherwise, if a project is specified, make a payment to it.\\n } else if (_split.projectId != 0) {\\n // Get a reference to the Juicebox terminal being used.\\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\\n\\n // The project must have a terminal to send funds to.\\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\\n\\n // Save gas if this contract is being used as the terminal.\\n if (_terminal == this) {\\n // This distribution does not incur a fee.\\n _netPayoutAmount = _payoutAmount;\\n\\n // Send the projectId in the metadata.\\n bytes memory _projectMetadata = new bytes(32);\\n _projectMetadata = bytes(abi.encodePacked(_projectId));\\n\\n // Add to balance if prefered.\\n if (_split.preferAddToBalance)\\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\\n else\\n _pay(\\n _netPayoutAmount,\\n address(this),\\n _split.projectId,\\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\\n 0,\\n _split.preferClaimed,\\n '',\\n _projectMetadata\\n );\\n } else {\\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\\n if (\\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_terminal)]\\n )\\n _netPayoutAmount = _payoutAmount;\\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\\n else {\\n unchecked {\\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\\n }\\n\\n feeEligibleDistributionAmount += _payoutAmount;\\n }\\n\\n // Trigger any inherited pre-transfer logic.\\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\\n\\n // If this terminal's token is ETH, send it in msg.value.\\n uint256 _payableValue = token == JBTokens.ETH ? _netPayoutAmount : 0;\\n\\n // Send the projectId in the metadata.\\n bytes memory _projectMetadata = new bytes(32);\\n _projectMetadata = bytes(abi.encodePacked(_projectId));\\n\\n // Add to balance if prefered.\\n if (_split.preferAddToBalance)\\n _terminal.addToBalanceOf{value: _payableValue}(\\n _split.projectId,\\n _netPayoutAmount,\\n token,\\n '',\\n _projectMetadata\\n );\\n else\\n _terminal.pay{value: _payableValue}(\\n _split.projectId,\\n _netPayoutAmount,\\n token,\\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\\n 0,\\n _split.preferClaimed,\\n '',\\n _projectMetadata\\n );\\n }\\n } else {\\n // Keep a reference to the beneficiary.\\n address payable _beneficiary = _split.beneficiary != address(0)\\n ? _split.beneficiary\\n : payable(msg.sender);\\n\\n // If there's a full discount, this distribution is not eligible for a fee.\\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\\n _netPayoutAmount = _payoutAmount;\\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\\n else {\\n unchecked {\\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\\n }\\n\\n feeEligibleDistributionAmount += _payoutAmount;\\n }\\n\\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\\n _transferFrom(address(this), _beneficiary, _netPayoutAmount);\\n }\\n\\n // Subtract from the amount to be sent to the beneficiary.\\n unchecked {\\n leftoverAmount = leftoverAmount - _payoutAmount;\\n }\\n }\\n\\n emit DistributeToPayoutSplit(\\n _projectId,\\n _domain,\\n _group,\\n _split,\\n _netPayoutAmount,\\n msg.sender\\n );\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n\\n /**\\n @notice\\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\\n\\n @param _projectId The ID of the project having fees taken from.\\n @param _fundingCycle The funding cycle during which the fee is being taken.\\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\\n @param _beneficiary The address to mint the platforms tokens for.\\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\\n\\n @return feeAmount The amount of the fee taken.\\n */\\n function _takeFeeFrom(\\n uint256 _projectId,\\n JBFundingCycle memory _fundingCycle,\\n uint256 _amount,\\n address _beneficiary,\\n uint256 _feeDiscount\\n ) internal returns (uint256 feeAmount) {\\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\\n\\n if (_fundingCycle.shouldHoldFees()) {\\n // Store the held fee.\\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\\n\\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\\n } else {\\n // Process the fee.\\n _processFee(feeAmount, _beneficiary); // Take the fee.\\n\\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\\n }\\n }\\n\\n /**\\n @notice\\n Process a fee of the specified amount.\\n\\n @param _amount The fee amount, as a floating point number with 18 decimals.\\n @param _beneficiary The address to mint the platform's tokens for.\\n */\\n function _processFee(uint256 _amount, address _beneficiary) internal {\\n // Get the terminal for the protocol project.\\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\\n\\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\\n if (_terminal == this)\\n _pay(\\n _amount,\\n address(this),\\n _FEE_BENEFICIARY_PROJECT_ID,\\n _beneficiary,\\n 0,\\n false,\\n '',\\n bytes('')\\n ); // Use the local pay call.\\n else {\\n // Trigger any inherited pre-transfer logic.\\n _beforeTransferTo(address(_terminal), _amount);\\n\\n // If this terminal's token is ETH, send it in msg.value.\\n uint256 _payableValue = token == JBTokens.ETH ? _amount : 0;\\n\\n // Send the payment.\\n _terminal.pay{value: _payableValue}(\\n _FEE_BENEFICIARY_PROJECT_ID,\\n _amount,\\n token,\\n _beneficiary,\\n 0,\\n false,\\n '',\\n bytes('')\\n ); // Use the external pay call of the correct terminal.\\n }\\n }\\n\\n /**\\n @notice\\n Contribute tokens to a project.\\n\\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\\n @param _payer The address making the payment.\\n @param _projectId The ID of the project being paid.\\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\\n\\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\\n */\\n function _pay(\\n uint256 _amount,\\n address _payer,\\n uint256 _projectId,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string memory _memo,\\n bytes memory _metadata\\n ) internal returns (uint256 beneficiaryTokenCount) {\\n // Cant send tokens to the zero address.\\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\\n\\n // Define variables that will be needed outside the scoped section below.\\n // Keep a reference to the funding cycle during which the payment is being made.\\n JBFundingCycle memory _fundingCycle;\\n\\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\\n {\\n JBPayDelegateAllocation[] memory _delegateAllocations;\\n uint256 _tokenCount;\\n\\n // Bundle the amount info into a JBTokenAmount struct.\\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\\n\\n // Record the payment.\\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\\n _payer,\\n _bundledAmount,\\n _projectId,\\n baseWeightCurrency,\\n _beneficiary,\\n _memo,\\n _metadata\\n );\\n\\n // Mint the tokens if needed.\\n if (_tokenCount > 0)\\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\\n _projectId,\\n _tokenCount,\\n _beneficiary,\\n '',\\n _preferClaimedTokens,\\n true\\n );\\n\\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\\n\\n // If delegate allocations were specified by the data source, fulfill them.\\n if (_delegateAllocations.length != 0) {\\n // Keep a reference to the token amount being forwarded to the delegate.\\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\\n\\n JBDidPayData memory _data = JBDidPayData(\\n _payer,\\n _projectId,\\n _fundingCycle.configuration,\\n _bundledAmount,\\n _forwardedAmount,\\n beneficiaryTokenCount,\\n _beneficiary,\\n _preferClaimedTokens,\\n _memo,\\n _metadata\\n );\\n\\n // Get a reference to the number of delegates to allocate to.\\n uint256 _numDelegates = _delegateAllocations.length;\\n\\n for (uint256 _i; _i < _numDelegates; ) {\\n // Get a reference to the delegate being iterated on.\\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\\n\\n // Trigger any inherited pre-transfer logic.\\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\\n\\n // Keep track of the msg.value to use in the delegate call\\n uint256 _payableValue;\\n\\n // If this terminal's token is ETH, send it in msg.value.\\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\\n\\n // Pass the correct token forwardedAmount to the delegate\\n _data.forwardedAmount.value = _delegateAllocation.amount;\\n\\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\\n\\n emit DelegateDidPay(\\n _delegateAllocation.delegate,\\n _data,\\n _delegateAllocation.amount,\\n msg.sender\\n );\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n }\\n\\n emit Pay(\\n _fundingCycle.configuration,\\n _fundingCycle.number,\\n _projectId,\\n _payer,\\n _beneficiary,\\n _amount,\\n beneficiaryTokenCount,\\n _memo,\\n _metadata,\\n msg.sender\\n );\\n }\\n\\n /**\\n @notice\\n Receives funds belonging to the specified project.\\n\\n @param _projectId The ID of the project to which the funds received belong.\\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Extra data to pass along to the emitted event.\\n */\\n function _addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n bool _shouldRefundHeldFees,\\n string memory _memo,\\n bytes memory _metadata\\n ) internal {\\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\\n\\n // Record the added funds with any refunded fees.\\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\\n\\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\\n }\\n\\n /**\\n @notice\\n Refund fees based on the specified amount.\\n\\n @param _projectId The project for which fees are being refunded.\\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\\n\\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\\n */\\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\\n internal\\n returns (uint256 refundedFees)\\n {\\n // Get a reference to the project's held fees.\\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\\n\\n // Delete the current held fees.\\n delete _heldFeesOf[_projectId];\\n\\n // Get a reference to the leftover amount once all fees have been settled.\\n uint256 leftoverAmount = _amount;\\n\\n // Push length in stack\\n uint256 _heldFeesLength = _heldFees.length;\\n\\n // Process each fee.\\n for (uint256 _i; _i < _heldFeesLength; ) {\\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\\n else if (leftoverAmount >= _heldFees[_i].amount) {\\n unchecked {\\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\\n refundedFees += _feeAmount(\\n _heldFees[_i].amount,\\n _heldFees[_i].fee,\\n _heldFees[_i].feeDiscount\\n );\\n }\\n } else {\\n unchecked {\\n _heldFeesOf[_projectId].push(\\n JBFee(\\n _heldFees[_i].amount - leftoverAmount,\\n _heldFees[_i].fee,\\n _heldFees[_i].feeDiscount,\\n _heldFees[_i].beneficiary\\n )\\n );\\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\\n }\\n leftoverAmount = 0;\\n }\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n\\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\\n }\\n\\n /** \\n @notice \\n Returns the fee amount based on the provided amount for the specified project.\\n\\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\\n @param _fee The percentage of the fee, out of MAX_FEE. \\n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\\n\\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\\n */\\n function _feeAmount(\\n uint256 _amount,\\n uint256 _fee,\\n uint256 _feeDiscount\\n ) internal pure returns (uint256) {\\n // Calculate the discounted fee.\\n uint256 _discountedFee = _fee -\\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\\n\\n // The amount of tokens from the `_amount` to pay as a fee.\\n return\\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\\n }\\n\\n /** \\n @notice\\n Get the fee discount from the fee gauge for the specified project.\\n\\n @param _projectId The ID of the project to get a fee discount for.\\n \\n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\\n */\\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\\n if (\\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\\n IJBPaymentTerminal(address(0))\\n ) return JBConstants.MAX_FEE_DISCOUNT;\\n\\n // Get the fee discount.\\n if (feeGauge != IJBFeeGauge(address(0)))\\n // If the guage reverts, keep the discount at 0.\\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\\n // If the fee discount is greater than the max, we ignore the return value\\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\\n } catch {\\n return 0;\\n }\\n\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0xbd19927d16eca865a8c894bed895c2704fa17ef361b97f90310b5ff0d43d9036\",\"license\":\"MIT\"},\"contracts/abstract/JBSingleTokenPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\\nimport './../interfaces/IJBSingleTokenPaymentTerminal.sol';\\n\\n/**\\n @notice\\n Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\\n\\n @dev\\n Adheres to -\\n IJBSingleTokenPaymentTerminals: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n\\n @dev\\n Inherits from -\\n ERC165: Introspection on interface adherance. \\n*/\\nabstract contract JBSingleTokenPaymentTerminal is ERC165, IJBSingleTokenPaymentTerminal {\\n //*********************************************************************//\\n // ---------------- public immutable stored properties --------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The token that this terminal accepts.\\n */\\n address public immutable override token;\\n\\n /**\\n @notice\\n The number of decimals the token fixed point amounts are expected to have.\\n */\\n uint256 public immutable override decimals;\\n\\n /**\\n @notice\\n The currency to use when resolving price feeds for this terminal.\\n */\\n uint256 public immutable override currency;\\n\\n //*********************************************************************//\\n // ------------------------- external views -------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n A flag indicating if this terminal accepts the specified token.\\n\\n @param _token The token to check if this terminal accepts or not.\\n @param _projectId The project ID to check for token acceptance.\\n\\n @return The flag.\\n */\\n function acceptsToken(address _token, uint256 _projectId) external view override returns (bool) {\\n _projectId; // Prevents unused var compiler and natspec complaints.\\n\\n return _token == token;\\n }\\n\\n /** \\n @notice\\n The decimals that should be used in fixed number accounting for the specified token.\\n\\n @param _token The token to check for the decimals of.\\n\\n @return The number of decimals for the token.\\n */\\n function decimalsForToken(address _token) external view override returns (uint256) {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n return decimals;\\n }\\n\\n /** \\n @notice\\n The currency that should be used for the specified token.\\n\\n @param _token The token to check for the currency of.\\n\\n @return The currency index.\\n */\\n function currencyForToken(address _token) external view override returns (uint256) {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n return currency;\\n }\\n\\n //*********************************************************************//\\n // -------------------------- public views --------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Indicates if this contract adheres to the specified interface.\\n\\n @dev \\n See {IERC165-supportsInterface}.\\n\\n @param _interfaceId The ID of the interface to check for adherance to.\\n */\\n function supportsInterface(bytes4 _interfaceId)\\n public\\n view\\n virtual\\n override(ERC165, IERC165)\\n returns (bool)\\n {\\n return\\n _interfaceId == type(IJBPaymentTerminal).interfaceId ||\\n _interfaceId == type(IJBSingleTokenPaymentTerminal).interfaceId ||\\n super.supportsInterface(_interfaceId);\\n }\\n\\n //*********************************************************************//\\n // -------------------------- constructor ---------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @param _token The token that this terminal manages.\\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\\n @param _currency The currency that this terminal's token adheres to for price feeds.\\n */\\n constructor(\\n address _token,\\n uint256 _decimals,\\n uint256 _currency\\n ) {\\n token = _token;\\n decimals = _decimals;\\n currency = _currency;\\n }\\n}\\n\",\"keccak256\":\"0xdc82ad3e01b918d3d21ffea8c9f30950d81e225137c851599d028dcd22125f89\",\"license\":\"MIT\"},\"contracts/enums/JBBallotState.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nenum JBBallotState {\\n Active,\\n Approved,\\n Failed\\n}\\n\",\"keccak256\":\"0x891fcac63470398b3a11239da7feba6b07d640809fcefd2404303b823d7378f8\",\"license\":\"MIT\"},\"contracts/interfaces/IJBAllowanceTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBAllowanceTerminal {\\n function useAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n address _token,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string calldata _memo\\n ) external returns (uint256 netDistributedAmount);\\n}\\n\",\"keccak256\":\"0x139d7628da9fc8510f53482d592cd4074d21c0cb6d72510ff2743076f3b17533\",\"license\":\"MIT\"},\"contracts/interfaces/IJBController.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBFundAccessConstraints.sol';\\nimport './../structs/JBFundingCycleData.sol';\\nimport './../structs/JBFundingCycleMetadata.sol';\\nimport './../structs/JBGroupedSplits.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBMigratable.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBSplitsStore.sol';\\nimport './IJBTokenStore.sol';\\n\\ninterface IJBController is IERC165 {\\n event LaunchProject(uint256 configuration, uint256 projectId, string memo, address caller);\\n\\n event LaunchFundingCycles(uint256 configuration, uint256 projectId, string memo, address caller);\\n\\n event ReconfigureFundingCycles(\\n uint256 configuration,\\n uint256 projectId,\\n string memo,\\n address caller\\n );\\n\\n event SetFundAccessConstraints(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n JBFundAccessConstraints constraints,\\n address caller\\n );\\n\\n event DistributeReservedTokens(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address beneficiary,\\n uint256 tokenCount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n address caller\\n );\\n\\n event DistributeToReservedTokenSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n uint256 tokenCount,\\n address caller\\n );\\n\\n event MintTokens(\\n address indexed beneficiary,\\n uint256 indexed projectId,\\n uint256 tokenCount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n uint256 reservedRate,\\n address caller\\n );\\n\\n event BurnTokens(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 tokenCount,\\n string memo,\\n address caller\\n );\\n\\n event Migrate(uint256 indexed projectId, IJBMigratable to, address caller);\\n\\n event PrepMigration(uint256 indexed projectId, address from, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function tokenStore() external view returns (IJBTokenStore);\\n\\n function splitsStore() external view returns (IJBSplitsStore);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function reservedTokenBalanceOf(uint256 _projectId, uint256 _reservedRate)\\n external\\n view\\n returns (uint256);\\n\\n function distributionLimitOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n IJBPaymentTerminal _terminal,\\n address _token\\n ) external view returns (uint256 distributionLimit, uint256 distributionLimitCurrency);\\n\\n function overflowAllowanceOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n IJBPaymentTerminal _terminal,\\n address _token\\n ) external view returns (uint256 overflowAllowance, uint256 overflowAllowanceCurrency);\\n\\n function totalOutstandingTokensOf(uint256 _projectId, uint256 _reservedRate)\\n external\\n view\\n returns (uint256);\\n\\n function getFundingCycleOf(uint256 _projectId, uint256 _configuration)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function latestConfiguredFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (\\n JBFundingCycle memory,\\n JBFundingCycleMetadata memory metadata,\\n JBBallotState\\n );\\n\\n function currentFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function queuedFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function launchProjectFor(\\n address _owner,\\n JBProjectMetadata calldata _projectMetadata,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n IJBPaymentTerminal[] memory _terminals,\\n string calldata _memo\\n ) external returns (uint256 projectId);\\n\\n function launchFundingCyclesFor(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n IJBPaymentTerminal[] memory _terminals,\\n string calldata _memo\\n ) external returns (uint256 configuration);\\n\\n function reconfigureFundingCyclesOf(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n string calldata _memo\\n ) external returns (uint256);\\n\\n function mintTokensOf(\\n uint256 _projectId,\\n uint256 _tokenCount,\\n address _beneficiary,\\n string calldata _memo,\\n bool _preferClaimedTokens,\\n bool _useReservedRate\\n ) external returns (uint256 beneficiaryTokenCount);\\n\\n function burnTokensOf(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n string calldata _memo,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function distributeReservedTokensOf(uint256 _projectId, string memory _memo)\\n external\\n returns (uint256);\\n\\n function migrate(uint256 _projectId, IJBMigratable _to) external;\\n}\\n\",\"keccak256\":\"0xb1ee4b41f2a06f28f69c74cb729b8964f2e75f3c545a68f85bd9082b5575bc85\",\"license\":\"MIT\"},\"contracts/interfaces/IJBDirectory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBProjects.sol';\\n\\ninterface IJBDirectory {\\n event SetController(uint256 indexed projectId, address indexed controller, address caller);\\n\\n event AddTerminal(uint256 indexed projectId, IJBPaymentTerminal indexed terminal, address caller);\\n\\n event SetTerminals(uint256 indexed projectId, IJBPaymentTerminal[] terminals, address caller);\\n\\n event SetPrimaryTerminal(\\n uint256 indexed projectId,\\n address indexed token,\\n IJBPaymentTerminal indexed terminal,\\n address caller\\n );\\n\\n event SetIsAllowedToSetFirstController(address indexed addr, bool indexed flag, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function controllerOf(uint256 _projectId) external view returns (address);\\n\\n function isAllowedToSetFirstController(address _address) external view returns (bool);\\n\\n function terminalsOf(uint256 _projectId) external view returns (IJBPaymentTerminal[] memory);\\n\\n function isTerminalOf(uint256 _projectId, IJBPaymentTerminal _terminal)\\n external\\n view\\n returns (bool);\\n\\n function primaryTerminalOf(uint256 _projectId, address _token)\\n external\\n view\\n returns (IJBPaymentTerminal);\\n\\n function setControllerOf(uint256 _projectId, address _controller) external;\\n\\n function setTerminalsOf(uint256 _projectId, IJBPaymentTerminal[] calldata _terminals) external;\\n\\n function setPrimaryTerminalOf(\\n uint256 _projectId,\\n address _token,\\n IJBPaymentTerminal _terminal\\n ) external;\\n\\n function setIsAllowedToSetFirstController(address _address, bool _flag) external;\\n}\\n\",\"keccak256\":\"0x715321646db00514d1355ed43c40cd3f01e94959552fd07797b315d9c49cdb1d\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFeeGauge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBFeeGauge {\\n function currentDiscountFor(uint256 _projectId) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x8e19959617191320fe1210760860e668a57319258c0c74fcfabac829ae0222c0\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleBallot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../enums/JBBallotState.sol';\\n\\ninterface IJBFundingCycleBallot is IERC165 {\\n function duration() external view returns (uint256);\\n\\n function stateOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n uint256 _start\\n ) external view returns (JBBallotState);\\n}\\n\",\"keccak256\":\"0x49553a56209237846bc400cf27f260824a6bd06fd8094a7eb5abb9de75779598\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../enums/JBBallotState.sol';\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBFundingCycleData.sol';\\n\\ninterface IJBFundingCycleStore {\\n event Configure(\\n uint256 indexed configuration,\\n uint256 indexed projectId,\\n JBFundingCycleData data,\\n uint256 metadata,\\n uint256 mustStartAtOrAfter,\\n address caller\\n );\\n\\n event Init(uint256 indexed configuration, uint256 indexed projectId, uint256 indexed basedOn);\\n\\n function latestConfigurationOf(uint256 _projectId) external view returns (uint256);\\n\\n function get(uint256 _projectId, uint256 _configuration)\\n external\\n view\\n returns (JBFundingCycle memory);\\n\\n function latestConfiguredOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBBallotState ballotState);\\n\\n function queuedOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentBallotStateOf(uint256 _projectId) external view returns (JBBallotState);\\n\\n function configureFor(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n uint256 _metadata,\\n uint256 _mustStartAtOrAfter\\n ) external returns (JBFundingCycle memory fundingCycle);\\n}\\n\",\"keccak256\":\"0xaead823851433be0c2ddc8f8086813e6cd647de3a1bc0f7570a5d6b38c378b5a\",\"license\":\"MIT\"},\"contracts/interfaces/IJBMigratable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBMigratable {\\n function prepForMigrationOf(uint256 _projectId, address _from) external;\\n}\\n\",\"keccak256\":\"0xc81053e4b4754fc510aa04fecd3ab1460f01e3e27761e7a8c94f631a978ae127\",\"license\":\"MIT\"},\"contracts/interfaces/IJBOperatable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBOperatorStore.sol';\\n\\ninterface IJBOperatable {\\n function operatorStore() external view returns (IJBOperatorStore);\\n}\\n\",\"keccak256\":\"0x09a55a91c6ce3625379334271d236cfa47bf36522a91568b406bf06f7239407e\",\"license\":\"MIT\"},\"contracts/interfaces/IJBOperatorStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBOperatorData.sol';\\n\\ninterface IJBOperatorStore {\\n event SetOperator(\\n address indexed operator,\\n address indexed account,\\n uint256 indexed domain,\\n uint256[] permissionIndexes,\\n uint256 packed\\n );\\n\\n function permissionsOf(\\n address _operator,\\n address _account,\\n uint256 _domain\\n ) external view returns (uint256);\\n\\n function hasPermission(\\n address _operator,\\n address _account,\\n uint256 _domain,\\n uint256 _permissionIndex\\n ) external view returns (bool);\\n\\n function hasPermissions(\\n address _operator,\\n address _account,\\n uint256 _domain,\\n uint256[] calldata _permissionIndexes\\n ) external view returns (bool);\\n\\n function setOperator(JBOperatorData calldata _operatorData) external;\\n\\n function setOperators(JBOperatorData[] calldata _operatorData) external;\\n}\\n\",\"keccak256\":\"0x17f4929812a356984795fafed8cb2be816a025c9a0771d85595ac0b5ff3cffc5\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPayDelegate.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBDidPayData.sol';\\n\\n/**\\n @title\\n Pay delegate\\n\\n @notice\\n Delegate called after JBTerminal.pay(..) logic completion (if passed by the funding cycle datasource)\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n*/\\ninterface IJBPayDelegate is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.pay(..), after the execution of its logic\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control\\n \\n @param _data the data passed by the terminal, as a JBDidPayData struct:\\n address payer;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n JBTokenAmount amount;\\n JBTokenAmount forwardedAmount;\\n uint256 projectTokenCount;\\n address beneficiary;\\n bool preferClaimedTokens;\\n string memo;\\n bytes metadata;\\n */\\n function didPay(JBDidPayData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0xa797de18b69eceba117e1f0b3810cf3cc2d2791417d580a5bdc510d1b868ab26\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\n\\ninterface IJBPaymentTerminal is IERC165 {\\n function acceptsToken(address _token, uint256 _projectId) external view returns (bool);\\n\\n function currencyForToken(address _token) external view returns (uint256);\\n\\n function decimalsForToken(address _token) external view returns (uint256);\\n\\n // Return value must be a fixed point number with 18 decimals.\\n function currentEthOverflowOf(uint256 _projectId) external view returns (uint256);\\n\\n function pay(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable returns (uint256 beneficiaryTokenCount);\\n\\n function addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable;\\n}\\n\",\"keccak256\":\"0xb7826f5ed609359ce322c09e83236c47ba385df1c3cad3607e56fd0a2e00eee2\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPayoutRedemptionPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBFee.sol';\\nimport './IJBAllowanceTerminal.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFeeGauge.sol';\\nimport './IJBPayDelegate.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBPayoutTerminal.sol';\\nimport './IJBPrices.sol';\\nimport './IJBProjects.sol';\\nimport './IJBRedemptionDelegate.sol';\\nimport './IJBRedemptionTerminal.sol';\\nimport './IJBSingleTokenPaymentTerminalStore.sol';\\nimport './IJBSplitsStore.sol';\\n\\ninterface IJBPayoutRedemptionPaymentTerminal is\\n IJBPaymentTerminal,\\n IJBPayoutTerminal,\\n IJBAllowanceTerminal,\\n IJBRedemptionTerminal\\n{\\n event AddToBalance(\\n uint256 indexed projectId,\\n uint256 amount,\\n uint256 refundedFees,\\n string memo,\\n bytes metadata,\\n address caller\\n );\\n\\n event Migrate(\\n uint256 indexed projectId,\\n IJBPaymentTerminal indexed to,\\n uint256 amount,\\n address caller\\n );\\n\\n event DistributePayouts(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address beneficiary,\\n uint256 amount,\\n uint256 distributedAmount,\\n uint256 fee,\\n uint256 beneficiaryDistributionAmount,\\n string memo,\\n address caller\\n );\\n\\n event UseAllowance(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address beneficiary,\\n uint256 amount,\\n uint256 distributedAmount,\\n uint256 netDistributedamount,\\n string memo,\\n address caller\\n );\\n\\n event HoldFee(\\n uint256 indexed projectId,\\n uint256 indexed amount,\\n uint256 indexed fee,\\n uint256 feeDiscount,\\n address beneficiary,\\n address caller\\n );\\n\\n event ProcessFee(\\n uint256 indexed projectId,\\n uint256 indexed amount,\\n bool indexed wasHeld,\\n address beneficiary,\\n address caller\\n );\\n\\n event RefundHeldFees(\\n uint256 indexed projectId,\\n uint256 indexed amount,\\n uint256 indexed refundedFees,\\n uint256 leftoverAmount,\\n address caller\\n );\\n\\n event Pay(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address payer,\\n address beneficiary,\\n uint256 amount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n bytes metadata,\\n address caller\\n );\\n\\n event DelegateDidPay(\\n IJBPayDelegate indexed delegate,\\n JBDidPayData data,\\n uint256 delegatedAmount,\\n address caller\\n );\\n\\n event RedeemTokens(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address holder,\\n address beneficiary,\\n uint256 tokenCount,\\n uint256 reclaimedAmount,\\n string memo,\\n bytes metadata,\\n address caller\\n );\\n\\n event DelegateDidRedeem(\\n IJBRedemptionDelegate indexed delegate,\\n JBDidRedeemData data,\\n uint256 delegatedAmount,\\n address caller\\n );\\n\\n event DistributeToPayoutSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n uint256 amount,\\n address caller\\n );\\n\\n event SetFee(uint256 fee, address caller);\\n\\n event SetFeeGauge(IJBFeeGauge indexed feeGauge, address caller);\\n\\n event SetFeelessAddress(address indexed addrs, bool indexed flag, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function splitsStore() external view returns (IJBSplitsStore);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function prices() external view returns (IJBPrices);\\n\\n function store() external view returns (IJBSingleTokenPaymentTerminalStore);\\n\\n function baseWeightCurrency() external view returns (uint256);\\n\\n function payoutSplitsGroup() external view returns (uint256);\\n\\n function heldFeesOf(uint256 _projectId) external view returns (JBFee[] memory);\\n\\n function fee() external view returns (uint256);\\n\\n function feeGauge() external view returns (IJBFeeGauge);\\n\\n function isFeelessAddress(address _contract) external view returns (bool);\\n\\n function migrate(uint256 _projectId, IJBPaymentTerminal _to) external returns (uint256 balance);\\n\\n function processFees(uint256 _projectId) external;\\n\\n function setFee(uint256 _fee) external;\\n\\n function setFeeGauge(IJBFeeGauge _feeGauge) external;\\n\\n function setFeelessAddress(address _contract, bool _flag) external;\\n}\\n\",\"keccak256\":\"0x5cd280eda38ee2d6e50604576e9260a788bf89b55dd7801a3ed1e8f876920450\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPayoutTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBPayoutTerminal {\\n function distributePayoutsOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n address _token,\\n uint256 _minReturnedTokens,\\n string calldata _memo\\n ) external returns (uint256 netLeftoverDistributionAmount);\\n}\\n\",\"keccak256\":\"0xbb556a74e4f82e9d65c3d1c40120bc57487440844b7bcf8c66935748aeab2dbd\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPriceFeed.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBPriceFeed {\\n function currentPrice(uint256 _targetDecimals) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x57c71282fec1b34b00cf991ffed2e36031c393e35bfa7ca5d723eb6572fb7122\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPrices.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBPriceFeed.sol';\\n\\ninterface IJBPrices {\\n event AddFeed(uint256 indexed currency, uint256 indexed base, IJBPriceFeed feed);\\n\\n function feedFor(uint256 _currency, uint256 _base) external view returns (IJBPriceFeed);\\n\\n function priceFor(\\n uint256 _currency,\\n uint256 _base,\\n uint256 _decimals\\n ) external view returns (uint256);\\n\\n function addFeedFor(\\n uint256 _currency,\\n uint256 _base,\\n IJBPriceFeed _priceFeed\\n ) external;\\n}\\n\",\"keccak256\":\"0x82a175b1f4b95b506c98406576cd59cbe04615e3df24f9cf3587b61b8ee323b1\",\"license\":\"MIT\"},\"contracts/interfaces/IJBProjects.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBTokenUriResolver.sol';\\n\\ninterface IJBProjects is IERC721 {\\n event Create(\\n uint256 indexed projectId,\\n address indexed owner,\\n JBProjectMetadata metadata,\\n address caller\\n );\\n\\n event SetMetadata(uint256 indexed projectId, JBProjectMetadata metadata, address caller);\\n\\n event SetTokenUriResolver(IJBTokenUriResolver indexed resolver, address caller);\\n\\n function count() external view returns (uint256);\\n\\n function metadataContentOf(uint256 _projectId, uint256 _domain)\\n external\\n view\\n returns (string memory);\\n\\n function tokenUriResolver() external view returns (IJBTokenUriResolver);\\n\\n function createFor(address _owner, JBProjectMetadata calldata _metadata)\\n external\\n returns (uint256 projectId);\\n\\n function setMetadataOf(uint256 _projectId, JBProjectMetadata calldata _metadata) external;\\n\\n function setTokenUriResolver(IJBTokenUriResolver _newResolver) external;\\n}\\n\",\"keccak256\":\"0x7cfc021d0bd7e73b1ba8f4845d7d35e3419d6a14d3d25ca3a8010e7f91062fe4\",\"license\":\"MIT\"},\"contracts/interfaces/IJBRedemptionDelegate.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBDidRedeemData.sol';\\n\\n/**\\n @title\\n Redemption delegate\\n\\n @notice\\n Delegate called after JBTerminal.redeemTokensOf(..) logic completion (if passed by the funding cycle datasource)\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n*/\\ninterface IJBRedemptionDelegate is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.redeemTokensOf(..), after the execution of its logic\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control\\n \\n @param _data the data passed by the terminal, as a JBDidRedeemData struct:\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 projectTokenCount;\\n JBTokenAmount reclaimedAmount;\\n JBTokenAmount forwardedAmount;\\n address payable beneficiary;\\n string memo;\\n bytes metadata;\\n */\\n function didRedeem(JBDidRedeemData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0x172d2c0be65e72e54f71ae521907067f0fa30e8ca05c4f88826903208aa437e2\",\"license\":\"MIT\"},\"contracts/interfaces/IJBRedemptionTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBRedemptionTerminal {\\n function redeemTokensOf(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n address _token,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external returns (uint256 reclaimAmount);\\n}\\n\",\"keccak256\":\"0xe26a6a03468401b802ae5328b39a266f53b9331a1c077fcbf7719d10ba74ff44\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSingleTokenPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBPaymentTerminal.sol';\\n\\ninterface IJBSingleTokenPaymentTerminal is IJBPaymentTerminal {\\n function token() external view returns (address);\\n\\n function currency() external view returns (uint256);\\n\\n function decimals() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xf6e78323caa9af7bbf024f44b2032a83fed0394e0b3a242a6346e73c85b2e46f\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSingleTokenPaymentTerminalStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBPayDelegateAllocation.sol';\\nimport './../structs/JBRedemptionDelegateAllocation.sol';\\nimport './../structs/JBTokenAmount.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBPrices.sol';\\nimport './IJBSingleTokenPaymentTerminal.sol';\\n\\ninterface IJBSingleTokenPaymentTerminalStore {\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function prices() external view returns (IJBPrices);\\n\\n function balanceOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\\n external\\n view\\n returns (uint256);\\n\\n function usedDistributionLimitOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _fundingCycleNumber\\n ) external view returns (uint256);\\n\\n function usedOverflowAllowanceOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _fundingCycleConfiguration\\n ) external view returns (uint256);\\n\\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\\n external\\n view\\n returns (uint256);\\n\\n function currentTotalOverflowOf(\\n uint256 _projectId,\\n uint256 _decimals,\\n uint256 _currency\\n ) external view returns (uint256);\\n\\n function currentReclaimableOverflowOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n bool _useTotalOverflow\\n ) external view returns (uint256);\\n\\n function currentReclaimableOverflowOf(\\n uint256 _projectId,\\n uint256 _tokenCount,\\n uint256 _totalSupply,\\n uint256 _overflow\\n ) external view returns (uint256);\\n\\n function recordPaymentFrom(\\n address _payer,\\n JBTokenAmount memory _amount,\\n uint256 _projectId,\\n uint256 _baseWeightCurrency,\\n address _beneficiary,\\n string calldata _memo,\\n bytes calldata _metadata\\n )\\n external\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 tokenCount,\\n JBPayDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n );\\n\\n function recordRedemptionFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n string calldata _memo,\\n bytes calldata _metadata\\n )\\n external\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 reclaimAmount,\\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n );\\n\\n function recordDistributionFor(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n ) external returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount);\\n\\n function recordUsedAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n ) external returns (JBFundingCycle memory fundingCycle, uint256 withdrawnAmount);\\n\\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external;\\n\\n function recordMigration(uint256 _projectId) external returns (uint256 balance);\\n}\\n\",\"keccak256\":\"0xd78929c9371fd7895b829ef5e4ad4b3786523c3580ac3f6f5f25d2b5941c0dd3\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSplitAllocator.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport '../structs/JBSplitAllocationData.sol';\\n\\n/**\\n @title\\n Split allocator\\n\\n @notice\\n Provide a way to process a single split with extra logic\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n\\n @dev\\n The contract address should be set as an allocator in the adequate split\\n*/\\ninterface IJBSplitAllocator is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.distributePayoutOf(..), during the processing of the split including it\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control. The token and/or eth are optimistically transfered\\n to the allocator for its logic.\\n \\n @param _data the data passed by the terminal, as a JBSplitAllocationData struct:\\n address token;\\n uint256 amount;\\n uint256 decimals;\\n uint256 projectId;\\n uint256 group;\\n JBSplit split;\\n */\\n function allocate(JBSplitAllocationData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0x5efb6f51fc161f42ff58989386ad99028e4039a0ba897d66f358c3dfcf686105\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSplitsStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBGroupedSplits.sol';\\nimport './../structs/JBSplit.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBProjects.sol';\\n\\ninterface IJBSplitsStore {\\n event SetSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n address caller\\n );\\n\\n function projects() external view returns (IJBProjects);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function splitsOf(\\n uint256 _projectId,\\n uint256 _domain,\\n uint256 _group\\n ) external view returns (JBSplit[] memory);\\n\\n function set(\\n uint256 _projectId,\\n uint256 _domain,\\n JBGroupedSplits[] memory _groupedSplits\\n ) external;\\n}\\n\",\"keccak256\":\"0x66dab3dd394e318b850401ca92c2963b906cc0ad5562fa5d4f6f850175d1c77a\",\"license\":\"MIT\"},\"contracts/interfaces/IJBToken.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBToken {\\n function projectId() external view returns (uint256);\\n\\n function decimals() external view returns (uint8);\\n\\n function totalSupply(uint256 _projectId) external view returns (uint256);\\n\\n function balanceOf(address _account, uint256 _projectId) external view returns (uint256);\\n\\n function mint(\\n uint256 _projectId,\\n address _account,\\n uint256 _amount\\n ) external;\\n\\n function burn(\\n uint256 _projectId,\\n address _account,\\n uint256 _amount\\n ) external;\\n\\n function approve(\\n uint256,\\n address _spender,\\n uint256 _amount\\n ) external;\\n\\n function transfer(\\n uint256 _projectId,\\n address _to,\\n uint256 _amount\\n ) external;\\n\\n function transferFrom(\\n uint256 _projectId,\\n address _from,\\n address _to,\\n uint256 _amount\\n ) external;\\n}\\n\",\"keccak256\":\"0xe8969210417736c85d71101bf1c0bd8ebbf9d1e62a93e758148bd5709a6c7097\",\"license\":\"MIT\"},\"contracts/interfaces/IJBTokenStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBProjects.sol';\\nimport './IJBToken.sol';\\n\\ninterface IJBTokenStore {\\n event Issue(\\n uint256 indexed projectId,\\n IJBToken indexed token,\\n string name,\\n string symbol,\\n address caller\\n );\\n\\n event Mint(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 amount,\\n bool tokensWereClaimed,\\n bool preferClaimedTokens,\\n address caller\\n );\\n\\n event Burn(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 amount,\\n uint256 initialUnclaimedBalance,\\n uint256 initialClaimedBalance,\\n bool preferClaimedTokens,\\n address caller\\n );\\n\\n event Claim(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 initialUnclaimedBalance,\\n uint256 amount,\\n address caller\\n );\\n\\n event Set(uint256 indexed projectId, IJBToken indexed newToken, address caller);\\n\\n event Transfer(\\n address indexed holder,\\n uint256 indexed projectId,\\n address indexed recipient,\\n uint256 amount,\\n address caller\\n );\\n\\n function tokenOf(uint256 _projectId) external view returns (IJBToken);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function unclaimedBalanceOf(address _holder, uint256 _projectId) external view returns (uint256);\\n\\n function unclaimedTotalSupplyOf(uint256 _projectId) external view returns (uint256);\\n\\n function totalSupplyOf(uint256 _projectId) external view returns (uint256);\\n\\n function balanceOf(address _holder, uint256 _projectId) external view returns (uint256 _result);\\n\\n function issueFor(\\n uint256 _projectId,\\n string calldata _name,\\n string calldata _symbol\\n ) external returns (IJBToken token);\\n\\n function setFor(uint256 _projectId, IJBToken _token) external;\\n\\n function burnFrom(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function mintFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function claimFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount\\n ) external;\\n\\n function transferFrom(\\n address _holder,\\n uint256 _projectId,\\n address _recipient,\\n uint256 _amount\\n ) external;\\n}\\n\",\"keccak256\":\"0x98459e3af050d41dfeffdc97f1c93330207ba450f8ff3613224b49a89eeca9c6\",\"license\":\"MIT\"},\"contracts/interfaces/IJBTokenUriResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBTokenUriResolver {\\n function getUri(uint256 _projectId) external view returns (string memory tokenUri);\\n}\\n\",\"keccak256\":\"0xd267fd8ca7c21c2c71794acdb9a98314c33a35fc559e0bf0897a6686d196d174\",\"license\":\"MIT\"},\"contracts/libraries/JBConstants.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/**\\n @notice\\n Global constants used across Juicebox contracts.\\n*/\\nlibrary JBConstants {\\n uint256 public constant MAX_RESERVED_RATE = 10_000;\\n uint256 public constant MAX_REDEMPTION_RATE = 10_000;\\n uint256 public constant MAX_DISCOUNT_RATE = 1_000_000_000;\\n uint256 public constant SPLITS_TOTAL_PERCENT = 1_000_000_000;\\n uint256 public constant MAX_FEE = 1_000_000_000;\\n uint256 public constant MAX_FEE_DISCOUNT = 1_000_000_000;\\n}\\n\",\"keccak256\":\"0x34362846a1cd428a8bdedf4ab6857e11402f345cb87b994b2e7fb6d2474b808d\",\"license\":\"MIT\"},\"contracts/libraries/JBCurrencies.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBCurrencies {\\n uint256 public constant ETH = 1;\\n uint256 public constant USD = 2;\\n}\\n\",\"keccak256\":\"0x7e417ff25c173608ee4fe6d9fc3dcd5e1458c78c889af12bac47b1189a436076\",\"license\":\"MIT\"},\"contracts/libraries/JBFixedPointNumber.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nlibrary JBFixedPointNumber {\\n function adjustDecimals(\\n uint256 _value,\\n uint256 _decimals,\\n uint256 _targetDecimals\\n ) internal pure returns (uint256) {\\n // If decimals need adjusting, multiply or divide the price by the decimal adjuster to get the normalized result.\\n if (_targetDecimals == _decimals) return _value;\\n else if (_targetDecimals > _decimals) return _value * 10**(_targetDecimals - _decimals);\\n else return _value / 10**(_decimals - _targetDecimals);\\n }\\n}\\n\",\"keccak256\":\"0x18efac48269f3a3bd7e9a1c770776f950e0afa86769e6f8b128002c3b8c6742c\",\"license\":\"MIT\"},\"contracts/libraries/JBFundingCycleMetadataResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBFundingCycleMetadata.sol';\\nimport './../structs/JBGlobalFundingCycleMetadata.sol';\\nimport './JBConstants.sol';\\nimport './JBGlobalFundingCycleMetadataResolver.sol';\\n\\nlibrary JBFundingCycleMetadataResolver {\\n function global(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (JBGlobalFundingCycleMetadata memory)\\n {\\n return JBGlobalFundingCycleMetadataResolver.expandMetadata(uint8(_fundingCycle.metadata >> 8));\\n }\\n\\n function reservedRate(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n return uint256(uint16(_fundingCycle.metadata >> 24));\\n }\\n\\n function redemptionRate(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n // Redemption rate is a number 0-10000. It's inverse was stored so the most common case of 100% results in no storage needs.\\n return JBConstants.MAX_REDEMPTION_RATE - uint256(uint16(_fundingCycle.metadata >> 40));\\n }\\n\\n function ballotRedemptionRate(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (uint256)\\n {\\n // Redemption rate is a number 0-10000. It's inverse was stored so the most common case of 100% results in no storage needs.\\n return JBConstants.MAX_REDEMPTION_RATE - uint256(uint16(_fundingCycle.metadata >> 56));\\n }\\n\\n function payPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 72) & 1) == 1;\\n }\\n\\n function distributionsPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 73) & 1) == 1;\\n }\\n\\n function redeemPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 74) & 1) == 1;\\n }\\n\\n function burnPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 75) & 1) == 1;\\n }\\n\\n function mintingAllowed(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 76) & 1) == 1;\\n }\\n\\n function terminalMigrationAllowed(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 77) & 1) == 1;\\n }\\n\\n function controllerMigrationAllowed(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 78) & 1) == 1;\\n }\\n\\n function shouldHoldFees(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 79) & 1) == 1;\\n }\\n\\n function preferClaimedTokenOverride(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 80) & 1) == 1;\\n }\\n\\n function useTotalOverflowForRedemptions(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 81) & 1) == 1;\\n }\\n\\n function useDataSourceForPay(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return (_fundingCycle.metadata >> 82) & 1 == 1;\\n }\\n\\n function useDataSourceForRedeem(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return (_fundingCycle.metadata >> 83) & 1 == 1;\\n }\\n\\n function dataSource(JBFundingCycle memory _fundingCycle) internal pure returns (address) {\\n return address(uint160(_fundingCycle.metadata >> 84));\\n }\\n\\n function metadata(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n return uint256(uint8(_fundingCycle.metadata >> 244));\\n }\\n\\n /**\\n @notice\\n Pack the funding cycle metadata.\\n\\n @param _metadata The metadata to validate and pack.\\n\\n @return packed The packed uint256 of all metadata params. The first 8 bits specify the version.\\n */\\n function packFundingCycleMetadata(JBFundingCycleMetadata memory _metadata)\\n internal\\n pure\\n returns (uint256 packed)\\n {\\n // version 1 in the bits 0-7 (8 bits).\\n packed = 1;\\n // global metadta in bits 8-23 (16 bits).\\n packed |=\\n JBGlobalFundingCycleMetadataResolver.packFundingCycleGlobalMetadata(_metadata.global) <<\\n 8;\\n // reserved rate in bits 24-39 (16 bits).\\n packed |= _metadata.reservedRate << 24;\\n // redemption rate in bits 40-55 (16 bits).\\n // redemption rate is a number 0-10000. Store the reverse so the most common case of 100% results in no storage needs.\\n packed |= (JBConstants.MAX_REDEMPTION_RATE - _metadata.redemptionRate) << 40;\\n // ballot redemption rate rate in bits 56-71 (16 bits).\\n // ballot redemption rate is a number 0-10000. Store the reverse so the most common case of 100% results in no storage needs.\\n packed |= (JBConstants.MAX_REDEMPTION_RATE - _metadata.ballotRedemptionRate) << 56;\\n // pause pay in bit 72.\\n if (_metadata.pausePay) packed |= 1 << 72;\\n // pause tap in bit 73.\\n if (_metadata.pauseDistributions) packed |= 1 << 73;\\n // pause redeem in bit 74.\\n if (_metadata.pauseRedeem) packed |= 1 << 74;\\n // pause burn in bit 75.\\n if (_metadata.pauseBurn) packed |= 1 << 75;\\n // allow minting in bit 76.\\n if (_metadata.allowMinting) packed |= 1 << 76;\\n // allow terminal migration in bit 77.\\n if (_metadata.allowTerminalMigration) packed |= 1 << 77;\\n // allow controller migration in bit 78.\\n if (_metadata.allowControllerMigration) packed |= 1 << 78;\\n // hold fees in bit 79.\\n if (_metadata.holdFees) packed |= 1 << 79;\\n // prefer claimed token override in bit 80.\\n if (_metadata.preferClaimedTokenOverride) packed |= 1 << 80;\\n // useTotalOverflowForRedemptions in bit 81.\\n if (_metadata.useTotalOverflowForRedemptions) packed |= 1 << 81;\\n // use pay data source in bit 82.\\n if (_metadata.useDataSourceForPay) packed |= 1 << 82;\\n // use redeem data source in bit 83.\\n if (_metadata.useDataSourceForRedeem) packed |= 1 << 83;\\n // data source address in bits 84-243.\\n packed |= uint256(uint160(address(_metadata.dataSource))) << 84;\\n // metadata in bits 244-252 (8 bits).\\n packed |= _metadata.metadata << 244;\\n }\\n\\n /**\\n @notice\\n Expand the funding cycle metadata.\\n\\n @param _fundingCycle The funding cycle having its metadata expanded.\\n\\n @return metadata The metadata object.\\n */\\n function expandMetadata(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (JBFundingCycleMetadata memory)\\n {\\n return\\n JBFundingCycleMetadata(\\n global(_fundingCycle),\\n reservedRate(_fundingCycle),\\n redemptionRate(_fundingCycle),\\n ballotRedemptionRate(_fundingCycle),\\n payPaused(_fundingCycle),\\n distributionsPaused(_fundingCycle),\\n redeemPaused(_fundingCycle),\\n burnPaused(_fundingCycle),\\n mintingAllowed(_fundingCycle),\\n terminalMigrationAllowed(_fundingCycle),\\n controllerMigrationAllowed(_fundingCycle),\\n shouldHoldFees(_fundingCycle),\\n preferClaimedTokenOverride(_fundingCycle),\\n useTotalOverflowForRedemptions(_fundingCycle),\\n useDataSourceForPay(_fundingCycle),\\n useDataSourceForRedeem(_fundingCycle),\\n dataSource(_fundingCycle),\\n metadata(_fundingCycle)\\n );\\n }\\n}\\n\",\"keccak256\":\"0x3d045c38593102cfb6ac67f3ddf2232e1ff5518d6d021423ae2681387599fbd3\",\"license\":\"MIT\"},\"contracts/libraries/JBGlobalFundingCycleMetadataResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport './../structs/JBFundingCycleMetadata.sol';\\n\\nlibrary JBGlobalFundingCycleMetadataResolver {\\n function setTerminalsAllowed(uint8 _data) internal pure returns (bool) {\\n return (_data & 1) == 1;\\n }\\n\\n function setControllerAllowed(uint8 _data) internal pure returns (bool) {\\n return ((_data >> 1) & 1) == 1;\\n }\\n\\n function transfersPaused(uint8 _data) internal pure returns (bool) {\\n return ((_data >> 2) & 1) == 1;\\n }\\n\\n /**\\n @notice\\n Pack the global funding cycle metadata.\\n\\n @param _metadata The metadata to validate and pack.\\n\\n @return packed The packed uint256 of all global metadata params. The first 8 bits specify the version.\\n */\\n function packFundingCycleGlobalMetadata(JBGlobalFundingCycleMetadata memory _metadata)\\n internal\\n pure\\n returns (uint256 packed)\\n {\\n // allow set terminals in bit 0.\\n if (_metadata.allowSetTerminals) packed |= 1;\\n // allow set controller in bit 1.\\n if (_metadata.allowSetController) packed |= 1 << 1;\\n // pause transfers in bit 2.\\n if (_metadata.pauseTransfers) packed |= 1 << 2;\\n }\\n\\n /**\\n @notice\\n Expand the global funding cycle metadata.\\n\\n @param _packedMetadata The packed metadata to expand.\\n\\n @return metadata The global metadata object.\\n */\\n function expandMetadata(uint8 _packedMetadata)\\n internal\\n pure\\n returns (JBGlobalFundingCycleMetadata memory metadata)\\n {\\n return\\n JBGlobalFundingCycleMetadata(\\n setTerminalsAllowed(_packedMetadata),\\n setControllerAllowed(_packedMetadata),\\n transfersPaused(_packedMetadata)\\n );\\n }\\n}\\n\",\"keccak256\":\"0x0d998f938026edeb755987a79421267cf860801161b5f171206a200b60f1061f\",\"license\":\"MIT\"},\"contracts/libraries/JBOperations.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBOperations {\\n uint256 public constant RECONFIGURE = 1;\\n uint256 public constant REDEEM = 2;\\n uint256 public constant MIGRATE_CONTROLLER = 3;\\n uint256 public constant MIGRATE_TERMINAL = 4;\\n uint256 public constant PROCESS_FEES = 5;\\n uint256 public constant SET_METADATA = 6;\\n uint256 public constant ISSUE = 7;\\n uint256 public constant SET_TOKEN = 8;\\n uint256 public constant MINT = 9;\\n uint256 public constant BURN = 10;\\n uint256 public constant CLAIM = 11;\\n uint256 public constant TRANSFER = 12;\\n uint256 public constant REQUIRE_CLAIM = 13; // unused in v3\\n uint256 public constant SET_CONTROLLER = 14;\\n uint256 public constant SET_TERMINALS = 15;\\n uint256 public constant SET_PRIMARY_TERMINAL = 16;\\n uint256 public constant USE_ALLOWANCE = 17;\\n uint256 public constant SET_SPLITS = 18;\\n}\\n\",\"keccak256\":\"0x7f8e501e6890297f4015b1c27cebdb44fadbf21204bea1f3162f5388c060f690\",\"license\":\"MIT\"},\"contracts/libraries/JBSplitsGroups.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBSplitsGroups {\\n uint256 public constant ETH_PAYOUT = 1;\\n uint256 public constant RESERVED_TOKENS = 2;\\n}\\n\",\"keccak256\":\"0x4183db6087bd8db645fc3a0d3d8afb0d6356e003650793f63c301ebbbae47269\",\"license\":\"MIT\"},\"contracts/libraries/JBTokens.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBTokens {\\n /** \\n @notice \\n The ETH token address in Juicebox is represented by 0x000000000000000000000000000000000000EEEe.\\n */\\n address public constant ETH = address(0x000000000000000000000000000000000000EEEe);\\n}\\n\",\"keccak256\":\"0xecf82992f7b827766aa55f16872517a646521eef414d8cc9786617ea377e5463\",\"license\":\"MIT\"},\"contracts/structs/JBDidPayData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member payer The address from which the payment originated.\\n @member projectId The ID of the project for which the payment was made.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the payment is being made.\\n @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.\\n @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.\\n @member projectTokenCount The number of project tokens minted for the beneficiary.\\n @member beneficiary The address to which the tokens were minted.\\n @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.\\n @member memo The memo that is being emitted alongside the payment.\\n @member metadata Extra data to send to the delegate.\\n*/\\nstruct JBDidPayData {\\n address payer;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n JBTokenAmount amount;\\n JBTokenAmount forwardedAmount;\\n uint256 projectTokenCount;\\n address beneficiary;\\n bool preferClaimedTokens;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0xf3c664309b37790f16047ae97b0459889ae0242dfcde7fc8902c8d10c7f8e6b6\",\"license\":\"MIT\"},\"contracts/structs/JBDidRedeemData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member holder The holder of the tokens being redeemed.\\n @member projectId The ID of the project with which the redeemed tokens are associated.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the redemption is being made.\\n @member projectTokenCount The number of project tokens being redeemed.\\n @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.\\n @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.\\n @member beneficiary The address to which the reclaimed amount will be sent.\\n @member memo The memo that is being emitted alongside the redemption.\\n @member metadata Extra data to send to the delegate.\\n*/\\nstruct JBDidRedeemData {\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 projectTokenCount;\\n JBTokenAmount reclaimedAmount;\\n JBTokenAmount forwardedAmount;\\n address payable beneficiary;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0xe2c401f39723a7ce915b8bef328744c66daaf57460843964b941456c2258a412\",\"license\":\"MIT\"},\"contracts/structs/JBFee.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member amount The total amount the fee was taken from, as a fixed point number with the same number of decimals as the terminal in which this struct was created.\\n @member fee The percent of the fee, out of MAX_FEE.\\n @member feeDiscount The discount of the fee.\\n @member beneficiary The address that will receive the tokens that are minted as a result of the fee payment.\\n*/\\nstruct JBFee {\\n uint256 amount;\\n uint32 fee;\\n uint32 feeDiscount;\\n address beneficiary;\\n}\\n\",\"keccak256\":\"0xf4759ff41fe7f1db0fd1ccc7b2a326b239389fd8d69df9b9ed5e1d5926f6fe38\",\"license\":\"MIT\"},\"contracts/structs/JBFundAccessConstraints.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBPaymentTerminal.sol';\\n\\n/** \\n @member terminal The terminal within which the distribution limit and the overflow allowance applies.\\n @member token The token for which the fund access constraints apply.\\n @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.\\n @member distributionLimitCurrency The currency of the distribution limit.\\n @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.\\n @member overflowAllowanceCurrency The currency of the overflow allowance.\\n*/\\nstruct JBFundAccessConstraints {\\n IJBPaymentTerminal terminal;\\n address token;\\n uint256 distributionLimit;\\n uint256 distributionLimitCurrency;\\n uint256 overflowAllowance;\\n uint256 overflowAllowanceCurrency;\\n}\\n\",\"keccak256\":\"0x85ebaa57b788cbdedc7a3d0eec4892eda5d79db7c1a6103797f10d0d989775b2\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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.\\n @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.\\n @member basedOn The `configuration` of the funding cycle that was active when this cycle was created.\\n @member start The timestamp marking the moment from which the funding cycle is considered active. It is a unix timestamp measured in seconds.\\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n @member metadata Extra data that can be associated with a funding cycle.\\n*/\\nstruct JBFundingCycle {\\n uint256 number;\\n uint256 configuration;\\n uint256 basedOn;\\n uint256 start;\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n uint256 metadata;\\n}\\n\",\"keccak256\":\"0xcdd3ac9b6fa67e62ada88d09b73bc35ade1cd77d43db712289266a788928b4c2\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycleData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n*/\\nstruct JBFundingCycleData {\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n}\\n\",\"keccak256\":\"0x2aa6368bf4dfc5797e8b02a978293de0c777fae2658de2c825a103587240f3b0\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycleMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBGlobalFundingCycleMetadata.sol';\\n\\n/** \\n @member global Data used globally in non-migratable ecosystem contracts.\\n @member reservedRate The reserved rate of the funding cycle. This number is a percentage calculated out of `JBConstants.MAX_RESERVED_RATE`.\\n @member redemptionRate The redemption rate of the funding cycle. This number is a percentage calculated out of `JBConstants.MAX_REDEMPTION_RATE`.\\n @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`.\\n @member pausePay A flag indicating if the pay functionality should be paused during the funding cycle.\\n @member pauseDistributions A flag indicating if the distribute functionality should be paused during the funding cycle.\\n @member pauseRedeem A flag indicating if the redeem functionality should be paused during the funding cycle.\\n @member pauseBurn A flag indicating if the burn functionality should be paused during the funding cycle.\\n @member allowMinting A flag indicating if minting tokens should be allowed during this funding cycle.\\n @member allowTerminalMigration A flag indicating if migrating terminals should be allowed during this funding cycle.\\n @member allowControllerMigration A flag indicating if migrating controllers should be allowed during this funding cycle.\\n @member holdFees A flag indicating if fees should be held during this funding cycle.\\n @member preferClaimedTokenOverride A flag indicating if claimed tokens should always be prefered to unclaimed tokens when minting.\\n @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.\\n @member useDataSourceForPay A flag indicating if the data source should be used for pay transactions during this funding cycle.\\n @member useDataSourceForRedeem A flag indicating if the data source should be used for redeem transactions during this funding cycle.\\n @member dataSource The data source to use during this funding cycle.\\n @member metadata Metadata of the metadata, up to uint8 in size.\\n*/\\nstruct JBFundingCycleMetadata {\\n JBGlobalFundingCycleMetadata global;\\n uint256 reservedRate;\\n uint256 redemptionRate;\\n uint256 ballotRedemptionRate;\\n bool pausePay;\\n bool pauseDistributions;\\n bool pauseRedeem;\\n bool pauseBurn;\\n bool allowMinting;\\n bool allowTerminalMigration;\\n bool allowControllerMigration;\\n bool holdFees;\\n bool preferClaimedTokenOverride;\\n bool useTotalOverflowForRedemptions;\\n bool useDataSourceForPay;\\n bool useDataSourceForRedeem;\\n address dataSource;\\n uint256 metadata;\\n}\\n\",\"keccak256\":\"0x783604440cac8d176332eab28166f188ee5c230378c08cfc95fea4f7187dc77d\",\"license\":\"MIT\"},\"contracts/structs/JBGlobalFundingCycleMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member allowSetTerminals A flag indicating if setting terminals should be allowed during this funding cycle.\\n @member allowSetController A flag indicating if setting a new controller should be allowed during this funding cycle.\\n @member pauseTransfers A flag indicating if the project token transfer functionality should be paused during the funding cycle.\\n*/\\nstruct JBGlobalFundingCycleMetadata {\\n bool allowSetTerminals;\\n bool allowSetController;\\n bool pauseTransfers;\\n}\\n\",\"keccak256\":\"0x05d85530305fec6d6eca54cdbc2cd9110cbda0146598032b0203aa4b622944ff\",\"license\":\"MIT\"},\"contracts/structs/JBGroupedSplits.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBSplit.sol';\\n\\n/** \\n @member group The group indentifier.\\n @member splits The splits to associate with the group.\\n*/\\nstruct JBGroupedSplits {\\n uint256 group;\\n JBSplit[] splits;\\n}\\n\",\"keccak256\":\"0x80be1b220da4ac04851ea540ebb94c1ec2b0442ec5bd1e88fdf78a56becd8b5a\",\"license\":\"MIT\"},\"contracts/structs/JBOperatorData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member operator The address of the operator.\\n @member domain The domain within which the operator is being given permissions. A domain of 0 is a wildcard domain, which gives an operator access to all domains.\\n @member permissionIndexes The indexes of the permissions the operator is being given.\\n*/\\nstruct JBOperatorData {\\n address operator;\\n uint256 domain;\\n uint256[] permissionIndexes;\\n}\\n\",\"keccak256\":\"0x3b85be7b69515976ee10770776283911666aceca820b0cf4e201ea4dbffeb6f0\",\"license\":\"MIT\"},\"contracts/structs/JBPayDelegateAllocation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '../interfaces/IJBPayDelegate.sol';\\n\\n/** \\n @member delegate A delegate contract to use for subsequent calls.\\n @member amount The amount to send to the delegate.\\n*/\\nstruct JBPayDelegateAllocation {\\n IJBPayDelegate delegate;\\n uint256 amount;\\n}\\n\",\"keccak256\":\"0xb4e558dc62231d89e9b48998012577d22c3e52b58e23401f22d9096827f6ea0c\",\"license\":\"MIT\"},\"contracts/structs/JBProjectMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member content The metadata content.\\n @member domain The domain within which the metadata applies.\\n*/\\nstruct JBProjectMetadata {\\n string content;\\n uint256 domain;\\n}\\n\",\"keccak256\":\"0x90ad7b1014c0a9f945fe7a2efde9d5de41e40574fa27969070b1d2ff52033ea0\",\"license\":\"MIT\"},\"contracts/structs/JBRedemptionDelegateAllocation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '../interfaces/IJBRedemptionDelegate.sol';\\n\\n/** \\n @member delegate A delegate contract to use for subsequent calls.\\n @member amount The amount to send to the delegate.\\n*/\\nstruct JBRedemptionDelegateAllocation {\\n IJBRedemptionDelegate delegate;\\n uint256 amount;\\n}\\n\",\"keccak256\":\"0x10c29d33dd0d875a0d4692a2b9a9355c2ebf433cc06a9a60253d4366b60d4d31\",\"license\":\"MIT\"},\"contracts/structs/JBSplit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBSplitAllocator.sol';\\n\\n/** \\n @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.\\n @member preferAddToBalance A flag indicating if a distribution to a project should prefer triggering it's addToBalance function instead of its pay function.\\n @member percent The percent of the whole group that this split occupies. This number is out of `JBConstants.SPLITS_TOTAL_PERCENT`.\\n @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.\\n @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.\\n @member lockedUntil Specifies if the split should be unchangeable until the specified time, with the exception of extending the locked period.\\n @member allocator If an allocator is specified, funds will be sent to the allocator contract along with all properties of this split.\\n*/\\nstruct JBSplit {\\n bool preferClaimed;\\n bool preferAddToBalance;\\n uint256 percent;\\n uint256 projectId;\\n address payable beneficiary;\\n uint256 lockedUntil;\\n IJBSplitAllocator allocator;\\n}\\n\",\"keccak256\":\"0xc80a16606da8abf76d0f73abc38aee041e24f29342c1939018f70c286e89f105\",\"license\":\"MIT\"},\"contracts/structs/JBSplitAllocationData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBSplit.sol';\\n\\n/** \\n @member token The token being sent to the split allocator.\\n @member amount The amount being sent to the split allocator, as a fixed point number.\\n @member decimals The number of decimals in the amount.\\n @member projectId The project to which the split belongs.\\n @member group The group to which the split belongs.\\n @member split The split that caused the allocation.\\n*/\\nstruct JBSplitAllocationData {\\n address token;\\n uint256 amount;\\n uint256 decimals;\\n uint256 projectId;\\n uint256 group;\\n JBSplit split;\\n}\\n\",\"keccak256\":\"0x39f5c41bd31d36774744698ac94484b6cab62d7038df2f29d947668959782e63\",\"license\":\"MIT\"},\"contracts/structs/JBTokenAmount.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/* \\n @member token The token the payment was made in.\\n @member value The amount of tokens that was paid, as a fixed point number.\\n @member decimals The number of decimals included in the value fixed point number.\\n @member currency The expected currency of the value.\\n**/\\nstruct JBTokenAmount {\\n address token;\\n uint256 value;\\n uint256 decimals;\\n uint256 currency;\\n}\\n\",\"keccak256\":\"0x4a778e779ba257ba5638c5469e07a4d21b55a3128d56db5a0fdfacb1f3301c51\",\"license\":\"MIT\"},\"prb-math/contracts/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivFixedPointOverflow(uint256 prod1);\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivOverflow(uint256 prod1, uint256 denominator);\\n\\n/// @notice Emitted when one of the inputs is type(int256).min.\\nerror PRBMath__MulDivSignedInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows int256.\\nerror PRBMath__MulDivSignedOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is MIN_SD59x18.\\nerror PRBMathSD59x18__AbsInputTooSmall();\\n\\n/// @notice Emitted when ceiling a number overflows SD59x18.\\nerror PRBMathSD59x18__CeilOverflow(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__DivInputTooSmall();\\n\\n/// @notice Emitted when one of the intermediary unsigned results overflows SD59x18.\\nerror PRBMathSD59x18__DivOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathSD59x18__ExpInputTooBig(int256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathSD59x18__Exp2InputTooBig(int256 x);\\n\\n/// @notice Emitted when flooring a number underflows SD59x18.\\nerror PRBMathSD59x18__FloorUnderflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format overflows SD59x18.\\nerror PRBMathSD59x18__FromIntOverflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format underflows SD59x18.\\nerror PRBMathSD59x18__FromIntUnderflow(int256 x);\\n\\n/// @notice Emitted when the product of the inputs is negative.\\nerror PRBMathSD59x18__GmNegativeProduct(int256 x, int256 y);\\n\\n/// @notice Emitted when multiplying the inputs overflows SD59x18.\\nerror PRBMathSD59x18__GmOverflow(int256 x, int256 y);\\n\\n/// @notice Emitted when the input is less than or equal to zero.\\nerror PRBMathSD59x18__LogInputTooSmall(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__MulInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__MulOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__PowuOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is negative.\\nerror PRBMathSD59x18__SqrtNegativeInput(int256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows SD59x18.\\nerror PRBMathSD59x18__SqrtOverflow(int256 x);\\n\\n/// @notice Emitted when addition overflows UD60x18.\\nerror PRBMathUD60x18__AddOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when ceiling a number overflows UD60x18.\\nerror PRBMathUD60x18__CeilOverflow(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathUD60x18__ExpInputTooBig(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathUD60x18__Exp2InputTooBig(uint256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format format overflows UD60x18.\\nerror PRBMathUD60x18__FromUintOverflow(uint256 x);\\n\\n/// @notice Emitted when multiplying the inputs overflows UD60x18.\\nerror PRBMathUD60x18__GmOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when the input is less than 1.\\nerror PRBMathUD60x18__LogInputTooSmall(uint256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows UD60x18.\\nerror PRBMathUD60x18__SqrtOverflow(uint256 x);\\n\\n/// @notice Emitted when subtraction underflows UD60x18.\\nerror PRBMathUD60x18__SubUnderflow(uint256 x, uint256 y);\\n\\n/// @dev Common mathematical functions used in both PRBMathSD59x18 and PRBMathUD60x18. Note that this shared library\\n/// does not always assume the signed 59.18-decimal fixed-point or the unsigned 60.18-decimal fixed-point\\n/// representation. When it does not, it is explicitly mentioned in the NatSpec documentation.\\nlibrary PRBMath {\\n /// STRUCTS ///\\n\\n struct SD59x18 {\\n int256 value;\\n }\\n\\n struct UD60x18 {\\n uint256 value;\\n }\\n\\n /// STORAGE ///\\n\\n /// @dev How many trailing decimals can be represented.\\n uint256 internal constant SCALE = 1e18;\\n\\n /// @dev Largest power of two divisor of SCALE.\\n uint256 internal constant SCALE_LPOTD = 262144;\\n\\n /// @dev SCALE inverted mod 2^256.\\n uint256 internal constant SCALE_INVERSE =\\n 78156646155174841979727994598816262306175212592076161876661_508869554232690281;\\n\\n /// FUNCTIONS ///\\n\\n /// @notice Calculates the binary exponent of x using the binary fraction method.\\n /// @dev Has to use 192.64-bit fixed-point numbers.\\n /// See https://ethereum.stackexchange.com/a/96594/24693.\\n /// @param x The exponent as an unsigned 192.64-bit fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp2(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n // Start from 0.5 in the 192.64-bit fixed-point format.\\n result = 0x800000000000000000000000000000000000000000000000;\\n\\n // Multiply the result by root(2, 2^-i) when the bit at position i is 1. None of the intermediary results overflows\\n // because the initial result is 2^191 and all magic factors are less than 2^65.\\n if (x & 0x8000000000000000 > 0) {\\n result = (result * 0x16A09E667F3BCC909) >> 64;\\n }\\n if (x & 0x4000000000000000 > 0) {\\n result = (result * 0x1306FE0A31B7152DF) >> 64;\\n }\\n if (x & 0x2000000000000000 > 0) {\\n result = (result * 0x1172B83C7D517ADCE) >> 64;\\n }\\n if (x & 0x1000000000000000 > 0) {\\n result = (result * 0x10B5586CF9890F62A) >> 64;\\n }\\n if (x & 0x800000000000000 > 0) {\\n result = (result * 0x1059B0D31585743AE) >> 64;\\n }\\n if (x & 0x400000000000000 > 0) {\\n result = (result * 0x102C9A3E778060EE7) >> 64;\\n }\\n if (x & 0x200000000000000 > 0) {\\n result = (result * 0x10163DA9FB33356D8) >> 64;\\n }\\n if (x & 0x100000000000000 > 0) {\\n result = (result * 0x100B1AFA5ABCBED61) >> 64;\\n }\\n if (x & 0x80000000000000 > 0) {\\n result = (result * 0x10058C86DA1C09EA2) >> 64;\\n }\\n if (x & 0x40000000000000 > 0) {\\n result = (result * 0x1002C605E2E8CEC50) >> 64;\\n }\\n if (x & 0x20000000000000 > 0) {\\n result = (result * 0x100162F3904051FA1) >> 64;\\n }\\n if (x & 0x10000000000000 > 0) {\\n result = (result * 0x1000B175EFFDC76BA) >> 64;\\n }\\n if (x & 0x8000000000000 > 0) {\\n result = (result * 0x100058BA01FB9F96D) >> 64;\\n }\\n if (x & 0x4000000000000 > 0) {\\n result = (result * 0x10002C5CC37DA9492) >> 64;\\n }\\n if (x & 0x2000000000000 > 0) {\\n result = (result * 0x1000162E525EE0547) >> 64;\\n }\\n if (x & 0x1000000000000 > 0) {\\n result = (result * 0x10000B17255775C04) >> 64;\\n }\\n if (x & 0x800000000000 > 0) {\\n result = (result * 0x1000058B91B5BC9AE) >> 64;\\n }\\n if (x & 0x400000000000 > 0) {\\n result = (result * 0x100002C5C89D5EC6D) >> 64;\\n }\\n if (x & 0x200000000000 > 0) {\\n result = (result * 0x10000162E43F4F831) >> 64;\\n }\\n if (x & 0x100000000000 > 0) {\\n result = (result * 0x100000B1721BCFC9A) >> 64;\\n }\\n if (x & 0x80000000000 > 0) {\\n result = (result * 0x10000058B90CF1E6E) >> 64;\\n }\\n if (x & 0x40000000000 > 0) {\\n result = (result * 0x1000002C5C863B73F) >> 64;\\n }\\n if (x & 0x20000000000 > 0) {\\n result = (result * 0x100000162E430E5A2) >> 64;\\n }\\n if (x & 0x10000000000 > 0) {\\n result = (result * 0x1000000B172183551) >> 64;\\n }\\n if (x & 0x8000000000 > 0) {\\n result = (result * 0x100000058B90C0B49) >> 64;\\n }\\n if (x & 0x4000000000 > 0) {\\n result = (result * 0x10000002C5C8601CC) >> 64;\\n }\\n if (x & 0x2000000000 > 0) {\\n result = (result * 0x1000000162E42FFF0) >> 64;\\n }\\n if (x & 0x1000000000 > 0) {\\n result = (result * 0x10000000B17217FBB) >> 64;\\n }\\n if (x & 0x800000000 > 0) {\\n result = (result * 0x1000000058B90BFCE) >> 64;\\n }\\n if (x & 0x400000000 > 0) {\\n result = (result * 0x100000002C5C85FE3) >> 64;\\n }\\n if (x & 0x200000000 > 0) {\\n result = (result * 0x10000000162E42FF1) >> 64;\\n }\\n if (x & 0x100000000 > 0) {\\n result = (result * 0x100000000B17217F8) >> 64;\\n }\\n if (x & 0x80000000 > 0) {\\n result = (result * 0x10000000058B90BFC) >> 64;\\n }\\n if (x & 0x40000000 > 0) {\\n result = (result * 0x1000000002C5C85FE) >> 64;\\n }\\n if (x & 0x20000000 > 0) {\\n result = (result * 0x100000000162E42FF) >> 64;\\n }\\n if (x & 0x10000000 > 0) {\\n result = (result * 0x1000000000B17217F) >> 64;\\n }\\n if (x & 0x8000000 > 0) {\\n result = (result * 0x100000000058B90C0) >> 64;\\n }\\n if (x & 0x4000000 > 0) {\\n result = (result * 0x10000000002C5C860) >> 64;\\n }\\n if (x & 0x2000000 > 0) {\\n result = (result * 0x1000000000162E430) >> 64;\\n }\\n if (x & 0x1000000 > 0) {\\n result = (result * 0x10000000000B17218) >> 64;\\n }\\n if (x & 0x800000 > 0) {\\n result = (result * 0x1000000000058B90C) >> 64;\\n }\\n if (x & 0x400000 > 0) {\\n result = (result * 0x100000000002C5C86) >> 64;\\n }\\n if (x & 0x200000 > 0) {\\n result = (result * 0x10000000000162E43) >> 64;\\n }\\n if (x & 0x100000 > 0) {\\n result = (result * 0x100000000000B1721) >> 64;\\n }\\n if (x & 0x80000 > 0) {\\n result = (result * 0x10000000000058B91) >> 64;\\n }\\n if (x & 0x40000 > 0) {\\n result = (result * 0x1000000000002C5C8) >> 64;\\n }\\n if (x & 0x20000 > 0) {\\n result = (result * 0x100000000000162E4) >> 64;\\n }\\n if (x & 0x10000 > 0) {\\n result = (result * 0x1000000000000B172) >> 64;\\n }\\n if (x & 0x8000 > 0) {\\n result = (result * 0x100000000000058B9) >> 64;\\n }\\n if (x & 0x4000 > 0) {\\n result = (result * 0x10000000000002C5D) >> 64;\\n }\\n if (x & 0x2000 > 0) {\\n result = (result * 0x1000000000000162E) >> 64;\\n }\\n if (x & 0x1000 > 0) {\\n result = (result * 0x10000000000000B17) >> 64;\\n }\\n if (x & 0x800 > 0) {\\n result = (result * 0x1000000000000058C) >> 64;\\n }\\n if (x & 0x400 > 0) {\\n result = (result * 0x100000000000002C6) >> 64;\\n }\\n if (x & 0x200 > 0) {\\n result = (result * 0x10000000000000163) >> 64;\\n }\\n if (x & 0x100 > 0) {\\n result = (result * 0x100000000000000B1) >> 64;\\n }\\n if (x & 0x80 > 0) {\\n result = (result * 0x10000000000000059) >> 64;\\n }\\n if (x & 0x40 > 0) {\\n result = (result * 0x1000000000000002C) >> 64;\\n }\\n if (x & 0x20 > 0) {\\n result = (result * 0x10000000000000016) >> 64;\\n }\\n if (x & 0x10 > 0) {\\n result = (result * 0x1000000000000000B) >> 64;\\n }\\n if (x & 0x8 > 0) {\\n result = (result * 0x10000000000000006) >> 64;\\n }\\n if (x & 0x4 > 0) {\\n result = (result * 0x10000000000000003) >> 64;\\n }\\n if (x & 0x2 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n if (x & 0x1 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n\\n // We're doing two things at the same time:\\n //\\n // 1. Multiply the result by 2^n + 1, where \\\"2^n\\\" is the integer part and the one is added to account for\\n // the fact that we initially set the result to 0.5. This is accomplished by subtracting from 191\\n // rather than 192.\\n // 2. Convert the result to the unsigned 60.18-decimal fixed-point format.\\n //\\n // This works because 2^(191-ip) = 2^ip / 2^191, where \\\"ip\\\" is the integer part \\\"2^n\\\".\\n result *= SCALE;\\n result >>= (191 - (x >> 64));\\n }\\n }\\n\\n /// @notice Finds the zero-based index of the first one in the binary representation of x.\\n /// @dev See the note on msb in the \\\"Find First Set\\\" Wikipedia article https://en.wikipedia.org/wiki/Find_first_set\\n /// @param x The uint256 number for which to find the index of the most significant bit.\\n /// @return msb The index of the most significant bit as an uint256.\\n function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\\n if (x >= 2**128) {\\n x >>= 128;\\n msb += 128;\\n }\\n if (x >= 2**64) {\\n x >>= 64;\\n msb += 64;\\n }\\n if (x >= 2**32) {\\n x >>= 32;\\n msb += 32;\\n }\\n if (x >= 2**16) {\\n x >>= 16;\\n msb += 16;\\n }\\n if (x >= 2**8) {\\n x >>= 8;\\n msb += 8;\\n }\\n if (x >= 2**4) {\\n x >>= 4;\\n msb += 4;\\n }\\n if (x >= 2**2) {\\n x >>= 2;\\n msb += 2;\\n }\\n if (x >= 2**1) {\\n // No need to shift x any more.\\n msb += 1;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.\\n ///\\n /// Requirements:\\n /// - The denominator cannot be zero.\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The multiplicand as an uint256.\\n /// @param y The multiplier as an uint256.\\n /// @param denominator The divisor as an uint256.\\n /// @return result The result as an uint256.\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n unchecked {\\n result = prod0 / denominator;\\n }\\n return result;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n if (prod1 >= denominator) {\\n revert PRBMath__MulDivOverflow(prod1, denominator);\\n }\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n unchecked {\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 lpotdod = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by lpotdod.\\n denominator := div(denominator, lpotdod)\\n\\n // Divide [prod1 prod0] by lpotdod.\\n prod0 := div(prod0, lpotdod)\\n\\n // Flip lpotdod such that it is 2^256 / lpotdod. If lpotdod is zero, then it becomes one.\\n lpotdod := add(div(sub(0, lpotdod), lpotdod), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * lpotdod;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f71e18) with full precision.\\n ///\\n /// @dev Variant of \\\"mulDiv\\\" with constant folding, i.e. in which the denominator is always 1e18. Before returning the\\n /// final result, we add 1 if (x * y) % SCALE >= HALF_SCALE. Without this, 6.6e-19 would be truncated to 0 instead of\\n /// being rounded to 1e-18. See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717.\\n ///\\n /// Requirements:\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - The body is purposely left uncommented; see the NatSpec comments in \\\"PRBMath.mulDiv\\\" to understand how this works.\\n /// - It is assumed that the result can never be type(uint256).max when x and y solve the following two equations:\\n /// 1. x * y = type(uint256).max * SCALE\\n /// 2. (x * y) % SCALE >= SCALE / 2\\n ///\\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function mulDivFixedPoint(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n uint256 prod0;\\n uint256 prod1;\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n if (prod1 >= SCALE) {\\n revert PRBMath__MulDivFixedPointOverflow(prod1);\\n }\\n\\n uint256 remainder;\\n uint256 roundUpUnit;\\n assembly {\\n remainder := mulmod(x, y, SCALE)\\n roundUpUnit := gt(remainder, 499999999999999999)\\n }\\n\\n if (prod1 == 0) {\\n unchecked {\\n result = (prod0 / SCALE) + roundUpUnit;\\n return result;\\n }\\n }\\n\\n assembly {\\n result := add(\\n mul(\\n or(\\n div(sub(prod0, remainder), SCALE_LPOTD),\\n mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, SCALE_LPOTD), SCALE_LPOTD), 1))\\n ),\\n SCALE_INVERSE\\n ),\\n roundUpUnit\\n )\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev An extension of \\\"mulDiv\\\" for signed numbers. Works by computing the signs and the absolute values separately.\\n ///\\n /// Requirements:\\n /// - None of the inputs can be type(int256).min.\\n /// - The result must fit within int256.\\n ///\\n /// @param x The multiplicand as an int256.\\n /// @param y The multiplier as an int256.\\n /// @param denominator The divisor as an int256.\\n /// @return result The result as an int256.\\n function mulDivSigned(\\n int256 x,\\n int256 y,\\n int256 denominator\\n ) internal pure returns (int256 result) {\\n if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {\\n revert PRBMath__MulDivSignedInputTooSmall();\\n }\\n\\n // Get hold of the absolute values of x, y and the denominator.\\n uint256 ax;\\n uint256 ay;\\n uint256 ad;\\n unchecked {\\n ax = x < 0 ? uint256(-x) : uint256(x);\\n ay = y < 0 ? uint256(-y) : uint256(y);\\n ad = denominator < 0 ? uint256(-denominator) : uint256(denominator);\\n }\\n\\n // Compute the absolute value of (x*y)\\u00f7denominator. The result must fit within int256.\\n uint256 rAbs = mulDiv(ax, ay, ad);\\n if (rAbs > uint256(type(int256).max)) {\\n revert PRBMath__MulDivSignedOverflow(rAbs);\\n }\\n\\n // Get the signs of x, y and the denominator.\\n uint256 sx;\\n uint256 sy;\\n uint256 sd;\\n assembly {\\n sx := sgt(x, sub(0, 1))\\n sy := sgt(y, sub(0, 1))\\n sd := sgt(denominator, sub(0, 1))\\n }\\n\\n // XOR over sx, sy and sd. This is checking whether there are one or three negative signs in the inputs.\\n // If yes, the result should be negative.\\n result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs);\\n }\\n\\n /// @notice Calculates the square root of x, rounding down.\\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The uint256 number for which to calculate the square root.\\n /// @return result The result as an uint256.\\n function sqrt(uint256 x) internal pure returns (uint256 result) {\\n if (x == 0) {\\n return 0;\\n }\\n\\n // Set the initial guess to the closest power of two that is higher than x.\\n uint256 xAux = uint256(x);\\n result = 1;\\n if (xAux >= 0x100000000000000000000000000000000) {\\n xAux >>= 128;\\n result <<= 64;\\n }\\n if (xAux >= 0x10000000000000000) {\\n xAux >>= 64;\\n result <<= 32;\\n }\\n if (xAux >= 0x100000000) {\\n xAux >>= 32;\\n result <<= 16;\\n }\\n if (xAux >= 0x10000) {\\n xAux >>= 16;\\n result <<= 8;\\n }\\n if (xAux >= 0x100) {\\n xAux >>= 8;\\n result <<= 4;\\n }\\n if (xAux >= 0x10) {\\n xAux >>= 4;\\n result <<= 2;\\n }\\n if (xAux >= 0x8) {\\n result <<= 1;\\n }\\n\\n // The operations can never overflow because the result is max 2^127 when it enters this block.\\n unchecked {\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1; // Seven iterations should be enough\\n uint256 roundedDownResult = x / result;\\n return result >= roundedDownResult ? roundedDownResult : result;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x62cbabae4910e168e99b9c2c3e3b5c9c7ad5e7abd961dcc63b7ea3d83d8ea87e\",\"license\":\"Unlicense\"}},\"version\":1}", + "metadata": "{\"compiler\":{\"version\":\"0.8.16+commit.07a7930e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_baseWeightCurrency\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBOperatorStore\",\"name\":\"_operatorStore\",\"type\":\"address\"},{\"internalType\":\"contract IJBProjects\",\"name\":\"_projects\",\"type\":\"address\"},{\"internalType\":\"contract IJBDirectory\",\"name\":\"_directory\",\"type\":\"address\"},{\"internalType\":\"contract IJBSplitsStore\",\"name\":\"_splitsStore\",\"type\":\"address\"},{\"internalType\":\"contract IJBPrices\",\"name\":\"_prices\",\"type\":\"address\"},{\"internalType\":\"contract IJBSingleTokenPaymentTerminalStore\",\"name\":\"_store\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"FEE_TOO_HIGH\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INADEQUATE_DISTRIBUTION_AMOUNT\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INADEQUATE_RECLAIM_AMOUNT\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INADEQUATE_TOKEN_COUNT\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NO_MSG_VALUE_ALLOWED\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PAY_TO_ZERO_ADDRESS\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"prod1\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"denominator\",\"type\":\"uint256\"}],\"name\":\"PRBMath__MulDivOverflow\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PROJECT_TERMINAL_MISMATCH\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"REDEEM_TO_ZERO_ADDRESS\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TERMINAL_IN_SPLIT_ZERO_ADDRESS\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TERMINAL_TOKENS_INCOMPATIBLE\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UNAUTHORIZED\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"refundedFees\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AddToBalance\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IJBPayDelegate\",\"name\":\"delegate\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"currentFundingCycleConfiguration\",\"type\":\"uint256\"},{\"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\"},{\"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\":\"forwardedAmount\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"projectTokenCount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"preferClaimedTokens\",\"type\":\"bool\"},{\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"struct JBDidPayData\",\"name\":\"data\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"delegatedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"DelegateDidPay\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IJBRedemptionDelegate\",\"name\":\"delegate\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"currentFundingCycleConfiguration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"projectTokenCount\",\"type\":\"uint256\"},{\"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\":\"reclaimedAmount\",\"type\":\"tuple\"},{\"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\":\"forwardedAmount\",\"type\":\"tuple\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"struct JBDidRedeemData\",\"name\":\"data\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"delegatedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"DelegateDidRedeem\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleConfiguration\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleNumber\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"distributedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"beneficiaryDistributionAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"DistributePayouts\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"domain\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"group\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"preferClaimed\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"preferAddToBalance\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"percent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"lockedUntil\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBSplitAllocator\",\"name\":\"allocator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"struct JBSplit\",\"name\":\"split\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"DistributeToPayoutSplit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"feeDiscount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"HoldFee\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"contract IJBPaymentTerminal\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Migrate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleConfiguration\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleNumber\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"beneficiaryTokenCount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Pay\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"wasHeld\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"ProcessFee\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleConfiguration\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleNumber\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenCount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"reclaimedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"RedeemTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"refundedFees\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"leftoverAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"RefundHeldFees\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"SetFee\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IJBFeeGauge\",\"name\":\"feeGauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"SetFeeGauge\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"addrs\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"flag\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"SetFeelessAddress\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleConfiguration\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleNumber\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"distributedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"netDistributedamount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"UseAllowance\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"}],\"name\":\"acceptsToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"addToBalanceOf\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"baseWeightCurrency\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currency\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"currencyForToken\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"}],\"name\":\"currentEthOverflowOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"decimalsForToken\",\"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\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_currency\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_minReturnedTokens\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"}],\"name\":\"distributePayoutsOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"netLeftoverDistributionAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"feeGauge\",\"outputs\":[{\"internalType\":\"contract IJBFeeGauge\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"}],\"name\":\"heldFeesOf\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"fee\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"feeDiscount\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"internalType\":\"struct JBFee[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isFeelessAddress\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBPaymentTerminal\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"migrate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"operatorStore\",\"outputs\":[{\"internalType\":\"contract IJBOperatorStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_minReturnedTokens\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"_preferClaimedTokens\",\"type\":\"bool\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"pay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"payoutSplitsGroup\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"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\"}],\"name\":\"processFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"projects\",\"outputs\":[{\"internalType\":\"contract IJBProjects\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_holder\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_tokenCount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_minReturnedTokens\",\"type\":\"uint256\"},{\"internalType\":\"address payable\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"redeemTokensOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"reclaimAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_fee\",\"type\":\"uint256\"}],\"name\":\"setFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IJBFeeGauge\",\"name\":\"_feeGauge\",\"type\":\"address\"}],\"name\":\"setFeeGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_flag\",\"type\":\"bool\"}],\"name\":\"setFeelessAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"splitsStore\",\"outputs\":[{\"internalType\":\"contract IJBSplitsStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"store\",\"outputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminalStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_currency\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_minReturnedTokens\",\"type\":\"uint256\"},{\"internalType\":\"address payable\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"}],\"name\":\"useAllowanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"netDistributedAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Inherits from - JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\",\"kind\":\"dev\",\"methods\":{\"acceptsToken(address,uint256)\":{\"params\":{\"_projectId\":\"The project ID to check for token acceptance.\",\"_token\":\"The token to check if this terminal accepts or not.\"},\"returns\":{\"_0\":\"The flag.\"}},\"addToBalanceOf(uint256,uint256,address,string,bytes)\":{\"params\":{\"_amount\":\"The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\",\"_memo\":\"A memo to pass along to the emitted event.\",\"_metadata\":\"Extra data to pass along to the emitted event.\",\"_projectId\":\"The ID of the project to which the funds received belong.\",\"_token\":\"The token being paid. This terminal ignores this property since it only manages one currency. \"}},\"constructor\":{\"params\":{\"_baseWeightCurrency\":\"The currency to base token issuance on.\",\"_directory\":\"A contract storing directories of terminals and controllers for each project.\",\"_operatorStore\":\"A contract storing operator assignments.\",\"_owner\":\"The address that will own this contract.\",\"_prices\":\"A contract that exposes price feeds.\",\"_projects\":\"A contract which mints ERC-721's that represent project ownership and transfers.\",\"_splitsStore\":\"A contract that stores splits for each project.\",\"_store\":\"A contract that stores the terminal's data.\"}},\"currencyForToken(address)\":{\"params\":{\"_token\":\"The token to check for the currency of.\"},\"returns\":{\"_0\":\"The currency index.\"}},\"currentEthOverflowOf(uint256)\":{\"details\":\"The current overflow is represented as a fixed point number with 18 decimals.\",\"params\":{\"_projectId\":\"The ID of the project to get overflow for.\"},\"returns\":{\"_0\":\"The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\"}},\"decimalsForToken(address)\":{\"params\":{\"_token\":\"The token to check for the decimals of.\"},\"returns\":{\"_0\":\"The number of decimals for the token.\"}},\"distributePayoutsOf(uint256,uint256,uint256,address,uint256,string)\":{\"details\":\"Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\",\"params\":{\"_amount\":\"The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\",\"_currency\":\"The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\",\"_memo\":\"A memo to pass along to the emitted event.\",\"_minReturnedTokens\":\"The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\",\"_projectId\":\"The ID of the project having its payouts distributed.\",\"_token\":\"The token being distributed. This terminal ignores this property since it only manages one token. \"},\"returns\":{\"netLeftoverDistributionAmount\":\"The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\"}},\"heldFeesOf(uint256)\":{\"params\":{\"_projectId\":\"The ID of the project for which fees are being held.\"},\"returns\":{\"_0\":\"An array of fees that are being held.\"}},\"migrate(uint256,address)\":{\"details\":\"Only a project's owner or a designated operator can migrate it.\",\"params\":{\"_projectId\":\"The ID of the project being migrated.\",\"_to\":\"The terminal contract that will gain the project's funds.\"},\"returns\":{\"balance\":\"The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pay(uint256,uint256,address,address,uint256,bool,string,bytes)\":{\"params\":{\"_amount\":\"The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\",\"_beneficiary\":\"The address to mint tokens for and pass along to the funding cycle's data source and delegate.\",\"_memo\":\"A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\",\"_metadata\":\"Bytes to send along to the data source, delegate, and emitted event, if provided.\",\"_minReturnedTokens\":\"The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\",\"_preferClaimedTokens\":\"A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\",\"_projectId\":\"The ID of the project being paid.\",\"_token\":\"The token being paid. This terminal ignores this property since it only manages one token. \"},\"returns\":{\"_0\":\"The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\"}},\"processFees(uint256)\":{\"details\":\"Only a project owner, an operator, or the contract's owner can process held fees.\",\"params\":{\"_projectId\":\"The ID of the project whos held fees should be processed.\"}},\"redeemTokensOf(address,uint256,uint256,address,uint256,address,string,bytes)\":{\"details\":\"Only a token holder or a designated operator can redeem its tokens.\",\"params\":{\"_beneficiary\":\"The address to send the terminal tokens to.\",\"_holder\":\"The account to redeem tokens for.\",\"_memo\":\"A memo to pass along to the emitted event.\",\"_metadata\":\"Bytes to send along to the data source, delegate, and emitted event, if provided.\",\"_minReturnedTokens\":\"The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\",\"_projectId\":\"The ID of the project to which the tokens being redeemed belong.\",\"_token\":\"The token being reclaimed. This terminal ignores this property since it only manages one token. \",\"_tokenCount\":\"The number of project tokens to redeem, as a fixed point number with 18 decimals.\"},\"returns\":{\"reclaimAmount\":\"The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"setFee(uint256)\":{\"details\":\"Only the owner of this contract can change the fee.\",\"params\":{\"_fee\":\"The new fee, out of MAX_FEE.\"}},\"setFeeGauge(address)\":{\"details\":\"Only the owner of this contract can change the fee gauge.\",\"params\":{\"_feeGauge\":\"The new fee gauge.\"}},\"setFeelessAddress(address,bool)\":{\"details\":\"Only the owner of this contract can set addresses as feeless.\",\"params\":{\"_address\":\"The address that can be paid towards while still bypassing fees.\",\"_flag\":\"A flag indicating whether the terminal should be feeless or not.\"}},\"supportsInterface(bytes4)\":{\"details\":\" See {IERC165-supportsInterface}.\",\"params\":{\"_interfaceId\":\"The ID of the interface to check for adherance to.\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"useAllowanceOf(uint256,uint256,uint256,address,uint256,address,string)\":{\"details\":\"Only a project's owner or a designated operator can use its allowance.Incurs the protocol fee.\",\"params\":{\"_amount\":\"The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\",\"_beneficiary\":\"The address to send the funds to.\",\"_currency\":\"The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\",\"_memo\":\"A memo to pass along to the emitted event.\",\"_minReturnedTokens\":\"The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\",\"_projectId\":\"The ID of the project to use the allowance of.\",\"_token\":\"The token being distributed. This terminal ignores this property since it only manages one token. \"},\"returns\":{\"netDistributedAmount\":\"The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\"}}},\"version\":1},\"userdoc\":{\"errors\":{\"PRBMath__MulDivOverflow(uint256,uint256)\":[{\"notice\":\"Emitted when the result overflows uint256.\"}]},\"kind\":\"user\",\"methods\":{\"acceptsToken(address,uint256)\":{\"notice\":\"A flag indicating if this terminal accepts the specified token.\"},\"addToBalanceOf(uint256,uint256,address,string,bytes)\":{\"notice\":\"Receives funds belonging to the specified project.\"},\"baseWeightCurrency()\":{\"notice\":\"The currency to base token issuance on.\"},\"currency()\":{\"notice\":\"The currency to use when resolving price feeds for this terminal.\"},\"currencyForToken(address)\":{\"notice\":\"The currency that should be used for the specified token.\"},\"currentEthOverflowOf(uint256)\":{\"notice\":\"Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\"},\"decimals()\":{\"notice\":\"The number of decimals the token fixed point amounts are expected to have.\"},\"decimalsForToken(address)\":{\"notice\":\"The decimals that should be used in fixed number accounting for the specified token.\"},\"directory()\":{\"notice\":\"The directory of terminals and controllers for projects.\"},\"distributePayoutsOf(uint256,uint256,uint256,address,uint256,string)\":{\"notice\":\"Distributes payouts for a project with the distribution limit of its current funding cycle.\"},\"fee()\":{\"notice\":\"The platform fee percent.\"},\"feeGauge()\":{\"notice\":\"The data source that returns a discount to apply to a project's fee.\"},\"heldFeesOf(uint256)\":{\"notice\":\"The fees that are currently being held to be processed later for each project.\"},\"isFeelessAddress(address)\":{\"notice\":\"Addresses that can be paid towards from this terminal without incurring a fee.\"},\"migrate(uint256,address)\":{\"notice\":\"Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\"},\"operatorStore()\":{\"notice\":\" A contract storing operator assignments.\"},\"pay(uint256,uint256,address,address,uint256,bool,string,bytes)\":{\"notice\":\"Contribute tokens to a project.\"},\"payoutSplitsGroup()\":{\"notice\":\"The group that payout splits coming from this terminal are identified by.\"},\"prices()\":{\"notice\":\"The contract that exposes price feeds.\"},\"processFees(uint256)\":{\"notice\":\"Process any fees that are being held for the project.\"},\"projects()\":{\"notice\":\"Mints ERC-721's that represent project ownership and transfers.\"},\"redeemTokensOf(address,uint256,uint256,address,uint256,address,string,bytes)\":{\"notice\":\"Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\"},\"setFee(uint256)\":{\"notice\":\"Allows the fee to be updated.\"},\"setFeeGauge(address)\":{\"notice\":\"Allows the fee gauge to be updated.\"},\"setFeelessAddress(address,bool)\":{\"notice\":\"Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\"},\"splitsStore()\":{\"notice\":\"The contract that stores splits for each project.\"},\"store()\":{\"notice\":\"The contract that stores and manages the terminal's data.\"},\"supportsInterface(bytes4)\":{\"notice\":\"Indicates if this contract adheres to the specified interface.\"},\"token()\":{\"notice\":\"The token that this terminal accepts.\"},\"useAllowanceOf(uint256,uint256,uint256,address,uint256,address,string)\":{\"notice\":\"Allows a project to send funds from its overflow up to the preconfigured allowance.\"}},\"notice\":\"Manages all inflows and outflows of ETH funds into the protocol ecosystem.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/JBETHPaymentTerminal.sol\":\"JBETHPaymentTerminal\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0x24e0364e503a9bbde94c715d26573a76f14cd2a202d45f96f52134ab806b67b9\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool _approved) external;\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x516a22876c1fab47f49b1bc22b4614491cd05338af8bd2e7b382da090a079990\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3777e696b62134e6177440dbe6e6601c0c156a443f57167194b67e75527439de\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"@paulrberg/contracts/math/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\nimport \\\"prb-math/contracts/PRBMath.sol\\\";\\n\",\"keccak256\":\"0x42821345981bc0434a90ba2268a2f5278dfe9e38166981d72fc7f3b776a29495\",\"license\":\"Unlicense\"},\"contracts/JBETHPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport '@openzeppelin/contracts/utils/Address.sol';\\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\\nimport './libraries/JBSplitsGroups.sol';\\n\\n/**\\n @notice\\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\\n\\n @dev\\n Inherits from -\\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\\n*/\\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\\n //*********************************************************************//\\n // -------------------------- internal views ------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Checks the balance of tokens in this contract.\\n\\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\\n */\\n function _balance() internal view override returns (uint256) {\\n return address(this).balance;\\n }\\n\\n //*********************************************************************//\\n // -------------------------- constructor ---------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @param _baseWeightCurrency The currency to base token issuance on.\\n @param _operatorStore A contract storing operator assignments.\\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\\n @param _directory A contract storing directories of terminals and controllers for each project.\\n @param _splitsStore A contract that stores splits for each project.\\n @param _prices A contract that exposes price feeds.\\n @param _store A contract that stores the terminal's data.\\n @param _owner The address that will own this contract.\\n */\\n constructor(\\n uint256 _baseWeightCurrency,\\n IJBOperatorStore _operatorStore,\\n IJBProjects _projects,\\n IJBDirectory _directory,\\n IJBSplitsStore _splitsStore,\\n IJBPrices _prices,\\n IJBSingleTokenPaymentTerminalStore _store,\\n address _owner\\n )\\n JBPayoutRedemptionPaymentTerminal(\\n JBTokens.GAS_TOKEN,\\n 18, // 18 decimals.\\n JBCurrencies.GAS_CURRENCY,\\n _baseWeightCurrency,\\n JBSplitsGroups.ETH_PAYOUT,\\n _operatorStore,\\n _projects,\\n _directory,\\n _splitsStore,\\n _prices,\\n _store,\\n _owner\\n )\\n // solhint-disable-next-line no-empty-blocks\\n {\\n\\n }\\n\\n //*********************************************************************//\\n // ---------------------- internal transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Transfers tokens.\\n\\n @param _from The address from which the transfer should originate.\\n @param _to The address to which the transfer should go.\\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\\n */\\n function _transferFrom(\\n address _from,\\n address payable _to,\\n uint256 _amount\\n ) internal override {\\n _from; // Prevents unused var compiler and natspec complaints.\\n\\n Address.sendValue(_to, _amount);\\n }\\n}\\n\",\"keccak256\":\"0x6afb443f7efddb2ecd7023237f6e1684c4281a1fad43e4e1b34fa0d50b407384\",\"license\":\"MIT\"},\"contracts/abstract/JBOperatable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport './../interfaces/IJBOperatable.sol';\\n\\n/** \\n @notice\\n Modifiers to allow access to functions based on the message sender's operator status.\\n\\n @dev\\n Adheres to -\\n IJBOperatable: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n*/\\nabstract contract JBOperatable is IJBOperatable {\\n //*********************************************************************//\\n // --------------------------- custom errors -------------------------- //\\n //*********************************************************************//\\n error UNAUTHORIZED();\\n\\n //*********************************************************************//\\n // ---------------------------- modifiers ---------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Only allows the speficied account or an operator of the account to proceed. \\n\\n @param _account The account to check for.\\n @param _domain The domain namespace to look for an operator within. \\n @param _permissionIndex The index of the permission to check for. \\n */\\n modifier requirePermission(\\n address _account,\\n uint256 _domain,\\n uint256 _permissionIndex\\n ) {\\n _requirePermission(_account, _domain, _permissionIndex);\\n _;\\n }\\n\\n /** \\n @notice\\n Only allows the speficied account, an operator of the account to proceed, or a truthy override flag. \\n\\n @param _account The account to check for.\\n @param _domain The domain namespace to look for an operator within. \\n @param _permissionIndex The index of the permission to check for. \\n @param _override A condition to force allowance for.\\n */\\n modifier requirePermissionAllowingOverride(\\n address _account,\\n uint256 _domain,\\n uint256 _permissionIndex,\\n bool _override\\n ) {\\n _requirePermissionAllowingOverride(_account, _domain, _permissionIndex, _override);\\n _;\\n }\\n\\n //*********************************************************************//\\n // ---------------- public immutable stored properties --------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n A contract storing operator assignments.\\n */\\n IJBOperatorStore public immutable override operatorStore;\\n\\n //*********************************************************************//\\n // -------------------------- constructor ---------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @param _operatorStore A contract storing operator assignments.\\n */\\n constructor(IJBOperatorStore _operatorStore) {\\n operatorStore = _operatorStore;\\n }\\n\\n //*********************************************************************//\\n // -------------------------- internal views ------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Require the message sender is either the account or has the specified permission.\\n\\n @param _account The account to allow.\\n @param _domain The domain namespace within which the permission index will be checked.\\n @param _permissionIndex The permission index that an operator must have within the specified domain to be allowed.\\n */\\n function _requirePermission(\\n address _account,\\n uint256 _domain,\\n uint256 _permissionIndex\\n ) internal view {\\n if (\\n msg.sender != _account &&\\n !operatorStore.hasPermission(msg.sender, _account, _domain, _permissionIndex) &&\\n !operatorStore.hasPermission(msg.sender, _account, 0, _permissionIndex)\\n ) revert UNAUTHORIZED();\\n }\\n\\n /** \\n @notice\\n Require the message sender is either the account, has the specified permission, or the override condition is true.\\n\\n @param _account The account to allow.\\n @param _domain The domain namespace within which the permission index will be checked.\\n @param _domain The permission index that an operator must have within the specified domain to be allowed.\\n @param _override The override condition to allow.\\n */\\n function _requirePermissionAllowingOverride(\\n address _account,\\n uint256 _domain,\\n uint256 _permissionIndex,\\n bool _override\\n ) internal view {\\n if (\\n !_override &&\\n msg.sender != _account &&\\n !operatorStore.hasPermission(msg.sender, _account, _domain, _permissionIndex) &&\\n !operatorStore.hasPermission(msg.sender, _account, 0, _permissionIndex)\\n ) revert UNAUTHORIZED();\\n }\\n}\\n\",\"keccak256\":\"0x9e62cac5c464eb973f881cf6c373b95aab31d2ddbeb048ee7ad82b5c9ab28add\",\"license\":\"MIT\"},\"contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport '@openzeppelin/contracts/access/Ownable.sol';\\nimport '@paulrberg/contracts/math/PRBMath.sol';\\nimport './../interfaces/IJBController.sol';\\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal.sol';\\nimport './../libraries/JBConstants.sol';\\nimport './../libraries/JBCurrencies.sol';\\nimport './../libraries/JBFixedPointNumber.sol';\\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\\nimport './../libraries/JBOperations.sol';\\nimport './../libraries/JBTokens.sol';\\nimport './../structs/JBPayDelegateAllocation.sol';\\nimport './../structs/JBTokenAmount.sol';\\nimport './JBOperatable.sol';\\nimport './JBSingleTokenPaymentTerminal.sol';\\n\\n/**\\n @notice\\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\\n\\n @dev\\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\\n\\n @dev\\n Adheres to -\\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n\\n @dev\\n Inherits from -\\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\\n*/\\nabstract contract JBPayoutRedemptionPaymentTerminal is\\n JBSingleTokenPaymentTerminal,\\n JBOperatable,\\n Ownable,\\n IJBPayoutRedemptionPaymentTerminal\\n{\\n // A library that parses the packed funding cycle metadata into a friendlier format.\\n using JBFundingCycleMetadataResolver for JBFundingCycle;\\n\\n //*********************************************************************//\\n // --------------------------- custom errors ------------------------- //\\n //*********************************************************************//\\n error FEE_TOO_HIGH();\\n error INADEQUATE_DISTRIBUTION_AMOUNT();\\n error INADEQUATE_RECLAIM_AMOUNT();\\n error INADEQUATE_TOKEN_COUNT();\\n error NO_MSG_VALUE_ALLOWED();\\n error PAY_TO_ZERO_ADDRESS();\\n error PROJECT_TERMINAL_MISMATCH();\\n error REDEEM_TO_ZERO_ADDRESS();\\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\\n error TERMINAL_TOKENS_INCOMPATIBLE();\\n\\n //*********************************************************************//\\n // ---------------------------- modifiers ---------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n A modifier that verifies this terminal is a terminal of provided project ID.\\n */\\n modifier isTerminalOf(uint256 _projectId) {\\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\\n _;\\n }\\n\\n //*********************************************************************//\\n // --------------------- internal stored constants ------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Maximum fee that can be set for a funding cycle configuration.\\n\\n @dev\\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\\n */\\n uint256 internal constant _FEE_CAP = 50_000_000;\\n\\n /**\\n @notice\\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\\n */\\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\\n\\n //*********************************************************************//\\n // --------------------- internal stored properties ------------------ //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Fees that are being held to be processed later.\\n\\n _projectId The ID of the project for which fees are being held.\\n */\\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\\n\\n //*********************************************************************//\\n // ---------------- public immutable stored properties --------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Mints ERC-721's that represent project ownership and transfers.\\n */\\n IJBProjects public immutable override projects;\\n\\n /**\\n @notice\\n The directory of terminals and controllers for projects.\\n */\\n IJBDirectory public immutable override directory;\\n\\n /**\\n @notice\\n The contract that stores splits for each project.\\n */\\n IJBSplitsStore public immutable override splitsStore;\\n\\n /**\\n @notice\\n The contract that exposes price feeds.\\n */\\n IJBPrices public immutable override prices;\\n\\n /**\\n @notice\\n The contract that stores and manages the terminal's data.\\n */\\n IJBSingleTokenPaymentTerminalStore public immutable override store;\\n\\n /**\\n @notice\\n The currency to base token issuance on.\\n\\n @dev\\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\\n */\\n uint256 public immutable override baseWeightCurrency;\\n\\n /**\\n @notice\\n The group that payout splits coming from this terminal are identified by.\\n */\\n uint256 public immutable override payoutSplitsGroup;\\n\\n //*********************************************************************//\\n // --------------------- public stored properties -------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The platform fee percent.\\n\\n @dev\\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\\n */\\n uint256 public override fee = 25_000_000; // 2.5%\\n\\n /**\\n @notice\\n The data source that returns a discount to apply to a project's fee.\\n */\\n IJBFeeGauge public override feeGauge;\\n\\n /**\\n @notice\\n Addresses that can be paid towards from this terminal without incurring a fee.\\n\\n @dev\\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\\n\\n _address The address that can be paid toward.\\n */\\n mapping(address => bool) public override isFeelessAddress;\\n\\n //*********************************************************************//\\n // ------------------------- external views -------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\\n\\n @dev\\n The current overflow is represented as a fixed point number with 18 decimals.\\n\\n @param _projectId The ID of the project to get overflow for.\\n\\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\\n */\\n function currentEthOverflowOf(uint256 _projectId)\\n external\\n view\\n virtual\\n override\\n returns (uint256)\\n {\\n // Get this terminal's current overflow.\\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\\n\\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\\n uint256 _adjustedOverflow = (decimals == 18)\\n ? _overflow\\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\\n\\n // Return the amount converted to ETH.\\n return\\n (currency == JBCurrencies.GAS_CURRENCY)\\n ? _adjustedOverflow\\n : PRBMath.mulDiv(\\n _adjustedOverflow,\\n 10**decimals,\\n prices.priceFor(currency, JBCurrencies.GAS_CURRENCY, decimals)\\n );\\n }\\n\\n /**\\n @notice\\n The fees that are currently being held to be processed later for each project.\\n\\n @param _projectId The ID of the project for which fees are being held.\\n\\n @return An array of fees that are being held.\\n */\\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\\n return _heldFeesOf[_projectId];\\n }\\n\\n //*********************************************************************//\\n // -------------------------- public views --------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Indicates if this contract adheres to the specified interface.\\n\\n @dev \\n See {IERC165-supportsInterface}.\\n\\n @param _interfaceId The ID of the interface to check for adherance to.\\n */\\n function supportsInterface(bytes4 _interfaceId)\\n public\\n view\\n virtual\\n override(JBSingleTokenPaymentTerminal, IERC165)\\n returns (bool)\\n {\\n return\\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\\n _interfaceId == type(IJBOperatable).interfaceId ||\\n super.supportsInterface(_interfaceId);\\n }\\n\\n //*********************************************************************//\\n // -------------------------- internal views ------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Checks the balance of tokens in this contract.\\n\\n @return The contract's balance.\\n */\\n function _balance() internal view virtual returns (uint256);\\n\\n //*********************************************************************//\\n // -------------------------- constructor ---------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @param _token The token that this terminal manages.\\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\\n @param _currency The currency that this terminal's token adheres to for price feeds.\\n @param _baseWeightCurrency The currency to base token issuance on.\\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\\n @param _operatorStore A contract storing operator assignments.\\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\\n @param _directory A contract storing directories of terminals and controllers for each project.\\n @param _splitsStore A contract that stores splits for each project.\\n @param _prices A contract that exposes price feeds.\\n @param _store A contract that stores the terminal's data.\\n @param _owner The address that will own this contract.\\n */\\n constructor(\\n // payable constructor save the gas used to check msg.value==0\\n address _token,\\n uint256 _decimals,\\n uint256 _currency,\\n uint256 _baseWeightCurrency,\\n uint256 _payoutSplitsGroup,\\n IJBOperatorStore _operatorStore,\\n IJBProjects _projects,\\n IJBDirectory _directory,\\n IJBSplitsStore _splitsStore,\\n IJBPrices _prices,\\n IJBSingleTokenPaymentTerminalStore _store,\\n address _owner\\n )\\n payable\\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\\n JBOperatable(_operatorStore)\\n {\\n baseWeightCurrency = _baseWeightCurrency;\\n payoutSplitsGroup = _payoutSplitsGroup;\\n projects = _projects;\\n directory = _directory;\\n splitsStore = _splitsStore;\\n prices = _prices;\\n store = _store;\\n\\n transferOwnership(_owner);\\n }\\n\\n //*********************************************************************//\\n // ---------------------- external transactions ---------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Contribute tokens to a project.\\n\\n @param _projectId The ID of the project being paid.\\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\\n\\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\\n */\\n function pay(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n // ETH shouldn't be sent if this terminal's token isn't ETH.\\n if (token != JBTokens.GAS_TOKEN) {\\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\\n\\n // Get a reference to the balance before receiving tokens.\\n uint256 _balanceBefore = _balance();\\n\\n // Transfer tokens to this terminal from the msg sender.\\n _transferFrom(msg.sender, payable(address(this)), _amount);\\n\\n // The amount should reflect the change in balance.\\n _amount = _balance() - _balanceBefore;\\n }\\n // If this terminal's token is ETH, override _amount with msg.value.\\n else _amount = msg.value;\\n\\n return\\n _pay(\\n _amount,\\n msg.sender,\\n _projectId,\\n _beneficiary,\\n _minReturnedTokens,\\n _preferClaimedTokens,\\n _memo,\\n _metadata\\n );\\n }\\n\\n /**\\n @notice\\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\\n\\n @dev\\n Only a token holder or a designated operator can redeem its tokens.\\n\\n @param _holder The account to redeem tokens for.\\n @param _projectId The ID of the project to which the tokens being redeemed belong.\\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\\n @param _beneficiary The address to send the terminal tokens to.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\\n\\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\\n */\\n function redeemTokensOf(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n address _token,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string memory _memo,\\n bytes memory _metadata\\n )\\n external\\n virtual\\n override\\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\\n returns (uint256 reclaimAmount)\\n {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n return\\n _redeemTokensOf(\\n _holder,\\n _projectId,\\n _tokenCount,\\n _minReturnedTokens,\\n _beneficiary,\\n _memo,\\n _metadata\\n );\\n }\\n\\n /**\\n @notice\\n Distributes payouts for a project with the distribution limit of its current funding cycle.\\n\\n @dev\\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\\n\\n @dev\\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\\n\\n @dev\\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\\n\\n @param _projectId The ID of the project having its payouts distributed.\\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\\n @param _memo A memo to pass along to the emitted event.\\n\\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\\n */\\n function distributePayoutsOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n address _token,\\n uint256 _minReturnedTokens,\\n string calldata _memo\\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\\n }\\n\\n /**\\n @notice\\n Allows a project to send funds from its overflow up to the preconfigured allowance.\\n\\n @dev\\n Only a project's owner or a designated operator can use its allowance.\\n\\n @dev\\n Incurs the protocol fee.\\n\\n @param _projectId The ID of the project to use the allowance of.\\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\\n @param _beneficiary The address to send the funds to.\\n @param _memo A memo to pass along to the emitted event.\\n\\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\\n */\\n function useAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n address _token,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string memory _memo\\n )\\n external\\n virtual\\n override\\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\\n returns (uint256 netDistributedAmount)\\n {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\\n }\\n\\n /**\\n @notice\\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\\n\\n @dev\\n Only a project's owner or a designated operator can migrate it.\\n\\n @param _projectId The ID of the project being migrated.\\n @param _to The terminal contract that will gain the project's funds.\\n\\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\\n */\\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\\n external\\n virtual\\n override\\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\\n returns (uint256 balance)\\n {\\n // The terminal being migrated to must accept the same token as this terminal.\\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\\n\\n // Record the migration in the store.\\n balance = store.recordMigration(_projectId);\\n\\n // Transfer the balance if needed.\\n if (balance > 0) {\\n // Trigger any inherited pre-transfer logic.\\n _beforeTransferTo(address(_to), balance);\\n\\n // If this terminal's token is ETH, send it in msg.value.\\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? balance : 0;\\n\\n // Withdraw the balance to transfer to the new terminal;\\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\\n }\\n\\n emit Migrate(_projectId, _to, balance, msg.sender);\\n }\\n\\n /**\\n @notice\\n Receives funds belonging to the specified project.\\n\\n @param _projectId The ID of the project to which the funds received belong.\\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Extra data to pass along to the emitted event.\\n */\\n function addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable virtual override isTerminalOf(_projectId) {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\\n if (token != JBTokens.GAS_TOKEN) {\\n // Amount must be greater than 0.\\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\\n\\n // Get a reference to the balance before receiving tokens.\\n uint256 _balanceBefore = _balance();\\n\\n // Transfer tokens to this terminal from the msg sender.\\n _transferFrom(msg.sender, payable(address(this)), _amount);\\n\\n // The amount should reflect the change in balance.\\n _amount = _balance() - _balanceBefore;\\n }\\n // If the terminal's token is ETH, override `_amount` with msg.value.\\n else _amount = msg.value;\\n\\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\\n }\\n\\n /**\\n @notice\\n Process any fees that are being held for the project.\\n\\n @dev\\n Only a project owner, an operator, or the contract's owner can process held fees.\\n\\n @param _projectId The ID of the project whos held fees should be processed.\\n */\\n function processFees(uint256 _projectId)\\n external\\n virtual\\n override\\n requirePermissionAllowingOverride(\\n projects.ownerOf(_projectId),\\n _projectId,\\n JBOperations.PROCESS_FEES,\\n msg.sender == owner()\\n )\\n {\\n // Get a reference to the project's held fees.\\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\\n\\n // Delete the held fees.\\n delete _heldFeesOf[_projectId];\\n\\n // Push array length in stack\\n uint256 _heldFeeLength = _heldFees.length;\\n\\n // Process each fee.\\n for (uint256 _i; _i < _heldFeeLength; ) {\\n // Get the fee amount.\\n uint256 _amount = _feeAmount(\\n _heldFees[_i].amount,\\n _heldFees[_i].fee,\\n _heldFees[_i].feeDiscount\\n );\\n\\n // Process the fee.\\n _processFee(_amount, _heldFees[_i].beneficiary);\\n\\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n\\n /**\\n @notice\\n Allows the fee to be updated.\\n\\n @dev\\n Only the owner of this contract can change the fee.\\n\\n @param _fee The new fee, out of MAX_FEE.\\n */\\n function setFee(uint256 _fee) external virtual override onlyOwner {\\n // The provided fee must be within the max.\\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\\n\\n // Store the new fee.\\n fee = _fee;\\n\\n emit SetFee(_fee, msg.sender);\\n }\\n\\n /**\\n @notice\\n Allows the fee gauge to be updated.\\n\\n @dev\\n Only the owner of this contract can change the fee gauge.\\n\\n @param _feeGauge The new fee gauge.\\n */\\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\\n // Store the new fee gauge.\\n feeGauge = _feeGauge;\\n\\n emit SetFeeGauge(_feeGauge, msg.sender);\\n }\\n\\n /**\\n @notice\\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\\n\\n @dev\\n Only the owner of this contract can set addresses as feeless.\\n\\n @param _address The address that can be paid towards while still bypassing fees.\\n @param _flag A flag indicating whether the terminal should be feeless or not.\\n */\\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\\n // Set the flag value.\\n isFeelessAddress[_address] = _flag;\\n\\n emit SetFeelessAddress(_address, _flag, msg.sender);\\n }\\n\\n //*********************************************************************//\\n // ---------------------- internal transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Transfers tokens.\\n\\n @param _from The address from which the transfer should originate.\\n @param _to The address to which the transfer should go.\\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\\n */\\n function _transferFrom(\\n address _from,\\n address payable _to,\\n uint256 _amount\\n ) internal virtual {\\n _from; // Prevents unused var compiler and natspec complaints.\\n _to; // Prevents unused var compiler and natspec complaints.\\n _amount; // Prevents unused var compiler and natspec complaints.\\n }\\n\\n /** \\n @notice\\n Logic to be triggered before transferring tokens from this terminal.\\n\\n @param _to The address to which the transfer is going.\\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\\n */\\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\\n _to; // Prevents unused var compiler and natspec complaints.\\n _amount; // Prevents unused var compiler and natspec complaints.\\n }\\n\\n /**\\n @notice\\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\\n\\n @dev\\n Only a token holder or a designated operator can redeem its tokens.\\n\\n @param _holder The account to redeem tokens for.\\n @param _projectId The ID of the project to which the tokens being redeemed belong.\\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\\n @param _beneficiary The address to send the terminal tokens to.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\\n\\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\\n */\\n function _redeemTokensOf(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string memory _memo,\\n bytes memory _metadata\\n ) internal returns (uint256 reclaimAmount) {\\n // Can't send reclaimed funds to the zero address.\\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\\n\\n // Define variables that will be needed outside the scoped section below.\\n // Keep a reference to the funding cycle during which the redemption is being made.\\n JBFundingCycle memory _fundingCycle;\\n\\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\\n {\\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\\n\\n // Record the redemption.\\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\\n _holder,\\n _projectId,\\n _tokenCount,\\n _memo,\\n _metadata\\n );\\n\\n // The amount being reclaimed must be at least as much as was expected.\\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\\n\\n // Burn the project tokens.\\n if (_tokenCount > 0)\\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\\n _holder,\\n _projectId,\\n _tokenCount,\\n '',\\n false\\n );\\n\\n // If delegate allocations were specified by the data source, fulfill them.\\n if (_delegateAllocations.length != 0) {\\n // Keep a reference to the token amount being forwarded to the delegate.\\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\\n\\n JBDidRedeemData memory _data = JBDidRedeemData(\\n _holder,\\n _projectId,\\n _fundingCycle.configuration,\\n _tokenCount,\\n JBTokenAmount(token, reclaimAmount, decimals, currency),\\n _forwardedAmount,\\n _beneficiary,\\n _memo,\\n _metadata\\n );\\n\\n uint256 _numDelegates = _delegateAllocations.length;\\n\\n for (uint256 _i; _i < _numDelegates; ) {\\n // Get a reference to the delegate being iterated on.\\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\\n\\n // Trigger any inherited pre-transfer logic.\\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\\n\\n // Keep track of the msg.value to use in the delegate call\\n uint256 _payableValue;\\n\\n // If this terminal's token is ETH, send it in msg.value.\\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\\n\\n // Pass the correct token forwardedAmount to the delegate\\n _data.forwardedAmount.value = _delegateAllocation.amount;\\n\\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\\n\\n emit DelegateDidRedeem(\\n _delegateAllocation.delegate,\\n _data,\\n _delegateAllocation.amount,\\n msg.sender\\n );\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n }\\n\\n // Send the reclaimed funds to the beneficiary.\\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\\n\\n emit RedeemTokens(\\n _fundingCycle.configuration,\\n _fundingCycle.number,\\n _projectId,\\n _holder,\\n _beneficiary,\\n _tokenCount,\\n reclaimAmount,\\n _memo,\\n _metadata,\\n msg.sender\\n );\\n }\\n\\n /**\\n @notice\\n Distributes payouts for a project with the distribution limit of its current funding cycle.\\n\\n @dev\\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\\n\\n @dev\\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\\n\\n @dev\\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\\n\\n @param _projectId The ID of the project having its payouts distributed.\\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\\n @param _memo A memo to pass along to the emitted event.\\n\\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\\n */\\n function _distributePayoutsOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n uint256 _minReturnedTokens,\\n string calldata _memo\\n ) internal returns (uint256 netLeftoverDistributionAmount) {\\n // Record the distribution.\\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\\n _projectId,\\n _amount,\\n _currency\\n );\\n\\n // The amount being distributed must be at least as much as was expected.\\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\\n\\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\\n // and receive any extra distributable funds not allocated to payout splits.\\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\\n\\n // Define variables that will be needed outside the scoped section below.\\n // Keep a reference to the fee amount that was paid.\\n uint256 _fee;\\n\\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\\n {\\n // Get the amount of discount that should be applied to any fees taken.\\n // If the fee is zero, set the discount to 100% for convenience.\\n uint256 _feeDiscount = fee == 0\\n ? JBConstants.MAX_FEE_DISCOUNT\\n : _currentFeeDiscount(_projectId);\\n\\n // The amount distributed that is eligible for incurring fees.\\n uint256 _feeEligibleDistributionAmount;\\n\\n // The amount leftover after distributing to the splits.\\n uint256 _leftoverDistributionAmount;\\n\\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\\n _projectId,\\n _fundingCycle.configuration,\\n payoutSplitsGroup,\\n _distributedAmount,\\n _feeDiscount\\n );\\n\\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\\n unchecked {\\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\\n }\\n }\\n\\n // Take the fee.\\n _fee = _feeEligibleDistributionAmount != 0\\n ? _takeFeeFrom(\\n _projectId,\\n _fundingCycle,\\n _feeEligibleDistributionAmount,\\n _projectOwner,\\n _feeDiscount\\n )\\n : 0;\\n\\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\\n if (_leftoverDistributionAmount != 0) {\\n // Subtract the fee from the net leftover amount.\\n netLeftoverDistributionAmount =\\n _leftoverDistributionAmount -\\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\\n\\n // Transfer the amount to the project owner.\\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\\n }\\n }\\n\\n emit DistributePayouts(\\n _fundingCycle.configuration,\\n _fundingCycle.number,\\n _projectId,\\n _projectOwner,\\n _amount,\\n _distributedAmount,\\n _fee,\\n netLeftoverDistributionAmount,\\n _memo,\\n msg.sender\\n );\\n }\\n\\n /**\\n @notice\\n Allows a project to send funds from its overflow up to the preconfigured allowance.\\n\\n @dev\\n Only a project's owner or a designated operator can use its allowance.\\n\\n @dev\\n Incurs the protocol fee.\\n\\n @param _projectId The ID of the project to use the allowance of.\\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\\n @param _beneficiary The address to send the funds to.\\n @param _memo A memo to pass along to the emitted event.\\n\\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\\n */\\n function _useAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string memory _memo\\n ) internal returns (uint256 netDistributedAmount) {\\n // Record the use of the allowance.\\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\\n _projectId,\\n _amount,\\n _currency\\n );\\n\\n // The amount being withdrawn must be at least as much as was expected.\\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\\n\\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\\n {\\n // Keep a reference to the fee amount that was paid.\\n uint256 _fee;\\n\\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\\n address _projectOwner = projects.ownerOf(_projectId);\\n\\n // Get the amount of discount that should be applied to any fees taken.\\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\\n ? JBConstants.MAX_FEE_DISCOUNT\\n : _currentFeeDiscount(_projectId);\\n\\n // Take a fee from the `_distributedAmount`, if needed.\\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\\n ? 0\\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\\n\\n unchecked {\\n // The net amount is the withdrawn amount without the fee.\\n netDistributedAmount = _distributedAmount - _fee;\\n }\\n\\n // Transfer any remaining balance to the beneficiary.\\n if (netDistributedAmount > 0)\\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\\n }\\n\\n emit UseAllowance(\\n _fundingCycle.configuration,\\n _fundingCycle.number,\\n _projectId,\\n _beneficiary,\\n _amount,\\n _distributedAmount,\\n netDistributedAmount,\\n _memo,\\n msg.sender\\n );\\n }\\n\\n /**\\n @notice\\n Pays out splits for a project's funding cycle configuration.\\n\\n @param _projectId The ID of the project for which payout splits are being distributed.\\n @param _domain The domain of the splits to distribute the payout between.\\n @param _group The group of the splits to distribute the payout between.\\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\\n\\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\\n */\\n function _distributeToPayoutSplitsOf(\\n uint256 _projectId,\\n uint256 _domain,\\n uint256 _group,\\n uint256 _amount,\\n uint256 _feeDiscount\\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\\n // Set the leftover amount to the initial amount.\\n leftoverAmount = _amount;\\n // The total percentage available to split\\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\\n\\n // Get a reference to the project's payout splits.\\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\\n\\n // Transfer between all splits.\\n for (uint256 _i; _i < _splits.length; ) {\\n // Get a reference to the split being iterated on.\\n JBSplit memory _split = _splits[_i];\\n\\n // The amount to send towards the split.\\n uint256 _payoutAmount = _split.percent == leftoverPercentage\\n ? leftoverAmount\\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\\n\\n // Decrement the leftover percentage.\\n leftoverPercentage -= _split.percent;\\n\\n // The payout amount substracting any applicable incurred fees.\\n uint256 _netPayoutAmount;\\n\\n if (_payoutAmount > 0) {\\n // Transfer tokens to the split.\\n // If there's an allocator set, transfer to its `allocate` function.\\n if (_split.allocator != IJBSplitAllocator(address(0))) {\\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\\n if (\\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\\n isFeelessAddress[address(_split.allocator)]\\n )\\n _netPayoutAmount = _payoutAmount;\\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\\n else {\\n unchecked {\\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\\n }\\n\\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\\n feeEligibleDistributionAmount += _payoutAmount;\\n }\\n\\n // Trigger any inherited pre-transfer logic.\\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\\n\\n // Create the data to send to the allocator.\\n JBSplitAllocationData memory _data = JBSplitAllocationData(\\n token,\\n _netPayoutAmount,\\n decimals,\\n _projectId,\\n _group,\\n _split\\n );\\n\\n // Trigger the allocator's `allocate` function.\\n // If this terminal's token is ETH, send it in msg.value.\\n _split.allocator.allocate{value: token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0}(_data);\\n\\n // Otherwise, if a project is specified, make a payment to it.\\n } else if (_split.projectId != 0) {\\n // Get a reference to the Juicebox terminal being used.\\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\\n\\n // The project must have a terminal to send funds to.\\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\\n\\n // Save gas if this contract is being used as the terminal.\\n if (_terminal == this) {\\n // This distribution does not incur a fee.\\n _netPayoutAmount = _payoutAmount;\\n\\n // Send the projectId in the metadata.\\n bytes memory _projectMetadata = new bytes(32);\\n _projectMetadata = bytes(abi.encodePacked(_projectId));\\n\\n // Add to balance if prefered.\\n if (_split.preferAddToBalance)\\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\\n else\\n _pay(\\n _netPayoutAmount,\\n address(this),\\n _split.projectId,\\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\\n 0,\\n _split.preferClaimed,\\n '',\\n _projectMetadata\\n );\\n } else {\\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\\n if (\\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_terminal)]\\n )\\n _netPayoutAmount = _payoutAmount;\\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\\n else {\\n unchecked {\\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\\n }\\n\\n feeEligibleDistributionAmount += _payoutAmount;\\n }\\n\\n // Trigger any inherited pre-transfer logic.\\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\\n\\n // If this terminal's token is ETH, send it in msg.value.\\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0;\\n\\n // Send the projectId in the metadata.\\n bytes memory _projectMetadata = new bytes(32);\\n _projectMetadata = bytes(abi.encodePacked(_projectId));\\n\\n // Add to balance if prefered.\\n if (_split.preferAddToBalance)\\n _terminal.addToBalanceOf{value: _payableValue}(\\n _split.projectId,\\n _netPayoutAmount,\\n token,\\n '',\\n _projectMetadata\\n );\\n else\\n _terminal.pay{value: _payableValue}(\\n _split.projectId,\\n _netPayoutAmount,\\n token,\\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\\n 0,\\n _split.preferClaimed,\\n '',\\n _projectMetadata\\n );\\n }\\n } else {\\n // Keep a reference to the beneficiary.\\n address payable _beneficiary = _split.beneficiary != address(0)\\n ? _split.beneficiary\\n : payable(msg.sender);\\n\\n // If there's a full discount, this distribution is not eligible for a fee.\\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\\n _netPayoutAmount = _payoutAmount;\\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\\n else {\\n unchecked {\\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\\n }\\n\\n feeEligibleDistributionAmount += _payoutAmount;\\n }\\n\\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\\n _transferFrom(address(this), _beneficiary, _netPayoutAmount);\\n }\\n\\n // Subtract from the amount to be sent to the beneficiary.\\n unchecked {\\n leftoverAmount = leftoverAmount - _payoutAmount;\\n }\\n }\\n\\n emit DistributeToPayoutSplit(\\n _projectId,\\n _domain,\\n _group,\\n _split,\\n _netPayoutAmount,\\n msg.sender\\n );\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n\\n /**\\n @notice\\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\\n\\n @param _projectId The ID of the project having fees taken from.\\n @param _fundingCycle The funding cycle during which the fee is being taken.\\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\\n @param _beneficiary The address to mint the platforms tokens for.\\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\\n\\n @return feeAmount The amount of the fee taken.\\n */\\n function _takeFeeFrom(\\n uint256 _projectId,\\n JBFundingCycle memory _fundingCycle,\\n uint256 _amount,\\n address _beneficiary,\\n uint256 _feeDiscount\\n ) internal returns (uint256 feeAmount) {\\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\\n\\n if (_fundingCycle.shouldHoldFees()) {\\n // Store the held fee.\\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\\n\\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\\n } else {\\n // Process the fee.\\n _processFee(feeAmount, _beneficiary); // Take the fee.\\n\\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\\n }\\n }\\n\\n /**\\n @notice\\n Process a fee of the specified amount.\\n\\n @param _amount The fee amount, as a floating point number with 18 decimals.\\n @param _beneficiary The address to mint the platform's tokens for.\\n */\\n function _processFee(uint256 _amount, address _beneficiary) internal {\\n // Get the terminal for the protocol project.\\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\\n\\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\\n if (_terminal == this)\\n _pay(\\n _amount,\\n address(this),\\n _FEE_BENEFICIARY_PROJECT_ID,\\n _beneficiary,\\n 0,\\n false,\\n '',\\n bytes('')\\n ); // Use the local pay call.\\n else {\\n // Trigger any inherited pre-transfer logic.\\n _beforeTransferTo(address(_terminal), _amount);\\n\\n // If this terminal's token is ETH, send it in msg.value.\\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _amount : 0;\\n\\n // Send the payment.\\n _terminal.pay{value: _payableValue}(\\n _FEE_BENEFICIARY_PROJECT_ID,\\n _amount,\\n token,\\n _beneficiary,\\n 0,\\n false,\\n '',\\n bytes('')\\n ); // Use the external pay call of the correct terminal.\\n }\\n }\\n\\n /**\\n @notice\\n Contribute tokens to a project.\\n\\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\\n @param _payer The address making the payment.\\n @param _projectId The ID of the project being paid.\\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\\n\\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\\n */\\n function _pay(\\n uint256 _amount,\\n address _payer,\\n uint256 _projectId,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string memory _memo,\\n bytes memory _metadata\\n ) internal returns (uint256 beneficiaryTokenCount) {\\n // Cant send tokens to the zero address.\\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\\n\\n // Define variables that will be needed outside the scoped section below.\\n // Keep a reference to the funding cycle during which the payment is being made.\\n JBFundingCycle memory _fundingCycle;\\n\\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\\n {\\n JBPayDelegateAllocation[] memory _delegateAllocations;\\n uint256 _tokenCount;\\n\\n // Bundle the amount info into a JBTokenAmount struct.\\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\\n\\n // Record the payment.\\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\\n _payer,\\n _bundledAmount,\\n _projectId,\\n baseWeightCurrency,\\n _beneficiary,\\n _memo,\\n _metadata\\n );\\n\\n // Mint the tokens if needed.\\n if (_tokenCount > 0)\\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\\n _projectId,\\n _tokenCount,\\n _beneficiary,\\n '',\\n _preferClaimedTokens,\\n true\\n );\\n\\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\\n\\n // If delegate allocations were specified by the data source, fulfill them.\\n if (_delegateAllocations.length != 0) {\\n // Keep a reference to the token amount being forwarded to the delegate.\\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\\n\\n JBDidPayData memory _data = JBDidPayData(\\n _payer,\\n _projectId,\\n _fundingCycle.configuration,\\n _bundledAmount,\\n _forwardedAmount,\\n beneficiaryTokenCount,\\n _beneficiary,\\n _preferClaimedTokens,\\n _memo,\\n _metadata\\n );\\n\\n // Get a reference to the number of delegates to allocate to.\\n uint256 _numDelegates = _delegateAllocations.length;\\n\\n for (uint256 _i; _i < _numDelegates; ) {\\n // Get a reference to the delegate being iterated on.\\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\\n\\n // Trigger any inherited pre-transfer logic.\\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\\n\\n // Keep track of the msg.value to use in the delegate call\\n uint256 _payableValue;\\n\\n // If this terminal's token is ETH, send it in msg.value.\\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\\n\\n // Pass the correct token forwardedAmount to the delegate\\n _data.forwardedAmount.value = _delegateAllocation.amount;\\n\\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\\n\\n emit DelegateDidPay(\\n _delegateAllocation.delegate,\\n _data,\\n _delegateAllocation.amount,\\n msg.sender\\n );\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n }\\n\\n emit Pay(\\n _fundingCycle.configuration,\\n _fundingCycle.number,\\n _projectId,\\n _payer,\\n _beneficiary,\\n _amount,\\n beneficiaryTokenCount,\\n _memo,\\n _metadata,\\n msg.sender\\n );\\n }\\n\\n /**\\n @notice\\n Receives funds belonging to the specified project.\\n\\n @param _projectId The ID of the project to which the funds received belong.\\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Extra data to pass along to the emitted event.\\n */\\n function _addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n bool _shouldRefundHeldFees,\\n string memory _memo,\\n bytes memory _metadata\\n ) internal {\\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\\n\\n // Record the added funds with any refunded fees.\\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\\n\\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\\n }\\n\\n /**\\n @notice\\n Refund fees based on the specified amount.\\n\\n @param _projectId The project for which fees are being refunded.\\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\\n\\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\\n */\\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\\n internal\\n returns (uint256 refundedFees)\\n {\\n // Get a reference to the project's held fees.\\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\\n\\n // Delete the current held fees.\\n delete _heldFeesOf[_projectId];\\n\\n // Get a reference to the leftover amount once all fees have been settled.\\n uint256 leftoverAmount = _amount;\\n\\n // Push length in stack\\n uint256 _heldFeesLength = _heldFees.length;\\n\\n // Process each fee.\\n for (uint256 _i; _i < _heldFeesLength; ) {\\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\\n else if (leftoverAmount >= _heldFees[_i].amount) {\\n unchecked {\\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\\n refundedFees += _feeAmount(\\n _heldFees[_i].amount,\\n _heldFees[_i].fee,\\n _heldFees[_i].feeDiscount\\n );\\n }\\n } else {\\n unchecked {\\n _heldFeesOf[_projectId].push(\\n JBFee(\\n _heldFees[_i].amount - leftoverAmount,\\n _heldFees[_i].fee,\\n _heldFees[_i].feeDiscount,\\n _heldFees[_i].beneficiary\\n )\\n );\\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\\n }\\n leftoverAmount = 0;\\n }\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n\\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\\n }\\n\\n /** \\n @notice \\n Returns the fee amount based on the provided amount for the specified project.\\n\\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\\n @param _fee The percentage of the fee, out of MAX_FEE. \\n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\\n\\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\\n */\\n function _feeAmount(\\n uint256 _amount,\\n uint256 _fee,\\n uint256 _feeDiscount\\n ) internal pure returns (uint256) {\\n // Calculate the discounted fee.\\n uint256 _discountedFee = _fee -\\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\\n\\n // The amount of tokens from the `_amount` to pay as a fee.\\n return\\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\\n }\\n\\n /** \\n @notice\\n Get the fee discount from the fee gauge for the specified project.\\n\\n @param _projectId The ID of the project to get a fee discount for.\\n \\n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\\n */\\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\\n if (\\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\\n IJBPaymentTerminal(address(0))\\n ) return JBConstants.MAX_FEE_DISCOUNT;\\n\\n // Get the fee discount.\\n if (feeGauge != IJBFeeGauge(address(0)))\\n // If the guage reverts, keep the discount at 0.\\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\\n // If the fee discount is greater than the max, we ignore the return value\\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\\n } catch {\\n return 0;\\n }\\n\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0xbd19927d16eca865a8c894bed895c2704fa17ef361b97f90310b5ff0d43d9036\",\"license\":\"MIT\"},\"contracts/abstract/JBSingleTokenPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\\nimport './../interfaces/IJBSingleTokenPaymentTerminal.sol';\\n\\n/**\\n @notice\\n Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\\n\\n @dev\\n Adheres to -\\n IJBSingleTokenPaymentTerminals: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n\\n @dev\\n Inherits from -\\n ERC165: Introspection on interface adherance. \\n*/\\nabstract contract JBSingleTokenPaymentTerminal is ERC165, IJBSingleTokenPaymentTerminal {\\n //*********************************************************************//\\n // ---------------- public immutable stored properties --------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The token that this terminal accepts.\\n */\\n address public immutable override token;\\n\\n /**\\n @notice\\n The number of decimals the token fixed point amounts are expected to have.\\n */\\n uint256 public immutable override decimals;\\n\\n /**\\n @notice\\n The currency to use when resolving price feeds for this terminal.\\n */\\n uint256 public immutable override currency;\\n\\n //*********************************************************************//\\n // ------------------------- external views -------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n A flag indicating if this terminal accepts the specified token.\\n\\n @param _token The token to check if this terminal accepts or not.\\n @param _projectId The project ID to check for token acceptance.\\n\\n @return The flag.\\n */\\n function acceptsToken(address _token, uint256 _projectId) external view override returns (bool) {\\n _projectId; // Prevents unused var compiler and natspec complaints.\\n\\n return _token == token;\\n }\\n\\n /** \\n @notice\\n The decimals that should be used in fixed number accounting for the specified token.\\n\\n @param _token The token to check for the decimals of.\\n\\n @return The number of decimals for the token.\\n */\\n function decimalsForToken(address _token) external view override returns (uint256) {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n return decimals;\\n }\\n\\n /** \\n @notice\\n The currency that should be used for the specified token.\\n\\n @param _token The token to check for the currency of.\\n\\n @return The currency index.\\n */\\n function currencyForToken(address _token) external view override returns (uint256) {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n return currency;\\n }\\n\\n //*********************************************************************//\\n // -------------------------- public views --------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Indicates if this contract adheres to the specified interface.\\n\\n @dev \\n See {IERC165-supportsInterface}.\\n\\n @param _interfaceId The ID of the interface to check for adherance to.\\n */\\n function supportsInterface(bytes4 _interfaceId)\\n public\\n view\\n virtual\\n override(ERC165, IERC165)\\n returns (bool)\\n {\\n return\\n _interfaceId == type(IJBPaymentTerminal).interfaceId ||\\n _interfaceId == type(IJBSingleTokenPaymentTerminal).interfaceId ||\\n super.supportsInterface(_interfaceId);\\n }\\n\\n //*********************************************************************//\\n // -------------------------- constructor ---------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @param _token The token that this terminal manages.\\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\\n @param _currency The currency that this terminal's token adheres to for price feeds.\\n */\\n constructor(\\n address _token,\\n uint256 _decimals,\\n uint256 _currency\\n ) {\\n token = _token;\\n decimals = _decimals;\\n currency = _currency;\\n }\\n}\\n\",\"keccak256\":\"0xdc82ad3e01b918d3d21ffea8c9f30950d81e225137c851599d028dcd22125f89\",\"license\":\"MIT\"},\"contracts/enums/JBBallotState.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nenum JBBallotState {\\n Active,\\n Approved,\\n Failed\\n}\\n\",\"keccak256\":\"0x891fcac63470398b3a11239da7feba6b07d640809fcefd2404303b823d7378f8\",\"license\":\"MIT\"},\"contracts/interfaces/IJBAllowanceTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBAllowanceTerminal {\\n function useAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n address _token,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string calldata _memo\\n ) external returns (uint256 netDistributedAmount);\\n}\\n\",\"keccak256\":\"0x139d7628da9fc8510f53482d592cd4074d21c0cb6d72510ff2743076f3b17533\",\"license\":\"MIT\"},\"contracts/interfaces/IJBController.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBFundAccessConstraints.sol';\\nimport './../structs/JBFundingCycleData.sol';\\nimport './../structs/JBFundingCycleMetadata.sol';\\nimport './../structs/JBGroupedSplits.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBMigratable.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBSplitsStore.sol';\\nimport './IJBTokenStore.sol';\\n\\ninterface IJBController is IERC165 {\\n event LaunchProject(uint256 configuration, uint256 projectId, string memo, address caller);\\n\\n event LaunchFundingCycles(uint256 configuration, uint256 projectId, string memo, address caller);\\n\\n event ReconfigureFundingCycles(\\n uint256 configuration,\\n uint256 projectId,\\n string memo,\\n address caller\\n );\\n\\n event SetFundAccessConstraints(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n JBFundAccessConstraints constraints,\\n address caller\\n );\\n\\n event DistributeReservedTokens(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address beneficiary,\\n uint256 tokenCount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n address caller\\n );\\n\\n event DistributeToReservedTokenSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n uint256 tokenCount,\\n address caller\\n );\\n\\n event MintTokens(\\n address indexed beneficiary,\\n uint256 indexed projectId,\\n uint256 tokenCount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n uint256 reservedRate,\\n address caller\\n );\\n\\n event BurnTokens(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 tokenCount,\\n string memo,\\n address caller\\n );\\n\\n event Migrate(uint256 indexed projectId, IJBMigratable to, address caller);\\n\\n event PrepMigration(uint256 indexed projectId, address from, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function tokenStore() external view returns (IJBTokenStore);\\n\\n function splitsStore() external view returns (IJBSplitsStore);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function reservedTokenBalanceOf(uint256 _projectId, uint256 _reservedRate)\\n external\\n view\\n returns (uint256);\\n\\n function distributionLimitOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n IJBPaymentTerminal _terminal,\\n address _token\\n ) external view returns (uint256 distributionLimit, uint256 distributionLimitCurrency);\\n\\n function overflowAllowanceOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n IJBPaymentTerminal _terminal,\\n address _token\\n ) external view returns (uint256 overflowAllowance, uint256 overflowAllowanceCurrency);\\n\\n function totalOutstandingTokensOf(uint256 _projectId, uint256 _reservedRate)\\n external\\n view\\n returns (uint256);\\n\\n function getFundingCycleOf(uint256 _projectId, uint256 _configuration)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function latestConfiguredFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (\\n JBFundingCycle memory,\\n JBFundingCycleMetadata memory metadata,\\n JBBallotState\\n );\\n\\n function currentFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function queuedFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function launchProjectFor(\\n address _owner,\\n JBProjectMetadata calldata _projectMetadata,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n IJBPaymentTerminal[] memory _terminals,\\n string calldata _memo\\n ) external returns (uint256 projectId);\\n\\n function launchFundingCyclesFor(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n IJBPaymentTerminal[] memory _terminals,\\n string calldata _memo\\n ) external returns (uint256 configuration);\\n\\n function reconfigureFundingCyclesOf(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n string calldata _memo\\n ) external returns (uint256);\\n\\n function mintTokensOf(\\n uint256 _projectId,\\n uint256 _tokenCount,\\n address _beneficiary,\\n string calldata _memo,\\n bool _preferClaimedTokens,\\n bool _useReservedRate\\n ) external returns (uint256 beneficiaryTokenCount);\\n\\n function burnTokensOf(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n string calldata _memo,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function distributeReservedTokensOf(uint256 _projectId, string memory _memo)\\n external\\n returns (uint256);\\n\\n function migrate(uint256 _projectId, IJBMigratable _to) external;\\n}\\n\",\"keccak256\":\"0xb1ee4b41f2a06f28f69c74cb729b8964f2e75f3c545a68f85bd9082b5575bc85\",\"license\":\"MIT\"},\"contracts/interfaces/IJBDirectory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBProjects.sol';\\n\\ninterface IJBDirectory {\\n event SetController(uint256 indexed projectId, address indexed controller, address caller);\\n\\n event AddTerminal(uint256 indexed projectId, IJBPaymentTerminal indexed terminal, address caller);\\n\\n event SetTerminals(uint256 indexed projectId, IJBPaymentTerminal[] terminals, address caller);\\n\\n event SetPrimaryTerminal(\\n uint256 indexed projectId,\\n address indexed token,\\n IJBPaymentTerminal indexed terminal,\\n address caller\\n );\\n\\n event SetIsAllowedToSetFirstController(address indexed addr, bool indexed flag, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function controllerOf(uint256 _projectId) external view returns (address);\\n\\n function isAllowedToSetFirstController(address _address) external view returns (bool);\\n\\n function terminalsOf(uint256 _projectId) external view returns (IJBPaymentTerminal[] memory);\\n\\n function isTerminalOf(uint256 _projectId, IJBPaymentTerminal _terminal)\\n external\\n view\\n returns (bool);\\n\\n function primaryTerminalOf(uint256 _projectId, address _token)\\n external\\n view\\n returns (IJBPaymentTerminal);\\n\\n function setControllerOf(uint256 _projectId, address _controller) external;\\n\\n function setTerminalsOf(uint256 _projectId, IJBPaymentTerminal[] calldata _terminals) external;\\n\\n function setPrimaryTerminalOf(\\n uint256 _projectId,\\n address _token,\\n IJBPaymentTerminal _terminal\\n ) external;\\n\\n function setIsAllowedToSetFirstController(address _address, bool _flag) external;\\n}\\n\",\"keccak256\":\"0x715321646db00514d1355ed43c40cd3f01e94959552fd07797b315d9c49cdb1d\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFeeGauge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBFeeGauge {\\n function currentDiscountFor(uint256 _projectId) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x8e19959617191320fe1210760860e668a57319258c0c74fcfabac829ae0222c0\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleBallot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../enums/JBBallotState.sol';\\n\\ninterface IJBFundingCycleBallot is IERC165 {\\n function duration() external view returns (uint256);\\n\\n function stateOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n uint256 _start\\n ) external view returns (JBBallotState);\\n}\\n\",\"keccak256\":\"0x49553a56209237846bc400cf27f260824a6bd06fd8094a7eb5abb9de75779598\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../enums/JBBallotState.sol';\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBFundingCycleData.sol';\\n\\ninterface IJBFundingCycleStore {\\n event Configure(\\n uint256 indexed configuration,\\n uint256 indexed projectId,\\n JBFundingCycleData data,\\n uint256 metadata,\\n uint256 mustStartAtOrAfter,\\n address caller\\n );\\n\\n event Init(uint256 indexed configuration, uint256 indexed projectId, uint256 indexed basedOn);\\n\\n function latestConfigurationOf(uint256 _projectId) external view returns (uint256);\\n\\n function get(uint256 _projectId, uint256 _configuration)\\n external\\n view\\n returns (JBFundingCycle memory);\\n\\n function latestConfiguredOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBBallotState ballotState);\\n\\n function queuedOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentBallotStateOf(uint256 _projectId) external view returns (JBBallotState);\\n\\n function configureFor(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n uint256 _metadata,\\n uint256 _mustStartAtOrAfter\\n ) external returns (JBFundingCycle memory fundingCycle);\\n}\\n\",\"keccak256\":\"0xaead823851433be0c2ddc8f8086813e6cd647de3a1bc0f7570a5d6b38c378b5a\",\"license\":\"MIT\"},\"contracts/interfaces/IJBMigratable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBMigratable {\\n function prepForMigrationOf(uint256 _projectId, address _from) external;\\n}\\n\",\"keccak256\":\"0xc81053e4b4754fc510aa04fecd3ab1460f01e3e27761e7a8c94f631a978ae127\",\"license\":\"MIT\"},\"contracts/interfaces/IJBOperatable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBOperatorStore.sol';\\n\\ninterface IJBOperatable {\\n function operatorStore() external view returns (IJBOperatorStore);\\n}\\n\",\"keccak256\":\"0x09a55a91c6ce3625379334271d236cfa47bf36522a91568b406bf06f7239407e\",\"license\":\"MIT\"},\"contracts/interfaces/IJBOperatorStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBOperatorData.sol';\\n\\ninterface IJBOperatorStore {\\n event SetOperator(\\n address indexed operator,\\n address indexed account,\\n uint256 indexed domain,\\n uint256[] permissionIndexes,\\n uint256 packed\\n );\\n\\n function permissionsOf(\\n address _operator,\\n address _account,\\n uint256 _domain\\n ) external view returns (uint256);\\n\\n function hasPermission(\\n address _operator,\\n address _account,\\n uint256 _domain,\\n uint256 _permissionIndex\\n ) external view returns (bool);\\n\\n function hasPermissions(\\n address _operator,\\n address _account,\\n uint256 _domain,\\n uint256[] calldata _permissionIndexes\\n ) external view returns (bool);\\n\\n function setOperator(JBOperatorData calldata _operatorData) external;\\n\\n function setOperators(JBOperatorData[] calldata _operatorData) external;\\n}\\n\",\"keccak256\":\"0x17f4929812a356984795fafed8cb2be816a025c9a0771d85595ac0b5ff3cffc5\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPayDelegate.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBDidPayData.sol';\\n\\n/**\\n @title\\n Pay delegate\\n\\n @notice\\n Delegate called after JBTerminal.pay(..) logic completion (if passed by the funding cycle datasource)\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n*/\\ninterface IJBPayDelegate is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.pay(..), after the execution of its logic\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control\\n \\n @param _data the data passed by the terminal, as a JBDidPayData struct:\\n address payer;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n JBTokenAmount amount;\\n JBTokenAmount forwardedAmount;\\n uint256 projectTokenCount;\\n address beneficiary;\\n bool preferClaimedTokens;\\n string memo;\\n bytes metadata;\\n */\\n function didPay(JBDidPayData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0xa797de18b69eceba117e1f0b3810cf3cc2d2791417d580a5bdc510d1b868ab26\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\n\\ninterface IJBPaymentTerminal is IERC165 {\\n function acceptsToken(address _token, uint256 _projectId) external view returns (bool);\\n\\n function currencyForToken(address _token) external view returns (uint256);\\n\\n function decimalsForToken(address _token) external view returns (uint256);\\n\\n // Return value must be a fixed point number with 18 decimals.\\n function currentEthOverflowOf(uint256 _projectId) external view returns (uint256);\\n\\n function pay(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable returns (uint256 beneficiaryTokenCount);\\n\\n function addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable;\\n}\\n\",\"keccak256\":\"0xb7826f5ed609359ce322c09e83236c47ba385df1c3cad3607e56fd0a2e00eee2\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPayoutRedemptionPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBFee.sol';\\nimport './IJBAllowanceTerminal.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFeeGauge.sol';\\nimport './IJBPayDelegate.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBPayoutTerminal.sol';\\nimport './IJBPrices.sol';\\nimport './IJBProjects.sol';\\nimport './IJBRedemptionDelegate.sol';\\nimport './IJBRedemptionTerminal.sol';\\nimport './IJBSingleTokenPaymentTerminalStore.sol';\\nimport './IJBSplitsStore.sol';\\n\\ninterface IJBPayoutRedemptionPaymentTerminal is\\n IJBPaymentTerminal,\\n IJBPayoutTerminal,\\n IJBAllowanceTerminal,\\n IJBRedemptionTerminal\\n{\\n event AddToBalance(\\n uint256 indexed projectId,\\n uint256 amount,\\n uint256 refundedFees,\\n string memo,\\n bytes metadata,\\n address caller\\n );\\n\\n event Migrate(\\n uint256 indexed projectId,\\n IJBPaymentTerminal indexed to,\\n uint256 amount,\\n address caller\\n );\\n\\n event DistributePayouts(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address beneficiary,\\n uint256 amount,\\n uint256 distributedAmount,\\n uint256 fee,\\n uint256 beneficiaryDistributionAmount,\\n string memo,\\n address caller\\n );\\n\\n event UseAllowance(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address beneficiary,\\n uint256 amount,\\n uint256 distributedAmount,\\n uint256 netDistributedamount,\\n string memo,\\n address caller\\n );\\n\\n event HoldFee(\\n uint256 indexed projectId,\\n uint256 indexed amount,\\n uint256 indexed fee,\\n uint256 feeDiscount,\\n address beneficiary,\\n address caller\\n );\\n\\n event ProcessFee(\\n uint256 indexed projectId,\\n uint256 indexed amount,\\n bool indexed wasHeld,\\n address beneficiary,\\n address caller\\n );\\n\\n event RefundHeldFees(\\n uint256 indexed projectId,\\n uint256 indexed amount,\\n uint256 indexed refundedFees,\\n uint256 leftoverAmount,\\n address caller\\n );\\n\\n event Pay(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address payer,\\n address beneficiary,\\n uint256 amount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n bytes metadata,\\n address caller\\n );\\n\\n event DelegateDidPay(\\n IJBPayDelegate indexed delegate,\\n JBDidPayData data,\\n uint256 delegatedAmount,\\n address caller\\n );\\n\\n event RedeemTokens(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address holder,\\n address beneficiary,\\n uint256 tokenCount,\\n uint256 reclaimedAmount,\\n string memo,\\n bytes metadata,\\n address caller\\n );\\n\\n event DelegateDidRedeem(\\n IJBRedemptionDelegate indexed delegate,\\n JBDidRedeemData data,\\n uint256 delegatedAmount,\\n address caller\\n );\\n\\n event DistributeToPayoutSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n uint256 amount,\\n address caller\\n );\\n\\n event SetFee(uint256 fee, address caller);\\n\\n event SetFeeGauge(IJBFeeGauge indexed feeGauge, address caller);\\n\\n event SetFeelessAddress(address indexed addrs, bool indexed flag, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function splitsStore() external view returns (IJBSplitsStore);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function prices() external view returns (IJBPrices);\\n\\n function store() external view returns (IJBSingleTokenPaymentTerminalStore);\\n\\n function baseWeightCurrency() external view returns (uint256);\\n\\n function payoutSplitsGroup() external view returns (uint256);\\n\\n function heldFeesOf(uint256 _projectId) external view returns (JBFee[] memory);\\n\\n function fee() external view returns (uint256);\\n\\n function feeGauge() external view returns (IJBFeeGauge);\\n\\n function isFeelessAddress(address _contract) external view returns (bool);\\n\\n function migrate(uint256 _projectId, IJBPaymentTerminal _to) external returns (uint256 balance);\\n\\n function processFees(uint256 _projectId) external;\\n\\n function setFee(uint256 _fee) external;\\n\\n function setFeeGauge(IJBFeeGauge _feeGauge) external;\\n\\n function setFeelessAddress(address _contract, bool _flag) external;\\n}\\n\",\"keccak256\":\"0x5cd280eda38ee2d6e50604576e9260a788bf89b55dd7801a3ed1e8f876920450\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPayoutTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBPayoutTerminal {\\n function distributePayoutsOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n address _token,\\n uint256 _minReturnedTokens,\\n string calldata _memo\\n ) external returns (uint256 netLeftoverDistributionAmount);\\n}\\n\",\"keccak256\":\"0xbb556a74e4f82e9d65c3d1c40120bc57487440844b7bcf8c66935748aeab2dbd\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPriceFeed.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBPriceFeed {\\n function currentPrice(uint256 _targetDecimals) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x57c71282fec1b34b00cf991ffed2e36031c393e35bfa7ca5d723eb6572fb7122\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPrices.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBPriceFeed.sol';\\n\\ninterface IJBPrices {\\n event AddFeed(uint256 indexed currency, uint256 indexed base, IJBPriceFeed feed);\\n\\n function feedFor(uint256 _currency, uint256 _base) external view returns (IJBPriceFeed);\\n\\n function priceFor(\\n uint256 _currency,\\n uint256 _base,\\n uint256 _decimals\\n ) external view returns (uint256);\\n\\n function addFeedFor(\\n uint256 _currency,\\n uint256 _base,\\n IJBPriceFeed _priceFeed\\n ) external;\\n}\\n\",\"keccak256\":\"0x82a175b1f4b95b506c98406576cd59cbe04615e3df24f9cf3587b61b8ee323b1\",\"license\":\"MIT\"},\"contracts/interfaces/IJBProjects.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBTokenUriResolver.sol';\\n\\ninterface IJBProjects is IERC721 {\\n event Create(\\n uint256 indexed projectId,\\n address indexed owner,\\n JBProjectMetadata metadata,\\n address caller\\n );\\n\\n event SetMetadata(uint256 indexed projectId, JBProjectMetadata metadata, address caller);\\n\\n event SetTokenUriResolver(IJBTokenUriResolver indexed resolver, address caller);\\n\\n function count() external view returns (uint256);\\n\\n function metadataContentOf(uint256 _projectId, uint256 _domain)\\n external\\n view\\n returns (string memory);\\n\\n function tokenUriResolver() external view returns (IJBTokenUriResolver);\\n\\n function createFor(address _owner, JBProjectMetadata calldata _metadata)\\n external\\n returns (uint256 projectId);\\n\\n function setMetadataOf(uint256 _projectId, JBProjectMetadata calldata _metadata) external;\\n\\n function setTokenUriResolver(IJBTokenUriResolver _newResolver) external;\\n}\\n\",\"keccak256\":\"0x7cfc021d0bd7e73b1ba8f4845d7d35e3419d6a14d3d25ca3a8010e7f91062fe4\",\"license\":\"MIT\"},\"contracts/interfaces/IJBRedemptionDelegate.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBDidRedeemData.sol';\\n\\n/**\\n @title\\n Redemption delegate\\n\\n @notice\\n Delegate called after JBTerminal.redeemTokensOf(..) logic completion (if passed by the funding cycle datasource)\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n*/\\ninterface IJBRedemptionDelegate is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.redeemTokensOf(..), after the execution of its logic\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control\\n \\n @param _data the data passed by the terminal, as a JBDidRedeemData struct:\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 projectTokenCount;\\n JBTokenAmount reclaimedAmount;\\n JBTokenAmount forwardedAmount;\\n address payable beneficiary;\\n string memo;\\n bytes metadata;\\n */\\n function didRedeem(JBDidRedeemData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0x172d2c0be65e72e54f71ae521907067f0fa30e8ca05c4f88826903208aa437e2\",\"license\":\"MIT\"},\"contracts/interfaces/IJBRedemptionTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBRedemptionTerminal {\\n function redeemTokensOf(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n address _token,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external returns (uint256 reclaimAmount);\\n}\\n\",\"keccak256\":\"0xe26a6a03468401b802ae5328b39a266f53b9331a1c077fcbf7719d10ba74ff44\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSingleTokenPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBPaymentTerminal.sol';\\n\\ninterface IJBSingleTokenPaymentTerminal is IJBPaymentTerminal {\\n function token() external view returns (address);\\n\\n function currency() external view returns (uint256);\\n\\n function decimals() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xf6e78323caa9af7bbf024f44b2032a83fed0394e0b3a242a6346e73c85b2e46f\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSingleTokenPaymentTerminalStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBPayDelegateAllocation.sol';\\nimport './../structs/JBRedemptionDelegateAllocation.sol';\\nimport './../structs/JBTokenAmount.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBPrices.sol';\\nimport './IJBSingleTokenPaymentTerminal.sol';\\n\\ninterface IJBSingleTokenPaymentTerminalStore {\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function prices() external view returns (IJBPrices);\\n\\n function balanceOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\\n external\\n view\\n returns (uint256);\\n\\n function usedDistributionLimitOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _fundingCycleNumber\\n ) external view returns (uint256);\\n\\n function usedOverflowAllowanceOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _fundingCycleConfiguration\\n ) external view returns (uint256);\\n\\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\\n external\\n view\\n returns (uint256);\\n\\n function currentTotalOverflowOf(\\n uint256 _projectId,\\n uint256 _decimals,\\n uint256 _currency\\n ) external view returns (uint256);\\n\\n function currentReclaimableOverflowOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n bool _useTotalOverflow\\n ) external view returns (uint256);\\n\\n function currentReclaimableOverflowOf(\\n uint256 _projectId,\\n uint256 _tokenCount,\\n uint256 _totalSupply,\\n uint256 _overflow\\n ) external view returns (uint256);\\n\\n function recordPaymentFrom(\\n address _payer,\\n JBTokenAmount memory _amount,\\n uint256 _projectId,\\n uint256 _baseWeightCurrency,\\n address _beneficiary,\\n string calldata _memo,\\n bytes calldata _metadata\\n )\\n external\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 tokenCount,\\n JBPayDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n );\\n\\n function recordRedemptionFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n string calldata _memo,\\n bytes calldata _metadata\\n )\\n external\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 reclaimAmount,\\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n );\\n\\n function recordDistributionFor(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n ) external returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount);\\n\\n function recordUsedAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n ) external returns (JBFundingCycle memory fundingCycle, uint256 withdrawnAmount);\\n\\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external;\\n\\n function recordMigration(uint256 _projectId) external returns (uint256 balance);\\n}\\n\",\"keccak256\":\"0xd78929c9371fd7895b829ef5e4ad4b3786523c3580ac3f6f5f25d2b5941c0dd3\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSplitAllocator.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport '../structs/JBSplitAllocationData.sol';\\n\\n/**\\n @title\\n Split allocator\\n\\n @notice\\n Provide a way to process a single split with extra logic\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n\\n @dev\\n The contract address should be set as an allocator in the adequate split\\n*/\\ninterface IJBSplitAllocator is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.distributePayoutOf(..), during the processing of the split including it\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control. The token and/or eth are optimistically transfered\\n to the allocator for its logic.\\n \\n @param _data the data passed by the terminal, as a JBSplitAllocationData struct:\\n address token;\\n uint256 amount;\\n uint256 decimals;\\n uint256 projectId;\\n uint256 group;\\n JBSplit split;\\n */\\n function allocate(JBSplitAllocationData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0x5efb6f51fc161f42ff58989386ad99028e4039a0ba897d66f358c3dfcf686105\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSplitsStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBGroupedSplits.sol';\\nimport './../structs/JBSplit.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBProjects.sol';\\n\\ninterface IJBSplitsStore {\\n event SetSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n address caller\\n );\\n\\n function projects() external view returns (IJBProjects);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function splitsOf(\\n uint256 _projectId,\\n uint256 _domain,\\n uint256 _group\\n ) external view returns (JBSplit[] memory);\\n\\n function set(\\n uint256 _projectId,\\n uint256 _domain,\\n JBGroupedSplits[] memory _groupedSplits\\n ) external;\\n}\\n\",\"keccak256\":\"0x66dab3dd394e318b850401ca92c2963b906cc0ad5562fa5d4f6f850175d1c77a\",\"license\":\"MIT\"},\"contracts/interfaces/IJBToken.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBToken {\\n function projectId() external view returns (uint256);\\n\\n function decimals() external view returns (uint8);\\n\\n function totalSupply(uint256 _projectId) external view returns (uint256);\\n\\n function balanceOf(address _account, uint256 _projectId) external view returns (uint256);\\n\\n function mint(\\n uint256 _projectId,\\n address _account,\\n uint256 _amount\\n ) external;\\n\\n function burn(\\n uint256 _projectId,\\n address _account,\\n uint256 _amount\\n ) external;\\n\\n function approve(\\n uint256,\\n address _spender,\\n uint256 _amount\\n ) external;\\n\\n function transfer(\\n uint256 _projectId,\\n address _to,\\n uint256 _amount\\n ) external;\\n\\n function transferFrom(\\n uint256 _projectId,\\n address _from,\\n address _to,\\n uint256 _amount\\n ) external;\\n}\\n\",\"keccak256\":\"0xe8969210417736c85d71101bf1c0bd8ebbf9d1e62a93e758148bd5709a6c7097\",\"license\":\"MIT\"},\"contracts/interfaces/IJBTokenStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBProjects.sol';\\nimport './IJBToken.sol';\\n\\ninterface IJBTokenStore {\\n event Issue(\\n uint256 indexed projectId,\\n IJBToken indexed token,\\n string name,\\n string symbol,\\n address caller\\n );\\n\\n event Mint(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 amount,\\n bool tokensWereClaimed,\\n bool preferClaimedTokens,\\n address caller\\n );\\n\\n event Burn(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 amount,\\n uint256 initialUnclaimedBalance,\\n uint256 initialClaimedBalance,\\n bool preferClaimedTokens,\\n address caller\\n );\\n\\n event Claim(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 initialUnclaimedBalance,\\n uint256 amount,\\n address caller\\n );\\n\\n event Set(uint256 indexed projectId, IJBToken indexed newToken, address caller);\\n\\n event Transfer(\\n address indexed holder,\\n uint256 indexed projectId,\\n address indexed recipient,\\n uint256 amount,\\n address caller\\n );\\n\\n function tokenOf(uint256 _projectId) external view returns (IJBToken);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function unclaimedBalanceOf(address _holder, uint256 _projectId) external view returns (uint256);\\n\\n function unclaimedTotalSupplyOf(uint256 _projectId) external view returns (uint256);\\n\\n function totalSupplyOf(uint256 _projectId) external view returns (uint256);\\n\\n function balanceOf(address _holder, uint256 _projectId) external view returns (uint256 _result);\\n\\n function issueFor(\\n uint256 _projectId,\\n string calldata _name,\\n string calldata _symbol\\n ) external returns (IJBToken token);\\n\\n function setFor(uint256 _projectId, IJBToken _token) external;\\n\\n function burnFrom(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function mintFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function claimFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount\\n ) external;\\n\\n function transferFrom(\\n address _holder,\\n uint256 _projectId,\\n address _recipient,\\n uint256 _amount\\n ) external;\\n}\\n\",\"keccak256\":\"0x98459e3af050d41dfeffdc97f1c93330207ba450f8ff3613224b49a89eeca9c6\",\"license\":\"MIT\"},\"contracts/interfaces/IJBTokenUriResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBTokenUriResolver {\\n function getUri(uint256 _projectId) external view returns (string memory tokenUri);\\n}\\n\",\"keccak256\":\"0xd267fd8ca7c21c2c71794acdb9a98314c33a35fc559e0bf0897a6686d196d174\",\"license\":\"MIT\"},\"contracts/libraries/JBConstants.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/**\\n @notice\\n Global constants used across Juicebox contracts.\\n*/\\nlibrary JBConstants {\\n uint256 public constant MAX_RESERVED_RATE = 10_000;\\n uint256 public constant MAX_REDEMPTION_RATE = 10_000;\\n uint256 public constant MAX_DISCOUNT_RATE = 1_000_000_000;\\n uint256 public constant SPLITS_TOTAL_PERCENT = 1_000_000_000;\\n uint256 public constant MAX_FEE = 1_000_000_000;\\n uint256 public constant MAX_FEE_DISCOUNT = 1_000_000_000;\\n}\\n\",\"keccak256\":\"0x34362846a1cd428a8bdedf4ab6857e11402f345cb87b994b2e7fb6d2474b808d\",\"license\":\"MIT\"},\"contracts/libraries/JBCurrencies.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBCurrencies {\\n uint256 public constant ETH = 1;\\n uint256 public constant USD = 2;\\n}\\n\",\"keccak256\":\"0x7e417ff25c173608ee4fe6d9fc3dcd5e1458c78c889af12bac47b1189a436076\",\"license\":\"MIT\"},\"contracts/libraries/JBFixedPointNumber.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nlibrary JBFixedPointNumber {\\n function adjustDecimals(\\n uint256 _value,\\n uint256 _decimals,\\n uint256 _targetDecimals\\n ) internal pure returns (uint256) {\\n // If decimals need adjusting, multiply or divide the price by the decimal adjuster to get the normalized result.\\n if (_targetDecimals == _decimals) return _value;\\n else if (_targetDecimals > _decimals) return _value * 10**(_targetDecimals - _decimals);\\n else return _value / 10**(_decimals - _targetDecimals);\\n }\\n}\\n\",\"keccak256\":\"0x18efac48269f3a3bd7e9a1c770776f950e0afa86769e6f8b128002c3b8c6742c\",\"license\":\"MIT\"},\"contracts/libraries/JBFundingCycleMetadataResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBFundingCycleMetadata.sol';\\nimport './../structs/JBGlobalFundingCycleMetadata.sol';\\nimport './JBConstants.sol';\\nimport './JBGlobalFundingCycleMetadataResolver.sol';\\n\\nlibrary JBFundingCycleMetadataResolver {\\n function global(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (JBGlobalFundingCycleMetadata memory)\\n {\\n return JBGlobalFundingCycleMetadataResolver.expandMetadata(uint8(_fundingCycle.metadata >> 8));\\n }\\n\\n function reservedRate(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n return uint256(uint16(_fundingCycle.metadata >> 24));\\n }\\n\\n function redemptionRate(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n // Redemption rate is a number 0-10000. It's inverse was stored so the most common case of 100% results in no storage needs.\\n return JBConstants.MAX_REDEMPTION_RATE - uint256(uint16(_fundingCycle.metadata >> 40));\\n }\\n\\n function ballotRedemptionRate(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (uint256)\\n {\\n // Redemption rate is a number 0-10000. It's inverse was stored so the most common case of 100% results in no storage needs.\\n return JBConstants.MAX_REDEMPTION_RATE - uint256(uint16(_fundingCycle.metadata >> 56));\\n }\\n\\n function payPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 72) & 1) == 1;\\n }\\n\\n function distributionsPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 73) & 1) == 1;\\n }\\n\\n function redeemPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 74) & 1) == 1;\\n }\\n\\n function burnPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 75) & 1) == 1;\\n }\\n\\n function mintingAllowed(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 76) & 1) == 1;\\n }\\n\\n function terminalMigrationAllowed(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 77) & 1) == 1;\\n }\\n\\n function controllerMigrationAllowed(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 78) & 1) == 1;\\n }\\n\\n function shouldHoldFees(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 79) & 1) == 1;\\n }\\n\\n function preferClaimedTokenOverride(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 80) & 1) == 1;\\n }\\n\\n function useTotalOverflowForRedemptions(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 81) & 1) == 1;\\n }\\n\\n function useDataSourceForPay(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return (_fundingCycle.metadata >> 82) & 1 == 1;\\n }\\n\\n function useDataSourceForRedeem(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return (_fundingCycle.metadata >> 83) & 1 == 1;\\n }\\n\\n function dataSource(JBFundingCycle memory _fundingCycle) internal pure returns (address) {\\n return address(uint160(_fundingCycle.metadata >> 84));\\n }\\n\\n function metadata(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n return uint256(uint8(_fundingCycle.metadata >> 244));\\n }\\n\\n /**\\n @notice\\n Pack the funding cycle metadata.\\n\\n @param _metadata The metadata to validate and pack.\\n\\n @return packed The packed uint256 of all metadata params. The first 8 bits specify the version.\\n */\\n function packFundingCycleMetadata(JBFundingCycleMetadata memory _metadata)\\n internal\\n pure\\n returns (uint256 packed)\\n {\\n // version 1 in the bits 0-7 (8 bits).\\n packed = 1;\\n // global metadta in bits 8-23 (16 bits).\\n packed |=\\n JBGlobalFundingCycleMetadataResolver.packFundingCycleGlobalMetadata(_metadata.global) <<\\n 8;\\n // reserved rate in bits 24-39 (16 bits).\\n packed |= _metadata.reservedRate << 24;\\n // redemption rate in bits 40-55 (16 bits).\\n // redemption rate is a number 0-10000. Store the reverse so the most common case of 100% results in no storage needs.\\n packed |= (JBConstants.MAX_REDEMPTION_RATE - _metadata.redemptionRate) << 40;\\n // ballot redemption rate rate in bits 56-71 (16 bits).\\n // ballot redemption rate is a number 0-10000. Store the reverse so the most common case of 100% results in no storage needs.\\n packed |= (JBConstants.MAX_REDEMPTION_RATE - _metadata.ballotRedemptionRate) << 56;\\n // pause pay in bit 72.\\n if (_metadata.pausePay) packed |= 1 << 72;\\n // pause tap in bit 73.\\n if (_metadata.pauseDistributions) packed |= 1 << 73;\\n // pause redeem in bit 74.\\n if (_metadata.pauseRedeem) packed |= 1 << 74;\\n // pause burn in bit 75.\\n if (_metadata.pauseBurn) packed |= 1 << 75;\\n // allow minting in bit 76.\\n if (_metadata.allowMinting) packed |= 1 << 76;\\n // allow terminal migration in bit 77.\\n if (_metadata.allowTerminalMigration) packed |= 1 << 77;\\n // allow controller migration in bit 78.\\n if (_metadata.allowControllerMigration) packed |= 1 << 78;\\n // hold fees in bit 79.\\n if (_metadata.holdFees) packed |= 1 << 79;\\n // prefer claimed token override in bit 80.\\n if (_metadata.preferClaimedTokenOverride) packed |= 1 << 80;\\n // useTotalOverflowForRedemptions in bit 81.\\n if (_metadata.useTotalOverflowForRedemptions) packed |= 1 << 81;\\n // use pay data source in bit 82.\\n if (_metadata.useDataSourceForPay) packed |= 1 << 82;\\n // use redeem data source in bit 83.\\n if (_metadata.useDataSourceForRedeem) packed |= 1 << 83;\\n // data source address in bits 84-243.\\n packed |= uint256(uint160(address(_metadata.dataSource))) << 84;\\n // metadata in bits 244-252 (8 bits).\\n packed |= _metadata.metadata << 244;\\n }\\n\\n /**\\n @notice\\n Expand the funding cycle metadata.\\n\\n @param _fundingCycle The funding cycle having its metadata expanded.\\n\\n @return metadata The metadata object.\\n */\\n function expandMetadata(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (JBFundingCycleMetadata memory)\\n {\\n return\\n JBFundingCycleMetadata(\\n global(_fundingCycle),\\n reservedRate(_fundingCycle),\\n redemptionRate(_fundingCycle),\\n ballotRedemptionRate(_fundingCycle),\\n payPaused(_fundingCycle),\\n distributionsPaused(_fundingCycle),\\n redeemPaused(_fundingCycle),\\n burnPaused(_fundingCycle),\\n mintingAllowed(_fundingCycle),\\n terminalMigrationAllowed(_fundingCycle),\\n controllerMigrationAllowed(_fundingCycle),\\n shouldHoldFees(_fundingCycle),\\n preferClaimedTokenOverride(_fundingCycle),\\n useTotalOverflowForRedemptions(_fundingCycle),\\n useDataSourceForPay(_fundingCycle),\\n useDataSourceForRedeem(_fundingCycle),\\n dataSource(_fundingCycle),\\n metadata(_fundingCycle)\\n );\\n }\\n}\\n\",\"keccak256\":\"0x3d045c38593102cfb6ac67f3ddf2232e1ff5518d6d021423ae2681387599fbd3\",\"license\":\"MIT\"},\"contracts/libraries/JBGlobalFundingCycleMetadataResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport './../structs/JBFundingCycleMetadata.sol';\\n\\nlibrary JBGlobalFundingCycleMetadataResolver {\\n function setTerminalsAllowed(uint8 _data) internal pure returns (bool) {\\n return (_data & 1) == 1;\\n }\\n\\n function setControllerAllowed(uint8 _data) internal pure returns (bool) {\\n return ((_data >> 1) & 1) == 1;\\n }\\n\\n function transfersPaused(uint8 _data) internal pure returns (bool) {\\n return ((_data >> 2) & 1) == 1;\\n }\\n\\n /**\\n @notice\\n Pack the global funding cycle metadata.\\n\\n @param _metadata The metadata to validate and pack.\\n\\n @return packed The packed uint256 of all global metadata params. The first 8 bits specify the version.\\n */\\n function packFundingCycleGlobalMetadata(JBGlobalFundingCycleMetadata memory _metadata)\\n internal\\n pure\\n returns (uint256 packed)\\n {\\n // allow set terminals in bit 0.\\n if (_metadata.allowSetTerminals) packed |= 1;\\n // allow set controller in bit 1.\\n if (_metadata.allowSetController) packed |= 1 << 1;\\n // pause transfers in bit 2.\\n if (_metadata.pauseTransfers) packed |= 1 << 2;\\n }\\n\\n /**\\n @notice\\n Expand the global funding cycle metadata.\\n\\n @param _packedMetadata The packed metadata to expand.\\n\\n @return metadata The global metadata object.\\n */\\n function expandMetadata(uint8 _packedMetadata)\\n internal\\n pure\\n returns (JBGlobalFundingCycleMetadata memory metadata)\\n {\\n return\\n JBGlobalFundingCycleMetadata(\\n setTerminalsAllowed(_packedMetadata),\\n setControllerAllowed(_packedMetadata),\\n transfersPaused(_packedMetadata)\\n );\\n }\\n}\\n\",\"keccak256\":\"0x0d998f938026edeb755987a79421267cf860801161b5f171206a200b60f1061f\",\"license\":\"MIT\"},\"contracts/libraries/JBOperations.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBOperations {\\n uint256 public constant RECONFIGURE = 1;\\n uint256 public constant REDEEM = 2;\\n uint256 public constant MIGRATE_CONTROLLER = 3;\\n uint256 public constant MIGRATE_TERMINAL = 4;\\n uint256 public constant PROCESS_FEES = 5;\\n uint256 public constant SET_METADATA = 6;\\n uint256 public constant ISSUE = 7;\\n uint256 public constant SET_TOKEN = 8;\\n uint256 public constant MINT = 9;\\n uint256 public constant BURN = 10;\\n uint256 public constant CLAIM = 11;\\n uint256 public constant TRANSFER = 12;\\n uint256 public constant REQUIRE_CLAIM = 13; // unused in v3\\n uint256 public constant SET_CONTROLLER = 14;\\n uint256 public constant SET_TERMINALS = 15;\\n uint256 public constant SET_PRIMARY_TERMINAL = 16;\\n uint256 public constant USE_ALLOWANCE = 17;\\n uint256 public constant SET_SPLITS = 18;\\n}\\n\",\"keccak256\":\"0x7f8e501e6890297f4015b1c27cebdb44fadbf21204bea1f3162f5388c060f690\",\"license\":\"MIT\"},\"contracts/libraries/JBSplitsGroups.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBSplitsGroups {\\n uint256 public constant ETH_PAYOUT = 1;\\n uint256 public constant RESERVED_TOKENS = 2;\\n}\\n\",\"keccak256\":\"0x4183db6087bd8db645fc3a0d3d8afb0d6356e003650793f63c301ebbbae47269\",\"license\":\"MIT\"},\"contracts/libraries/JBTokens.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBTokens {\\n /** \\n @notice \\n The ETH token address in Juicebox is represented by 0x000000000000000000000000000000000000EEEe.\\n */\\n address public constant ETH = address(0x000000000000000000000000000000000000EEEe);\\n}\\n\",\"keccak256\":\"0xecf82992f7b827766aa55f16872517a646521eef414d8cc9786617ea377e5463\",\"license\":\"MIT\"},\"contracts/structs/JBDidPayData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member payer The address from which the payment originated.\\n @member projectId The ID of the project for which the payment was made.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the payment is being made.\\n @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.\\n @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.\\n @member projectTokenCount The number of project tokens minted for the beneficiary.\\n @member beneficiary The address to which the tokens were minted.\\n @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.\\n @member memo The memo that is being emitted alongside the payment.\\n @member metadata Extra data to send to the delegate.\\n*/\\nstruct JBDidPayData {\\n address payer;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n JBTokenAmount amount;\\n JBTokenAmount forwardedAmount;\\n uint256 projectTokenCount;\\n address beneficiary;\\n bool preferClaimedTokens;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0xf3c664309b37790f16047ae97b0459889ae0242dfcde7fc8902c8d10c7f8e6b6\",\"license\":\"MIT\"},\"contracts/structs/JBDidRedeemData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member holder The holder of the tokens being redeemed.\\n @member projectId The ID of the project with which the redeemed tokens are associated.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the redemption is being made.\\n @member projectTokenCount The number of project tokens being redeemed.\\n @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.\\n @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.\\n @member beneficiary The address to which the reclaimed amount will be sent.\\n @member memo The memo that is being emitted alongside the redemption.\\n @member metadata Extra data to send to the delegate.\\n*/\\nstruct JBDidRedeemData {\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 projectTokenCount;\\n JBTokenAmount reclaimedAmount;\\n JBTokenAmount forwardedAmount;\\n address payable beneficiary;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0xe2c401f39723a7ce915b8bef328744c66daaf57460843964b941456c2258a412\",\"license\":\"MIT\"},\"contracts/structs/JBFee.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member amount The total amount the fee was taken from, as a fixed point number with the same number of decimals as the terminal in which this struct was created.\\n @member fee The percent of the fee, out of MAX_FEE.\\n @member feeDiscount The discount of the fee.\\n @member beneficiary The address that will receive the tokens that are minted as a result of the fee payment.\\n*/\\nstruct JBFee {\\n uint256 amount;\\n uint32 fee;\\n uint32 feeDiscount;\\n address beneficiary;\\n}\\n\",\"keccak256\":\"0xf4759ff41fe7f1db0fd1ccc7b2a326b239389fd8d69df9b9ed5e1d5926f6fe38\",\"license\":\"MIT\"},\"contracts/structs/JBFundAccessConstraints.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBPaymentTerminal.sol';\\n\\n/** \\n @member terminal The terminal within which the distribution limit and the overflow allowance applies.\\n @member token The token for which the fund access constraints apply.\\n @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.\\n @member distributionLimitCurrency The currency of the distribution limit.\\n @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.\\n @member overflowAllowanceCurrency The currency of the overflow allowance.\\n*/\\nstruct JBFundAccessConstraints {\\n IJBPaymentTerminal terminal;\\n address token;\\n uint256 distributionLimit;\\n uint256 distributionLimitCurrency;\\n uint256 overflowAllowance;\\n uint256 overflowAllowanceCurrency;\\n}\\n\",\"keccak256\":\"0x85ebaa57b788cbdedc7a3d0eec4892eda5d79db7c1a6103797f10d0d989775b2\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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.\\n @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.\\n @member basedOn The `configuration` of the funding cycle that was active when this cycle was created.\\n @member start The timestamp marking the moment from which the funding cycle is considered active. It is a unix timestamp measured in seconds.\\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n @member metadata Extra data that can be associated with a funding cycle.\\n*/\\nstruct JBFundingCycle {\\n uint256 number;\\n uint256 configuration;\\n uint256 basedOn;\\n uint256 start;\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n uint256 metadata;\\n}\\n\",\"keccak256\":\"0xcdd3ac9b6fa67e62ada88d09b73bc35ade1cd77d43db712289266a788928b4c2\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycleData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n*/\\nstruct JBFundingCycleData {\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n}\\n\",\"keccak256\":\"0x2aa6368bf4dfc5797e8b02a978293de0c777fae2658de2c825a103587240f3b0\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycleMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBGlobalFundingCycleMetadata.sol';\\n\\n/** \\n @member global Data used globally in non-migratable ecosystem contracts.\\n @member reservedRate The reserved rate of the funding cycle. This number is a percentage calculated out of `JBConstants.MAX_RESERVED_RATE`.\\n @member redemptionRate The redemption rate of the funding cycle. This number is a percentage calculated out of `JBConstants.MAX_REDEMPTION_RATE`.\\n @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`.\\n @member pausePay A flag indicating if the pay functionality should be paused during the funding cycle.\\n @member pauseDistributions A flag indicating if the distribute functionality should be paused during the funding cycle.\\n @member pauseRedeem A flag indicating if the redeem functionality should be paused during the funding cycle.\\n @member pauseBurn A flag indicating if the burn functionality should be paused during the funding cycle.\\n @member allowMinting A flag indicating if minting tokens should be allowed during this funding cycle.\\n @member allowTerminalMigration A flag indicating if migrating terminals should be allowed during this funding cycle.\\n @member allowControllerMigration A flag indicating if migrating controllers should be allowed during this funding cycle.\\n @member holdFees A flag indicating if fees should be held during this funding cycle.\\n @member preferClaimedTokenOverride A flag indicating if claimed tokens should always be prefered to unclaimed tokens when minting.\\n @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.\\n @member useDataSourceForPay A flag indicating if the data source should be used for pay transactions during this funding cycle.\\n @member useDataSourceForRedeem A flag indicating if the data source should be used for redeem transactions during this funding cycle.\\n @member dataSource The data source to use during this funding cycle.\\n @member metadata Metadata of the metadata, up to uint8 in size.\\n*/\\nstruct JBFundingCycleMetadata {\\n JBGlobalFundingCycleMetadata global;\\n uint256 reservedRate;\\n uint256 redemptionRate;\\n uint256 ballotRedemptionRate;\\n bool pausePay;\\n bool pauseDistributions;\\n bool pauseRedeem;\\n bool pauseBurn;\\n bool allowMinting;\\n bool allowTerminalMigration;\\n bool allowControllerMigration;\\n bool holdFees;\\n bool preferClaimedTokenOverride;\\n bool useTotalOverflowForRedemptions;\\n bool useDataSourceForPay;\\n bool useDataSourceForRedeem;\\n address dataSource;\\n uint256 metadata;\\n}\\n\",\"keccak256\":\"0x783604440cac8d176332eab28166f188ee5c230378c08cfc95fea4f7187dc77d\",\"license\":\"MIT\"},\"contracts/structs/JBGlobalFundingCycleMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member allowSetTerminals A flag indicating if setting terminals should be allowed during this funding cycle.\\n @member allowSetController A flag indicating if setting a new controller should be allowed during this funding cycle.\\n @member pauseTransfers A flag indicating if the project token transfer functionality should be paused during the funding cycle.\\n*/\\nstruct JBGlobalFundingCycleMetadata {\\n bool allowSetTerminals;\\n bool allowSetController;\\n bool pauseTransfers;\\n}\\n\",\"keccak256\":\"0x05d85530305fec6d6eca54cdbc2cd9110cbda0146598032b0203aa4b622944ff\",\"license\":\"MIT\"},\"contracts/structs/JBGroupedSplits.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBSplit.sol';\\n\\n/** \\n @member group The group indentifier.\\n @member splits The splits to associate with the group.\\n*/\\nstruct JBGroupedSplits {\\n uint256 group;\\n JBSplit[] splits;\\n}\\n\",\"keccak256\":\"0x80be1b220da4ac04851ea540ebb94c1ec2b0442ec5bd1e88fdf78a56becd8b5a\",\"license\":\"MIT\"},\"contracts/structs/JBOperatorData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member operator The address of the operator.\\n @member domain The domain within which the operator is being given permissions. A domain of 0 is a wildcard domain, which gives an operator access to all domains.\\n @member permissionIndexes The indexes of the permissions the operator is being given.\\n*/\\nstruct JBOperatorData {\\n address operator;\\n uint256 domain;\\n uint256[] permissionIndexes;\\n}\\n\",\"keccak256\":\"0x3b85be7b69515976ee10770776283911666aceca820b0cf4e201ea4dbffeb6f0\",\"license\":\"MIT\"},\"contracts/structs/JBPayDelegateAllocation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '../interfaces/IJBPayDelegate.sol';\\n\\n/** \\n @member delegate A delegate contract to use for subsequent calls.\\n @member amount The amount to send to the delegate.\\n*/\\nstruct JBPayDelegateAllocation {\\n IJBPayDelegate delegate;\\n uint256 amount;\\n}\\n\",\"keccak256\":\"0xb4e558dc62231d89e9b48998012577d22c3e52b58e23401f22d9096827f6ea0c\",\"license\":\"MIT\"},\"contracts/structs/JBProjectMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member content The metadata content.\\n @member domain The domain within which the metadata applies.\\n*/\\nstruct JBProjectMetadata {\\n string content;\\n uint256 domain;\\n}\\n\",\"keccak256\":\"0x90ad7b1014c0a9f945fe7a2efde9d5de41e40574fa27969070b1d2ff52033ea0\",\"license\":\"MIT\"},\"contracts/structs/JBRedemptionDelegateAllocation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '../interfaces/IJBRedemptionDelegate.sol';\\n\\n/** \\n @member delegate A delegate contract to use for subsequent calls.\\n @member amount The amount to send to the delegate.\\n*/\\nstruct JBRedemptionDelegateAllocation {\\n IJBRedemptionDelegate delegate;\\n uint256 amount;\\n}\\n\",\"keccak256\":\"0x10c29d33dd0d875a0d4692a2b9a9355c2ebf433cc06a9a60253d4366b60d4d31\",\"license\":\"MIT\"},\"contracts/structs/JBSplit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBSplitAllocator.sol';\\n\\n/** \\n @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.\\n @member preferAddToBalance A flag indicating if a distribution to a project should prefer triggering it's addToBalance function instead of its pay function.\\n @member percent The percent of the whole group that this split occupies. This number is out of `JBConstants.SPLITS_TOTAL_PERCENT`.\\n @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.\\n @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.\\n @member lockedUntil Specifies if the split should be unchangeable until the specified time, with the exception of extending the locked period.\\n @member allocator If an allocator is specified, funds will be sent to the allocator contract along with all properties of this split.\\n*/\\nstruct JBSplit {\\n bool preferClaimed;\\n bool preferAddToBalance;\\n uint256 percent;\\n uint256 projectId;\\n address payable beneficiary;\\n uint256 lockedUntil;\\n IJBSplitAllocator allocator;\\n}\\n\",\"keccak256\":\"0xc80a16606da8abf76d0f73abc38aee041e24f29342c1939018f70c286e89f105\",\"license\":\"MIT\"},\"contracts/structs/JBSplitAllocationData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBSplit.sol';\\n\\n/** \\n @member token The token being sent to the split allocator.\\n @member amount The amount being sent to the split allocator, as a fixed point number.\\n @member decimals The number of decimals in the amount.\\n @member projectId The project to which the split belongs.\\n @member group The group to which the split belongs.\\n @member split The split that caused the allocation.\\n*/\\nstruct JBSplitAllocationData {\\n address token;\\n uint256 amount;\\n uint256 decimals;\\n uint256 projectId;\\n uint256 group;\\n JBSplit split;\\n}\\n\",\"keccak256\":\"0x39f5c41bd31d36774744698ac94484b6cab62d7038df2f29d947668959782e63\",\"license\":\"MIT\"},\"contracts/structs/JBTokenAmount.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/* \\n @member token The token the payment was made in.\\n @member value The amount of tokens that was paid, as a fixed point number.\\n @member decimals The number of decimals included in the value fixed point number.\\n @member currency The expected currency of the value.\\n**/\\nstruct JBTokenAmount {\\n address token;\\n uint256 value;\\n uint256 decimals;\\n uint256 currency;\\n}\\n\",\"keccak256\":\"0x4a778e779ba257ba5638c5469e07a4d21b55a3128d56db5a0fdfacb1f3301c51\",\"license\":\"MIT\"},\"prb-math/contracts/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivFixedPointOverflow(uint256 prod1);\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivOverflow(uint256 prod1, uint256 denominator);\\n\\n/// @notice Emitted when one of the inputs is type(int256).min.\\nerror PRBMath__MulDivSignedInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows int256.\\nerror PRBMath__MulDivSignedOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is MIN_SD59x18.\\nerror PRBMathSD59x18__AbsInputTooSmall();\\n\\n/// @notice Emitted when ceiling a number overflows SD59x18.\\nerror PRBMathSD59x18__CeilOverflow(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__DivInputTooSmall();\\n\\n/// @notice Emitted when one of the intermediary unsigned results overflows SD59x18.\\nerror PRBMathSD59x18__DivOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathSD59x18__ExpInputTooBig(int256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathSD59x18__Exp2InputTooBig(int256 x);\\n\\n/// @notice Emitted when flooring a number underflows SD59x18.\\nerror PRBMathSD59x18__FloorUnderflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format overflows SD59x18.\\nerror PRBMathSD59x18__FromIntOverflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format underflows SD59x18.\\nerror PRBMathSD59x18__FromIntUnderflow(int256 x);\\n\\n/// @notice Emitted when the product of the inputs is negative.\\nerror PRBMathSD59x18__GmNegativeProduct(int256 x, int256 y);\\n\\n/// @notice Emitted when multiplying the inputs overflows SD59x18.\\nerror PRBMathSD59x18__GmOverflow(int256 x, int256 y);\\n\\n/// @notice Emitted when the input is less than or equal to zero.\\nerror PRBMathSD59x18__LogInputTooSmall(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__MulInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__MulOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__PowuOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is negative.\\nerror PRBMathSD59x18__SqrtNegativeInput(int256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows SD59x18.\\nerror PRBMathSD59x18__SqrtOverflow(int256 x);\\n\\n/// @notice Emitted when addition overflows UD60x18.\\nerror PRBMathUD60x18__AddOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when ceiling a number overflows UD60x18.\\nerror PRBMathUD60x18__CeilOverflow(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathUD60x18__ExpInputTooBig(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathUD60x18__Exp2InputTooBig(uint256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format format overflows UD60x18.\\nerror PRBMathUD60x18__FromUintOverflow(uint256 x);\\n\\n/// @notice Emitted when multiplying the inputs overflows UD60x18.\\nerror PRBMathUD60x18__GmOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when the input is less than 1.\\nerror PRBMathUD60x18__LogInputTooSmall(uint256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows UD60x18.\\nerror PRBMathUD60x18__SqrtOverflow(uint256 x);\\n\\n/// @notice Emitted when subtraction underflows UD60x18.\\nerror PRBMathUD60x18__SubUnderflow(uint256 x, uint256 y);\\n\\n/// @dev Common mathematical functions used in both PRBMathSD59x18 and PRBMathUD60x18. Note that this shared library\\n/// does not always assume the signed 59.18-decimal fixed-point or the unsigned 60.18-decimal fixed-point\\n/// representation. When it does not, it is explicitly mentioned in the NatSpec documentation.\\nlibrary PRBMath {\\n /// STRUCTS ///\\n\\n struct SD59x18 {\\n int256 value;\\n }\\n\\n struct UD60x18 {\\n uint256 value;\\n }\\n\\n /// STORAGE ///\\n\\n /// @dev How many trailing decimals can be represented.\\n uint256 internal constant SCALE = 1e18;\\n\\n /// @dev Largest power of two divisor of SCALE.\\n uint256 internal constant SCALE_LPOTD = 262144;\\n\\n /// @dev SCALE inverted mod 2^256.\\n uint256 internal constant SCALE_INVERSE =\\n 78156646155174841979727994598816262306175212592076161876661_508869554232690281;\\n\\n /// FUNCTIONS ///\\n\\n /// @notice Calculates the binary exponent of x using the binary fraction method.\\n /// @dev Has to use 192.64-bit fixed-point numbers.\\n /// See https://ethereum.stackexchange.com/a/96594/24693.\\n /// @param x The exponent as an unsigned 192.64-bit fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp2(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n // Start from 0.5 in the 192.64-bit fixed-point format.\\n result = 0x800000000000000000000000000000000000000000000000;\\n\\n // Multiply the result by root(2, 2^-i) when the bit at position i is 1. None of the intermediary results overflows\\n // because the initial result is 2^191 and all magic factors are less than 2^65.\\n if (x & 0x8000000000000000 > 0) {\\n result = (result * 0x16A09E667F3BCC909) >> 64;\\n }\\n if (x & 0x4000000000000000 > 0) {\\n result = (result * 0x1306FE0A31B7152DF) >> 64;\\n }\\n if (x & 0x2000000000000000 > 0) {\\n result = (result * 0x1172B83C7D517ADCE) >> 64;\\n }\\n if (x & 0x1000000000000000 > 0) {\\n result = (result * 0x10B5586CF9890F62A) >> 64;\\n }\\n if (x & 0x800000000000000 > 0) {\\n result = (result * 0x1059B0D31585743AE) >> 64;\\n }\\n if (x & 0x400000000000000 > 0) {\\n result = (result * 0x102C9A3E778060EE7) >> 64;\\n }\\n if (x & 0x200000000000000 > 0) {\\n result = (result * 0x10163DA9FB33356D8) >> 64;\\n }\\n if (x & 0x100000000000000 > 0) {\\n result = (result * 0x100B1AFA5ABCBED61) >> 64;\\n }\\n if (x & 0x80000000000000 > 0) {\\n result = (result * 0x10058C86DA1C09EA2) >> 64;\\n }\\n if (x & 0x40000000000000 > 0) {\\n result = (result * 0x1002C605E2E8CEC50) >> 64;\\n }\\n if (x & 0x20000000000000 > 0) {\\n result = (result * 0x100162F3904051FA1) >> 64;\\n }\\n if (x & 0x10000000000000 > 0) {\\n result = (result * 0x1000B175EFFDC76BA) >> 64;\\n }\\n if (x & 0x8000000000000 > 0) {\\n result = (result * 0x100058BA01FB9F96D) >> 64;\\n }\\n if (x & 0x4000000000000 > 0) {\\n result = (result * 0x10002C5CC37DA9492) >> 64;\\n }\\n if (x & 0x2000000000000 > 0) {\\n result = (result * 0x1000162E525EE0547) >> 64;\\n }\\n if (x & 0x1000000000000 > 0) {\\n result = (result * 0x10000B17255775C04) >> 64;\\n }\\n if (x & 0x800000000000 > 0) {\\n result = (result * 0x1000058B91B5BC9AE) >> 64;\\n }\\n if (x & 0x400000000000 > 0) {\\n result = (result * 0x100002C5C89D5EC6D) >> 64;\\n }\\n if (x & 0x200000000000 > 0) {\\n result = (result * 0x10000162E43F4F831) >> 64;\\n }\\n if (x & 0x100000000000 > 0) {\\n result = (result * 0x100000B1721BCFC9A) >> 64;\\n }\\n if (x & 0x80000000000 > 0) {\\n result = (result * 0x10000058B90CF1E6E) >> 64;\\n }\\n if (x & 0x40000000000 > 0) {\\n result = (result * 0x1000002C5C863B73F) >> 64;\\n }\\n if (x & 0x20000000000 > 0) {\\n result = (result * 0x100000162E430E5A2) >> 64;\\n }\\n if (x & 0x10000000000 > 0) {\\n result = (result * 0x1000000B172183551) >> 64;\\n }\\n if (x & 0x8000000000 > 0) {\\n result = (result * 0x100000058B90C0B49) >> 64;\\n }\\n if (x & 0x4000000000 > 0) {\\n result = (result * 0x10000002C5C8601CC) >> 64;\\n }\\n if (x & 0x2000000000 > 0) {\\n result = (result * 0x1000000162E42FFF0) >> 64;\\n }\\n if (x & 0x1000000000 > 0) {\\n result = (result * 0x10000000B17217FBB) >> 64;\\n }\\n if (x & 0x800000000 > 0) {\\n result = (result * 0x1000000058B90BFCE) >> 64;\\n }\\n if (x & 0x400000000 > 0) {\\n result = (result * 0x100000002C5C85FE3) >> 64;\\n }\\n if (x & 0x200000000 > 0) {\\n result = (result * 0x10000000162E42FF1) >> 64;\\n }\\n if (x & 0x100000000 > 0) {\\n result = (result * 0x100000000B17217F8) >> 64;\\n }\\n if (x & 0x80000000 > 0) {\\n result = (result * 0x10000000058B90BFC) >> 64;\\n }\\n if (x & 0x40000000 > 0) {\\n result = (result * 0x1000000002C5C85FE) >> 64;\\n }\\n if (x & 0x20000000 > 0) {\\n result = (result * 0x100000000162E42FF) >> 64;\\n }\\n if (x & 0x10000000 > 0) {\\n result = (result * 0x1000000000B17217F) >> 64;\\n }\\n if (x & 0x8000000 > 0) {\\n result = (result * 0x100000000058B90C0) >> 64;\\n }\\n if (x & 0x4000000 > 0) {\\n result = (result * 0x10000000002C5C860) >> 64;\\n }\\n if (x & 0x2000000 > 0) {\\n result = (result * 0x1000000000162E430) >> 64;\\n }\\n if (x & 0x1000000 > 0) {\\n result = (result * 0x10000000000B17218) >> 64;\\n }\\n if (x & 0x800000 > 0) {\\n result = (result * 0x1000000000058B90C) >> 64;\\n }\\n if (x & 0x400000 > 0) {\\n result = (result * 0x100000000002C5C86) >> 64;\\n }\\n if (x & 0x200000 > 0) {\\n result = (result * 0x10000000000162E43) >> 64;\\n }\\n if (x & 0x100000 > 0) {\\n result = (result * 0x100000000000B1721) >> 64;\\n }\\n if (x & 0x80000 > 0) {\\n result = (result * 0x10000000000058B91) >> 64;\\n }\\n if (x & 0x40000 > 0) {\\n result = (result * 0x1000000000002C5C8) >> 64;\\n }\\n if (x & 0x20000 > 0) {\\n result = (result * 0x100000000000162E4) >> 64;\\n }\\n if (x & 0x10000 > 0) {\\n result = (result * 0x1000000000000B172) >> 64;\\n }\\n if (x & 0x8000 > 0) {\\n result = (result * 0x100000000000058B9) >> 64;\\n }\\n if (x & 0x4000 > 0) {\\n result = (result * 0x10000000000002C5D) >> 64;\\n }\\n if (x & 0x2000 > 0) {\\n result = (result * 0x1000000000000162E) >> 64;\\n }\\n if (x & 0x1000 > 0) {\\n result = (result * 0x10000000000000B17) >> 64;\\n }\\n if (x & 0x800 > 0) {\\n result = (result * 0x1000000000000058C) >> 64;\\n }\\n if (x & 0x400 > 0) {\\n result = (result * 0x100000000000002C6) >> 64;\\n }\\n if (x & 0x200 > 0) {\\n result = (result * 0x10000000000000163) >> 64;\\n }\\n if (x & 0x100 > 0) {\\n result = (result * 0x100000000000000B1) >> 64;\\n }\\n if (x & 0x80 > 0) {\\n result = (result * 0x10000000000000059) >> 64;\\n }\\n if (x & 0x40 > 0) {\\n result = (result * 0x1000000000000002C) >> 64;\\n }\\n if (x & 0x20 > 0) {\\n result = (result * 0x10000000000000016) >> 64;\\n }\\n if (x & 0x10 > 0) {\\n result = (result * 0x1000000000000000B) >> 64;\\n }\\n if (x & 0x8 > 0) {\\n result = (result * 0x10000000000000006) >> 64;\\n }\\n if (x & 0x4 > 0) {\\n result = (result * 0x10000000000000003) >> 64;\\n }\\n if (x & 0x2 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n if (x & 0x1 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n\\n // We're doing two things at the same time:\\n //\\n // 1. Multiply the result by 2^n + 1, where \\\"2^n\\\" is the integer part and the one is added to account for\\n // the fact that we initially set the result to 0.5. This is accomplished by subtracting from 191\\n // rather than 192.\\n // 2. Convert the result to the unsigned 60.18-decimal fixed-point format.\\n //\\n // This works because 2^(191-ip) = 2^ip / 2^191, where \\\"ip\\\" is the integer part \\\"2^n\\\".\\n result *= SCALE;\\n result >>= (191 - (x >> 64));\\n }\\n }\\n\\n /// @notice Finds the zero-based index of the first one in the binary representation of x.\\n /// @dev See the note on msb in the \\\"Find First Set\\\" Wikipedia article https://en.wikipedia.org/wiki/Find_first_set\\n /// @param x The uint256 number for which to find the index of the most significant bit.\\n /// @return msb The index of the most significant bit as an uint256.\\n function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\\n if (x >= 2**128) {\\n x >>= 128;\\n msb += 128;\\n }\\n if (x >= 2**64) {\\n x >>= 64;\\n msb += 64;\\n }\\n if (x >= 2**32) {\\n x >>= 32;\\n msb += 32;\\n }\\n if (x >= 2**16) {\\n x >>= 16;\\n msb += 16;\\n }\\n if (x >= 2**8) {\\n x >>= 8;\\n msb += 8;\\n }\\n if (x >= 2**4) {\\n x >>= 4;\\n msb += 4;\\n }\\n if (x >= 2**2) {\\n x >>= 2;\\n msb += 2;\\n }\\n if (x >= 2**1) {\\n // No need to shift x any more.\\n msb += 1;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.\\n ///\\n /// Requirements:\\n /// - The denominator cannot be zero.\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The multiplicand as an uint256.\\n /// @param y The multiplier as an uint256.\\n /// @param denominator The divisor as an uint256.\\n /// @return result The result as an uint256.\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n unchecked {\\n result = prod0 / denominator;\\n }\\n return result;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n if (prod1 >= denominator) {\\n revert PRBMath__MulDivOverflow(prod1, denominator);\\n }\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n unchecked {\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 lpotdod = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by lpotdod.\\n denominator := div(denominator, lpotdod)\\n\\n // Divide [prod1 prod0] by lpotdod.\\n prod0 := div(prod0, lpotdod)\\n\\n // Flip lpotdod such that it is 2^256 / lpotdod. If lpotdod is zero, then it becomes one.\\n lpotdod := add(div(sub(0, lpotdod), lpotdod), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * lpotdod;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f71e18) with full precision.\\n ///\\n /// @dev Variant of \\\"mulDiv\\\" with constant folding, i.e. in which the denominator is always 1e18. Before returning the\\n /// final result, we add 1 if (x * y) % SCALE >= HALF_SCALE. Without this, 6.6e-19 would be truncated to 0 instead of\\n /// being rounded to 1e-18. See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717.\\n ///\\n /// Requirements:\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - The body is purposely left uncommented; see the NatSpec comments in \\\"PRBMath.mulDiv\\\" to understand how this works.\\n /// - It is assumed that the result can never be type(uint256).max when x and y solve the following two equations:\\n /// 1. x * y = type(uint256).max * SCALE\\n /// 2. (x * y) % SCALE >= SCALE / 2\\n ///\\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function mulDivFixedPoint(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n uint256 prod0;\\n uint256 prod1;\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n if (prod1 >= SCALE) {\\n revert PRBMath__MulDivFixedPointOverflow(prod1);\\n }\\n\\n uint256 remainder;\\n uint256 roundUpUnit;\\n assembly {\\n remainder := mulmod(x, y, SCALE)\\n roundUpUnit := gt(remainder, 499999999999999999)\\n }\\n\\n if (prod1 == 0) {\\n unchecked {\\n result = (prod0 / SCALE) + roundUpUnit;\\n return result;\\n }\\n }\\n\\n assembly {\\n result := add(\\n mul(\\n or(\\n div(sub(prod0, remainder), SCALE_LPOTD),\\n mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, SCALE_LPOTD), SCALE_LPOTD), 1))\\n ),\\n SCALE_INVERSE\\n ),\\n roundUpUnit\\n )\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev An extension of \\\"mulDiv\\\" for signed numbers. Works by computing the signs and the absolute values separately.\\n ///\\n /// Requirements:\\n /// - None of the inputs can be type(int256).min.\\n /// - The result must fit within int256.\\n ///\\n /// @param x The multiplicand as an int256.\\n /// @param y The multiplier as an int256.\\n /// @param denominator The divisor as an int256.\\n /// @return result The result as an int256.\\n function mulDivSigned(\\n int256 x,\\n int256 y,\\n int256 denominator\\n ) internal pure returns (int256 result) {\\n if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {\\n revert PRBMath__MulDivSignedInputTooSmall();\\n }\\n\\n // Get hold of the absolute values of x, y and the denominator.\\n uint256 ax;\\n uint256 ay;\\n uint256 ad;\\n unchecked {\\n ax = x < 0 ? uint256(-x) : uint256(x);\\n ay = y < 0 ? uint256(-y) : uint256(y);\\n ad = denominator < 0 ? uint256(-denominator) : uint256(denominator);\\n }\\n\\n // Compute the absolute value of (x*y)\\u00f7denominator. The result must fit within int256.\\n uint256 rAbs = mulDiv(ax, ay, ad);\\n if (rAbs > uint256(type(int256).max)) {\\n revert PRBMath__MulDivSignedOverflow(rAbs);\\n }\\n\\n // Get the signs of x, y and the denominator.\\n uint256 sx;\\n uint256 sy;\\n uint256 sd;\\n assembly {\\n sx := sgt(x, sub(0, 1))\\n sy := sgt(y, sub(0, 1))\\n sd := sgt(denominator, sub(0, 1))\\n }\\n\\n // XOR over sx, sy and sd. This is checking whether there are one or three negative signs in the inputs.\\n // If yes, the result should be negative.\\n result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs);\\n }\\n\\n /// @notice Calculates the square root of x, rounding down.\\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The uint256 number for which to calculate the square root.\\n /// @return result The result as an uint256.\\n function sqrt(uint256 x) internal pure returns (uint256 result) {\\n if (x == 0) {\\n return 0;\\n }\\n\\n // Set the initial guess to the closest power of two that is higher than x.\\n uint256 xAux = uint256(x);\\n result = 1;\\n if (xAux >= 0x100000000000000000000000000000000) {\\n xAux >>= 128;\\n result <<= 64;\\n }\\n if (xAux >= 0x10000000000000000) {\\n xAux >>= 64;\\n result <<= 32;\\n }\\n if (xAux >= 0x100000000) {\\n xAux >>= 32;\\n result <<= 16;\\n }\\n if (xAux >= 0x10000) {\\n xAux >>= 16;\\n result <<= 8;\\n }\\n if (xAux >= 0x100) {\\n xAux >>= 8;\\n result <<= 4;\\n }\\n if (xAux >= 0x10) {\\n xAux >>= 4;\\n result <<= 2;\\n }\\n if (xAux >= 0x8) {\\n result <<= 1;\\n }\\n\\n // The operations can never overflow because the result is max 2^127 when it enters this block.\\n unchecked {\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1; // Seven iterations should be enough\\n uint256 roundedDownResult = x / result;\\n return result >= roundedDownResult ? roundedDownResult : result;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x62cbabae4910e168e99b9c2c3e3b5c9c7ad5e7abd961dcc63b7ea3d83d8ea87e\",\"license\":\"Unlicense\"}},\"version\":1}", "bytecode": "0x6101e060405263017d78406002553480156200001a57600080fd5b5060405162006156380380620061568339810160408190526200003d916200020a565b61eeee6080819052601260a0819052600160c08190526001600160a01b038a1660e0528a818b8b8b8b8b8b8b6200007433620000cf565b6101a08990526101c08890526001600160a01b0380871661010052858116610120528481166101405283811661016052821661018052620000b5816200011f565b5050505050505050505050505050505050505050620002bf565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000546001600160a01b031633146200017f5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b6001600160a01b038116620001e65760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840162000176565b620001f181620000cf565b50565b6001600160a01b0381168114620001f157600080fd5b600080600080600080600080610100898b0312156200022857600080fd5b8851975060208901516200023c81620001f4565b60408a01519097506200024f81620001f4565b60608a01519096506200026281620001f4565b60808a01519095506200027581620001f4565b60a08a01519094506200028881620001f4565b60c08a01519093506200029b81620001f4565b60e08a0151909250620002ae81620001f4565b809150509295985092959890939650565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c051615c4262000514600039600081816103d401526125fd01526000818161032c0152611f3a0152600081816104fc01528181610f0a015281816117b401528181611cf501528181611f080152818161247901528181612eed01526131df01526000818161064801526119520152600081816102e00152613eac0152600081816106140152818161095901528181610b650152818161200401528181612b88015281816132dc01528181613d2801526142060152600081816104aa01528181610d7a0152818161143b01528181611a0b015281816125570152612fd50152600081816105500152818161274001528181612800015281816129760152612a3601526000818161026b0152818161070001528181611884015281816118ff01528181611ee2015281816121d70152818161345b015261351a015260008181610360015281816105c00152818161182501528181611851015281816118b10152818161192c01528181611ebc015281816121b101528181613435015281816134f401526140410152600081816106be0152818161075401528181610a0401528181610c0801528181610e2b01528181610f8b0152818161101701528181611e870152818161217c015281816122b401528181612b5d01528181612c3b01528181612cc9015281816133ff015281816134bf015281816135b901528181613cfb0152818161400c01528181614098015281816142330152818161442a015281816144fc01526145750152615c426000f3fe6080604052600436106101fe5760003560e01c80638b79543c1161011d578063c41c2f24116100b0578063df21a7dd1161007f578063f2fde38b11610064578063f2fde38b14610722578063fc0c546a14610742578063fe663f0f1461077657600080fd5b8063df21a7dd146106a0578063e5a6b10f146106ee57600080fd5b8063c41c2f2414610602578063d3419bf314610636578063d6dacc531461066a578063ddca3f431461068a57600080fd5b8063ad007d63116100ec578063ad007d631461053e578063b631b50014610572578063b7bad1b1146105a2578063bc8926e9146105e257600080fd5b80638b79543c146104985780638da5cb5b146104cc578063975057e7146104ea578063a32e1e961461051e57600080fd5b8063405b84fa11610195578063715018a611610164578063715018a6146104165780637258002c1461042b57806389701db51461044b5780638af560941461046b57600080fd5b8063405b84fa14610382578063637913ac146103a257806366248b86146103c257806369fe0e2d146103f657600080fd5b80632b267b4e116101d15780632b267b4e146102ae5780632bdfe004146102ce5780632d1a59031461031a578063313ce5671461034e57600080fd5b806301ffc9a7146102035780630cf8e858146102385780631982d6791461024d5780631ebc263f1461029b575b600080fd5b34801561020f57600080fd5b5061022361021e36600461492d565b610796565b60405190151581526020015b60405180910390f35b61024b6102463660046149cd565b610922565b005b34801561025957600080fd5b5061028d610268366004614a63565b507f000000000000000000000000000000000000000000000000000000000000000090565b60405190815260200161022f565b61028d6102a9366004614a8e565b610b23565b3480156102ba57600080fd5b5061028d6102c9366004614b56565b610d2c565b3480156102da57600080fd5b506103027f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161022f565b34801561032657600080fd5b5061028d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561035a57600080fd5b5061028d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561038e57600080fd5b5061028d61039d366004614bc0565b610d48565b3480156103ae57600080fd5b5061024b6103bd366004614a63565b6110c1565b3480156103ce57600080fd5b5061028d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561040257600080fd5b5061024b610411366004614bf0565b6111a6565b34801561042257600080fd5b5061024b611298565b34801561043757600080fd5b5061024b610446366004614c09565b611318565b34801561045757600080fd5b5061024b610466366004614bf0565b61140c565b34801561047757600080fd5b5061048b610486366004614bf0565b6116c0565b60405161022f9190614c37565b3480156104a457600080fd5b506103027f000000000000000000000000000000000000000000000000000000000000000081565b3480156104d857600080fd5b506000546001600160a01b0316610302565b3480156104f657600080fd5b506103027f000000000000000000000000000000000000000000000000000000000000000081565b34801561052a57600080fd5b5061028d610539366004614bf0565b611772565b34801561054a57600080fd5b506103027f000000000000000000000000000000000000000000000000000000000000000081565b34801561057e57600080fd5b5061022361058d366004614a63565b60046020526000908152604090205460ff1681565b3480156105ae57600080fd5b5061028d6105bd366004614a63565b507f000000000000000000000000000000000000000000000000000000000000000090565b3480156105ee57600080fd5b5061028d6105fd366004614dfb565b6119d9565b34801561060e57600080fd5b506103027f000000000000000000000000000000000000000000000000000000000000000081565b34801561064257600080fd5b506103027f000000000000000000000000000000000000000000000000000000000000000081565b34801561067657600080fd5b50600354610302906001600160a01b031681565b34801561069657600080fd5b5061028d60025481565b3480156106ac57600080fd5b506102236106bb366004614e84565b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161490565b3480156106fa57600080fd5b5061028d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561072e57600080fd5b5061024b61073d366004614a63565b611aa9565b34801561074e57600080fd5b506103027f000000000000000000000000000000000000000000000000000000000000000081565b34801561078257600080fd5b5061028d610791366004614eb0565b611bbf565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167fedb527eb00000000000000000000000000000000000000000000000000000000148061082957507fffffffff0000000000000000000000000000000000000000000000000000000082167f2b267b4e00000000000000000000000000000000000000000000000000000000145b8061087557507fffffffff0000000000000000000000000000000000000000000000000000000082167fbc8926e900000000000000000000000000000000000000000000000000000000145b806108c157507fffffffff0000000000000000000000000000000000000000000000000000000082167ffe663f0f00000000000000000000000000000000000000000000000000000000145b8061090d57507fffffffff0000000000000000000000000000000000000000000000000000000082167fad007d6300000000000000000000000000000000000000000000000000000000145b8061091c575061091c82611bdf565b92915050565b6040517f6e49181f0000000000000000000000000000000000000000000000000000000081526004810188905230602482015287907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636e49181f90604401602060405180830381865afa1580156109a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109cc9190614f69565b610a02576040517fd8ead2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661eeee14610a8a573415610a6c576040517fbcfd35be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b47610a7833308a611cc2565b610a828147614fb5565b975050610a8e565b3496505b33600090815260046020908152604091829020548251601f8801839004830281018301909352868352610b19928b928b9260ff161591908a908a908190840183828082843760009201919091525050604080516020601f8c018190048102820181019092528a815292508a9150899081908401838280828437600092019190915250611cd192505050565b5050505050505050565b6040517f6e49181f000000000000000000000000000000000000000000000000000000008152600481018b90523060248201526000908b906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636e49181f90604401602060405180830381865afa158015610bac573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bd09190614f69565b610c06576040517fd8ead2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661eeee14610c8e573415610c70576040517fbcfd35be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b47610c7c33308e611cc2565b610c868147614fb5565b9b5050610c92565b349a505b610d1c8b338e8c8c8c8c8c8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611ddb92505050565b9c9b505050505050505050505050565b6000610d3c88888887878761242d565b98975050505050505050565b6040517f6352211e000000000000000000000000000000000000000000000000000000008152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610dc9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ded9190614fc8565b836004610dfb8383836126e0565b6040517fdf21a7dd0000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301526024820188905286169063df21a7dd90604401602060405180830381865afa158015610e81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea59190614f69565b610edb576040517f581010ed00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f6bb6a5ad000000000000000000000000000000000000000000000000000000008152600481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636bb6a5ad906024016020604051808303816000875af1158015610f5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f7f9190614fe5565b935083156110735760007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661eeee14610fc2576000610fc4565b845b604080516020810182526000815290517f0cf8e8580000000000000000000000000000000000000000000000000000000081529192506001600160a01b03881691630cf8e85891849161103f918c918b917f00000000000000000000000000000000000000000000000000000000000000009160040161504e565b6000604051808303818588803b15801561105857600080fd5b505af115801561106c573d6000803e3d6000fd5b5050505050505b604080518581523360208201526001600160a01b0387169188917fa7519e5f94697b7f53e97c5eb46a0c730a296ab686ab8fd333835c5f735784eb910160405180910390a350505092915050565b6000546001600160a01b0316331461113a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b600380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040513381527f0a9a80fe9716605b3e52abb3d792d6a4e7816d6afc02a5a4ef023081feaf9f609060200160405180910390a250565b6000546001600160a01b0316331461121a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611131565b6302faf080811115611258576040517f45fbd9c100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002819055604080518281523360208201527fd7414e590e1cb532989ab2a34c8f4c2c17f7ab6f006efeeaef2e87cd5008c202910160405180910390a150565b6000546001600160a01b0316331461130c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611131565b61131660006128a4565b565b6000546001600160a01b0316331461138c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611131565b6001600160a01b03821660008181526004602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001685151590811790915591513381529192917fa2653e25a502c023a5830d0de847ef6f458387865b1f4f575d7594f9f2c0d71e910160405180910390a35050565b6040517f6352211e000000000000000000000000000000000000000000000000000000008152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa15801561148a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ae9190614fc8565b8160056114c36000546001600160a01b031690565b6001600160a01b0316336001600160a01b0316146114e38484848461290c565b600085815260016020908152604080832080548251818502810185019093528083529192909190849084015b8282101561158157600084815260209081902060408051608081018252600286029092018054835260019081015463ffffffff8082168587015264010000000082041692840192909252680100000000000000009091046001600160a01b03166060830152908352909201910161150f565b50505060008881526001602052604081209293506115a09291506148ce565b805160005b81811015610b1957600061161d8483815181106115c4576115c4615094565b6020026020010151600001518584815181106115e2576115e2615094565b60200260200101516020015163ffffffff1686858151811061160657611606615094565b60200260200101516040015163ffffffff16612ae0565b90506116468185848151811061163557611635615094565b602002602001015160600151612b26565b60011515818a7fcf0c92a2c6d7c42f488326b0cb900104b99984b6b218db81cd29371364a3525187868151811061167f5761167f615094565b602002602001015160600151336040516116af9291906001600160a01b0392831681529116602082015260400190565b60405180910390a4506001016115a5565b606060016000838152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b8282101561176757600084815260209081902060408051608081018252600286029092018054835260019081015463ffffffff8082168587015264010000000082041692840192909252680100000000000000009091046001600160a01b0316606083015290835290920191016116f5565b505050509050919050565b6040517fd49031c00000000000000000000000000000000000000000000000000000000081523060048201526024810182905260009081906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063d49031c090604401602060405180830381865afa1580156117fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061181f9190614fe5565b905060007f000000000000000000000000000000000000000000000000000000000000000060121461187c57611877827f00000000000000000000000000000000000000000000000000000000000000006012612d40565b61187e565b815b905060017f0000000000000000000000000000000000000000000000000000000000000000146119cf576119ca816118d77f0000000000000000000000000000000000000000000000000000000000000000600a6151e3565b6040517fa4d0caf20000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152600160248201527f000000000000000000000000000000000000000000000000000000000000000060448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a4d0caf290606401602060405180830381865afa1580156119a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119c59190614fe5565b612d9d565b6119d1565b805b949350505050565b6040517f6352211e000000000000000000000000000000000000000000000000000000008152600481018890526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015611a5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a7e9190614fc8565b886011611a8c8383836126e0565b611a9a8b8b8b8a8a8a612ea1565b9b9a5050505050505050505050565b6000546001600160a01b03163314611b1d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611131565b6001600160a01b038116611bb3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401611131565b611bbc816128a4565b50565b600088886002611bd08383836126e0565b610d1c8c8c8c8b8b8b8b613112565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167fc07370e4000000000000000000000000000000000000000000000000000000001480611c7257507fffffffff0000000000000000000000000000000000000000000000000000000082167f2896000200000000000000000000000000000000000000000000000000000000145b8061091c57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000083161461091c565b611ccc8282613740565b505050565b600083611cdf576000611ce9565b611ce9868661388d565b90506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663e7c8e3e387611d2584896151ef565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815260048101929092526024820152604401600060405180830381600087803b158015611d7b57600080fd5b505af1158015611d8f573d6000803e3d6000fd5b50505050857f9ecaf7fc3dfffd6867c175d6e684b1f1e3aef019398ba8db2c1ffab4a09db2538683868633604051611dcb959493929190615202565b60405180910390a2505050505050565b60006001600160a01b038616611e1d576040517fa762251300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611e756040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b606060008060405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020018e81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000000000000000000000000000000000000000000081525090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632fa1b3918d838e7f00000000000000000000000000000000000000000000000000000000000000008f8d8d6040518863ffffffff1660e01b8152600401611f7e979695949392919061524f565b6000604051808303816000875af1158015611f9d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611fc591908101906153dc565b99509195509093509150811561212c576040517f5dd8f6aa000000000000000000000000000000000000000000000000000000008152600481018c90527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635dd8f6aa90602401602060405180830381865afa158015612053573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120779190614fc8565b6040517f8ae9c07b000000000000000000000000000000000000000000000000000000008152600481018d9052602481018490526001600160a01b038c8116604483015260c06064830152600060c48301528a15156084830152600160a48301529190911690638ae9c07b9060e4016020604051808303816000875af1158015612105573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121299190614fe5565b94505b88851015612166576040517f7b94612600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8251156123cf57600060405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020018f81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f0000000000000000000000000000000000000000000000000000000000000000815250905060006040518061014001604052808f6001600160a01b031681526020018e8152602001876020015181526020018481526020018381526020018881526020018d6001600160a01b031681526020018b151581526020018a815260200189815250905060008551905060005b818110156123ca57600087828151811061228257612282615094565b6020908102919091010151905060007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11127f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316016122e8575060208101515b60208083015160808701519091015281516040517fda9ee8b70000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063da9ee8b79083906123419089906004016155d8565b6000604051808303818588803b15801561235a57600080fd5b505af115801561236e573d6000803e3d6000fd5b505050505081600001516001600160a01b03167f16112c26e14efc4be6c690149aa5a1ba75160de245f60d2273e28adb277b9e12868460200151336040516123b8939291906155eb565b60405180910390a25050600101612266565b505050505b50505087816000015182602001517f133161f1c9161488f777ab9a26aae91d47c0d9a3fafb398960f138db02c737978c8b8f888b8b33604051612418979695949392919061561d565b60405180910390a45098975050505050505050565b6040517fc6644597000000000000000000000000000000000000000000000000000000008152600481018790526024810186905260448101859052600090819081906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c664459790606401610140604051808303816000875af11580156124c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124e7919061567e565b9150915085811015612525576040517fb01493c100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f6352211e000000000000000000000000000000000000000000000000000000008152600481018a90526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa1580156125a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125ca9190614fc8565b90506000806002546000146125e7576125e28c613cc4565b6125ed565b633b9aca005b90506000806126238e88602001517f00000000000000000000000000000000000000000000000000000000000000008987613e62565b92509050633b9aca00831461263757908101905b81600003612646576000612653565b6126538e8884888761470f565b9350801561267f576126688160025485612ae0565b6126729082614fb5565b975061267f30868a611cc2565b5050508a846000015185602001517f24352f49df447b14e0e08a323625c663d865ce20c343c4638af12e1dc48aa760858e88878c8f8f336040516126ca9897969594939291906156ad565b60405180910390a4505050509695505050505050565b336001600160a01b038416148015906127ad57506040517fc161c93f0000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b03848116602483015260448201849052606482018390527f0000000000000000000000000000000000000000000000000000000000000000169063c161c93f90608401602060405180830381865afa158015612787573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127ab9190614f69565b155b801561286d57506040517fc161c93f0000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b03848116602483015260006044830152606482018390527f0000000000000000000000000000000000000000000000000000000000000000169063c161c93f90608401602060405180830381865afa158015612847573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061286b9190614f69565b155b15611ccc576040517f075fd2b100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b801580156129235750336001600160a01b03851614155b80156129e357506040517fc161c93f0000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b03858116602483015260448201859052606482018490527f0000000000000000000000000000000000000000000000000000000000000000169063c161c93f90608401602060405180830381865afa1580156129bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129e19190614f69565b155b8015612aa357506040517fc161c93f0000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b03858116602483015260006044830152606482018490527f0000000000000000000000000000000000000000000000000000000000000000169063c161c93f90608401602060405180830381865afa158015612a7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612aa19190614f69565b155b15612ada576040517f075fd2b100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b600080612af28484633b9aca00612d9d565b612afc9085614fb5565b9050612b1185633b9aca006119c581856151ef565b612b1b9086614fb5565b9150505b9392505050565b6040517f86202650000000000000000000000000000000000000000000000000000000008152600160048201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660248301526000917f000000000000000000000000000000000000000000000000000000000000000090911690638620265090604401602060405180830381865afa158015612bd1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bf59190614fc8565b9050306001600160a01b03821603612c3757612ada83306001856000806040518060200160405280600081525060405180602001604052806000815250611ddb565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661eeee14612c72576000612c74565b835b60408051602081018252600080825291517f1ebc263f0000000000000000000000000000000000000000000000000000000081529293506001600160a01b03851692631ebc263f928592612cf6926001928b927f0000000000000000000000000000000000000000000000000000000000000000928c92918291600401615711565b60206040518083038185885af1158015612d14573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612d399190614fe5565b5050505050565b6000828203612d50575082612b1f565b82821115612d7e57612d628383614fb5565b612d6d90600a6151e3565b612d779085615768565b9050612b1f565b612d888284614fb5565b612d9390600a6151e3565b612d7790856157d4565b600080807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff85870985870292508281108382030391505080600003612df557838281612deb57612deb6157a5565b0492505050612b1f565b838110612e38576040517f773cc18c0000000000000000000000000000000000000000000000000000000081526004810182905260248101859052604401611131565b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b6040517f25386715000000000000000000000000000000000000000000000000000000008152600481018790526024810186905260448101859052600090819081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632538671590606401610140604051808303816000875af1158015612f37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f5b919061567e565b9150915085811015612f99576040517fb01493c100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f6352211e000000000000000000000000000000000000000000000000000000008152600481018a905260009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa15801561301c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130409190614fc8565b905060006002546000148061306457503360009081526004602052604090205460ff165b613076576130718c613cc4565b61307c565b633b9aca005b9050633b9aca00811461309b576130968c8686858561470f565b61309e565b60005b808503965092508383146130b7576130b7308988611cc2565b50505088826000015183602001517f8657a0c05a68a912c23c1bd00124afaa8c669063b046bd9bfd22b21d573c5e6d888c86898b336040516130fe9695949392919061580f565b60405180910390a450509695505050505050565b60006001600160a01b038416613154576040517ff74a1b6600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6131ac6040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b6040517fa2df1f950000000000000000000000000000000000000000000000000000000081526060906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a2df1f959061321c908d908d908d908b908b9060040161585a565b6000604051808303816000875af115801561323b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613263919081019061589a565b97509094509092509050868310156132a7576040517ff896960b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87156133e9576040517f5dd8f6aa000000000000000000000000000000000000000000000000000000008152600481018a90527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635dd8f6aa90602401602060405180830381865afa15801561332b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061334f9190614fc8565b6040517f1665bc0f0000000000000000000000000000000000000000000000000000000081526001600160a01b038c81166004830152602482018c9052604482018b905260a06064830152600060a4830181905260848301529190911690631665bc0f9060c401600060405180830381600087803b1580156133d057600080fd5b505af11580156133e4573d6000803e3d6000fd5b505050505b8051156136d457600060405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602001600081526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f0000000000000000000000000000000000000000000000000000000000000000815250905060006040518061012001604052808d6001600160a01b031681526020018c8152602001856020015181526020018b815260200160405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020018881526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000008152508152602001838152602001896001600160a01b0316815260200188815260200187815250905060008351905060005b818110156136cf57600085828151811061358757613587615094565b6020908102919091010151905060007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11127f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316016135ed575060208101515b60208083015160a08701519091015281516040517f2b13c58f0000000000000000000000000000000000000000000000000000000081526001600160a01b0390911690632b13c58f908390613646908990600401615a5d565b6000604051808303818588803b15801561365f57600080fd5b505af1158015613673573d6000803e3d6000fd5b505050505081600001516001600160a01b03167f54b3744c489f40987dd2726ca12131243334e8292f567389f761c5a432d813e4868460200151336040516136bd93929190615a70565b60405180910390a2505060010161356b565b505050505b5081156136e6576136e6308684611cc2565b87816000015182602001517f2be10f2a0203c77d0fcaa9fd6484a8a1d6904de31cd820587f60c1c8c338c8148c898c888b8b3360405161372c979695949392919061561d565b60405180910390a450979650505050505050565b804710156137aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401611131565b6000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146137f7576040519150601f19603f3d011682016040523d82523d6000602084013e6137fc565b606091505b5050905080611ccc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401611131565b600082815260016020908152604080832080548251818502810185019093528083528493849084015b8282101561392857600084815260209081902060408051608081018252600286029092018054835260019081015463ffffffff8082168587015264010000000082041692840192909252680100000000000000009091046001600160a01b0316606083015290835290920191016138b6565b50505060008681526001602052604081209293506139479291506148ce565b8051839060005b81811015613c7c5782600003613a3e576000878152600160205260409020845185908390811061398057613980615094565b60209081029190910181015182546001818101855560009485529383902082516002909202019081559181015191909201805460408401516060909401516001600160a01b031668010000000000000000027fffffffff0000000000000000000000000000000000000000ffffffffffffffff63ffffffff958616640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000090931695909416949094171791909116919091179055613c74565b838181518110613a5057613a50615094565b6020026020010151600001518310613ae457838181518110613a7457613a74615094565b60200260200101516000015183039250613adb848281518110613a9957613a99615094565b602002602001015160000151858381518110613ab757613ab7615094565b60200260200101516020015163ffffffff1686848151811061160657611606615094565b85019450613c74565b60016000888152602001908152602001600020604051806080016040528085878581518110613b1557613b15615094565b602002602001015160000151038152602001868481518110613b3957613b39615094565b60200260200101516020015163ffffffff168152602001868481518110613b6257613b62615094565b60200260200101516040015163ffffffff168152602001868481518110613b8b57613b8b615094565b6020908102919091018101516060908101516001600160a01b039081169093528454600181810187556000968752958390208551600290920201908155918401519190940180546040850151949095015190921668010000000000000000027fffffffff0000000000000000000000000000000000000000ffffffffffffffff63ffffffff948516640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909616949092169390931793909317929092161790558351613c6b908490869084908110613ab757613ab7615094565b85019450600092505b60010161394e565b50604080518381523360208201528591879189917f59860d79d97c1fce2be7f987915c631471f4b08f671200463cc40a3380194ffb910160405180910390a450505092915050565b6040517f86202650000000000000000000000000000000000000000000000000000000008152600160048201526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116602483015260009182917f00000000000000000000000000000000000000000000000000000000000000001690638620265090604401602060405180830381865afa158015613d6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d939190614fc8565b6001600160a01b031603613dac5750633b9aca00919050565b6003546001600160a01b031615613e5a576003546040517f77695896000000000000000000000000000000000000000000000000000000008152600481018490526001600160a01b0390911690637769589690602401602060405180830381865afa925050508015613e3b575060408051601f3d908101601f19168201909252613e3891810190614fe5565b60015b613e4757506000919050565b633b9aca008111613e585792915050565b505b506000919050565b6040517f69e11cc50000000000000000000000000000000000000000000000000000000081526004810186905260248101859052604481018490528290600090633b9aca009082907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906369e11cc590606401600060405180830381865afa158015613efb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613f239190810190615a83565b905060005b8151811015614702576000828281518110613f4557613f45615094565b60200260200101519050600084826040015114613f7457613f6f898360400151633b9aca00612d9d565b613f76565b865b9050816040015185613f889190614fb5565b9450600081156146b65760c08301516001600160a01b0316156141c457633b9aca00891480613fd3575060c08301516001600160a01b031660009081526004602052604090205460ff165b15613fdf575080613ffd565b613fec826002548b612ae0565b82039050613ffa82886151ef565b96505b60006040518060c001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020018381526020017f000000000000000000000000000000000000000000000000000000000000000081526020018f81526020018d81526020018581525090508360c001516001600160a01b0316639d740bfa61eeee6001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316146140cc5760006140ce565b835b604080517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815285516001600160a01b039081166004830152602080880151602484015283880151604484015260608089015160648501526080808a0151608486015260a0808b01518051151560a488015293840151151560c48701529583015160e48601529082015161010485015281015182166101248401529283015161014483015260c090920151909116610164820152610184016000604051808303818588803b1580156141a557600080fd5b505af11580156141b9573d6000803e3d6000fd5b5050505050506146b0565b60608301511561464f5760608301516040517f862026500000000000000000000000000000000000000000000000000000000081526000916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163862026509161426d917f0000000000000000000000000000000000000000000000000000000000000000906004019182526001600160a01b0316602082015260400190565b602060405180830381865afa15801561428a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142ae9190614fc8565b90506001600160a01b0381166142f0576040517f6921234300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b306001600160a01b038216036143d1576040805160208082528183019092528493506000916020820181803683370190505090508e60405160200161433791815260200190565b60405160208183030381529060405290508460200151156143785761437385606001518460006040518060200160405280600081525085611cd1565b6143cb565b6143c98330876060015160006001600160a01b031689608001516001600160a01b0316036143a657336143ac565b88608001515b60008a600001516040518060200160405280600081525088611ddb565b505b50614649565b633b9aca008a14806143fb57506001600160a01b03811660009081526004602052604090205460ff165b1561440857829150614426565b614415836002548c612ae0565b8303915061442383896151ef565b97505b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661eeee14614461576000614463565b825b604080516020808252818301909252919250600091906020820181803683370190505090508f60405160200161449b91815260200190565b604051602081830303815290604052905085602001511561455d5760608601516040517f0cf8e8580000000000000000000000000000000000000000000000000000000081526001600160a01b03851691630cf8e8589185916145269189907f000000000000000000000000000000000000000000000000000000000000000090889060040161504e565b6000604051808303818588803b15801561453f57600080fd5b505af1158015614553573d6000803e3d6000fd5b5050505050614646565b826001600160a01b0316631ebc263f838860600151877f000000000000000000000000000000000000000000000000000000000000000060006001600160a01b03168c608001516001600160a01b0316036145b857336145be565b8b608001515b8c516040517fffffffff0000000000000000000000000000000000000000000000000000000060e089901b16815261460195949392916000918b90600401615711565b60206040518083038185885af115801561461f573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906146449190614fe5565b505b50505b506146b0565b60808301516000906001600160a01b031661466a5733614670565b83608001515b9050633b9aca008a03614685578291506146a3565b614692836002548c612ae0565b830391506146a083896151ef565b97505b6146ae308284611cc2565b505b81880397505b8a8c8e7f2a1f2df21da49f011c6165709ae4b279f8d6d7cffe9043c582352882d8c9698b8685336040516146ec93929190615b8d565b60405180910390a4836001019350505050613f28565b5050509550959350505050565b600061471e8460025484612ae0565b610100860151909150604f1c60019081160361487257600086815260016020818152604080842081516080810183528981526002805463ffffffff9081168387019081528a82168487019081526001600160a01b03808e16606087019081528754808c018955978c5298909a209451958402909401948555519390960180549251955190971668010000000000000000027fffffffff0000000000000000000000000000000000000000ffffffffffffffff958716640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909316939096169290921717929092169290921790925590549051859088907f77813be0661650ddc1a5193ff2837df4162b251cb432651e2c060c3fc39756be90614865908790899033909283526001600160a01b03918216602084015216604082015260600190565b60405180910390a46148c5565b61487c8184612b26565b604080516001600160a01b0385168152336020820152600091839189917fcf0c92a2c6d7c42f488326b0cb900104b99984b6b218db81cd29371364a35251910160405180910390a45b95945050505050565b5080546000825560020290600052602060002090810190611bbc91905b8082111561492957600081556001810180547fffffffff000000000000000000000000000000000000000000000000000000001690556002016148eb565b5090565b60006020828403121561493f57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114612b1f57600080fd5b6001600160a01b0381168114611bbc57600080fd5b60008083601f84011261499657600080fd5b50813567ffffffffffffffff8111156149ae57600080fd5b6020830191508360208285010111156149c657600080fd5b9250929050565b600080600080600080600060a0888a0312156149e857600080fd5b87359650602088013595506040880135614a018161496f565b9450606088013567ffffffffffffffff80821115614a1e57600080fd5b614a2a8b838c01614984565b909650945060808a0135915080821115614a4357600080fd5b50614a508a828b01614984565b989b979a50959850939692959293505050565b600060208284031215614a7557600080fd5b8135612b1f8161496f565b8015158114611bbc57600080fd5b6000806000806000806000806000806101008b8d031215614aae57600080fd5b8a35995060208b0135985060408b0135614ac78161496f565b975060608b0135614ad78161496f565b965060808b0135955060a08b0135614aee81614a80565b945060c08b013567ffffffffffffffff80821115614b0b57600080fd5b614b178e838f01614984565b909650945060e08d0135915080821115614b3057600080fd5b50614b3d8d828e01614984565b915080935050809150509295989b9194979a5092959850565b600080600080600080600060c0888a031215614b7157600080fd5b8735965060208801359550604088013594506060880135614b918161496f565b93506080880135925060a088013567ffffffffffffffff811115614bb457600080fd5b614a508a828b01614984565b60008060408385031215614bd357600080fd5b823591506020830135614be58161496f565b809150509250929050565b600060208284031215614c0257600080fd5b5035919050565b60008060408385031215614c1c57600080fd5b8235614c278161496f565b91506020830135614be581614a80565b602080825282518282018190526000919060409081850190868401855b82811015614ca0578151805185528681015163ffffffff908116888701528682015116868601526060908101516001600160a01b03169085015260809093019290850190600101614c54565b5091979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff81118282101715614d0057614d00614cad565b60405290565b6040805190810167ffffffffffffffff81118282101715614d0057614d00614cad565b60405160e0810167ffffffffffffffff81118282101715614d0057614d00614cad565b604051601f8201601f1916810167ffffffffffffffff81118282101715614d7557614d75614cad565b604052919050565b600067ffffffffffffffff821115614d9757614d97614cad565b50601f01601f191660200190565b600082601f830112614db657600080fd5b8135614dc9614dc482614d7d565b614d4c565b818152846020838601011115614dde57600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600080600060e0888a031215614e1657600080fd5b8735965060208801359550604088013594506060880135614e368161496f565b93506080880135925060a0880135614e4d8161496f565b915060c088013567ffffffffffffffff811115614e6957600080fd5b614e758a828b01614da5565b91505092959891949750929550565b60008060408385031215614e9757600080fd5b8235614ea28161496f565b946020939093013593505050565b600080600080600080600080610100898b031215614ecd57600080fd5b8835614ed88161496f565b975060208901359650604089013595506060890135614ef68161496f565b94506080890135935060a0890135614f0d8161496f565b925060c089013567ffffffffffffffff80821115614f2a57600080fd5b614f368c838d01614da5565b935060e08b0135915080821115614f4c57600080fd5b50614f598b828c01614da5565b9150509295985092959890939650565b600060208284031215614f7b57600080fd5b8151612b1f81614a80565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561091c5761091c614f86565b600060208284031215614fda57600080fd5b8151612b1f8161496f565b600060208284031215614ff757600080fd5b5051919050565b60005b83811015615019578181015183820152602001615001565b50506000910152565b6000815180845261503a816020860160208601614ffe565b601f01601f19169290920160200192915050565b8481528360208201526001600160a01b038316604082015260a06060820152600060a082015260c06080820152600061508a60c0830184615022565b9695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600181815b8085111561511c57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561510257615102614f86565b8085161561510f57918102915b93841c93908002906150c8565b509250929050565b6000826151335750600161091c565b816151405750600061091c565b816001811461515657600281146151605761517c565b600191505061091c565b60ff84111561517157615171614f86565b50506001821b61091c565b5060208310610133831016604e8410600b841016171561519f575081810a61091c565b6151a983836150c3565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156151db576151db614f86565b029392505050565b6000612b1f8383615124565b8082018082111561091c5761091c614f86565b85815284602082015260a06040820152600061522160a0830186615022565b82810360608401526152338186615022565b9150506001600160a01b03831660808301529695505050505050565b60006101406001600160a01b03808b168452615298602085018b6001600160a01b0381511682526020810151602083015260408101516040830152606081015160608301525050565b8860a08501528760c085015280871660e085015250806101008401526152c081840186615022565b90508281036101208401526152d58185615022565b9a9950505050505050505050565b80516152ee8161496f565b919050565b6000610120828403121561530657600080fd5b61530e614cdc565b9050815181526020820151602082015260408201516040820152606082015160608201526080820151608082015260a082015160a082015260c082015160c082015261535c60e083016152e3565b60e082015261010080830151818301525092915050565b600067ffffffffffffffff82111561538d5761538d614cad565b5060051b60200190565b600082601f8301126153a857600080fd5b81516153b6614dc482614d7d565b8181528460208386010111156153cb57600080fd5b6119d1826020830160208701614ffe565b60008060008061018085870312156153f357600080fd5b6153fd86866152f3565b9350610120850151925061014085015167ffffffffffffffff8082111561542357600080fd5b818701915087601f83011261543757600080fd5b81516020615447614dc483615373565b82815260069290921b8401810191818101908b84111561546657600080fd5b948201945b838610156154b2576040868d0312156154845760008081fd5b61548c614d06565b86516154978161496f565b8152868401518482015282526040909501949082019061546b565b6101608b01519097509450505050808211156154cd57600080fd5b506154da87828801615397565b91505092959194509250565b80516001600160a01b031682526000610200602083810151858201526040808501518187015260608086015180516001600160a01b0316828901529283015160808801529082015160a087015281015160c086015250608083015180516001600160a01b031660e08601526020810151610100860152604081015161012086015260608101516101408601525060a083015161016085015260c08301516001600160a01b0381166101808601525060e08301518015156101a086015250610100830151816101c08601526155bc82860182615022565b9150506101208301518482036101e08601526148c58282615022565b602081526000612b1f60208301846154e6565b6060815260006155fe60608301866154e6565b90508360208301526001600160a01b0383166040830152949350505050565b60006001600160a01b03808a168352808916602084015287604084015286606084015260e0608084015261565460e0840187615022565b83810360a08501526156668187615022565b92505080841660c08401525098975050505050505050565b600080610140838503121561569257600080fd5b61569c84846152f3565b915061012083015190509250929050565b60006001600160a01b03808b16835289602084015288604084015287606084015286608084015260e060a08401528460e08401526101008587828601376000848701820152931660c083015250601f909201601f1916909101019695505050505050565b60006101008983528860208401526001600160a01b03808916604085015280881660608501525085608084015284151560a08401528060c0840152600081840152506101208060e08401526152d581840185615022565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156157a0576157a0614f86565b500290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261580a577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60006001600160a01b03808916835287602084015286604084015285606084015260c0608084015261584460c0840186615022565b915080841660a084015250979650505050505050565b6001600160a01b038616815284602082015283604082015260a06060820152600061588860a0830185615022565b8281036080840152610d3c8185615022565b60008060008061018085870312156158b157600080fd5b6158bb86866152f3565b9350610120850151925061014085015167ffffffffffffffff808211156158e157600080fd5b818701915087601f8301126158f557600080fd5b81516020615905614dc483615373565b82815260069290921b8401810191818101908b84111561592457600080fd5b948201945b838610156154b2576040868d0312156159425760008081fd5b61594a614d06565b86516159558161496f565b81528684015184820152825260409095019490820190615929565b80516001600160a01b0316825260006101e060208301516020850152604083015160408501526060830151606085015260808301516159dc60808601826001600160a01b0381511682526020810151602083015260408101516040830152606081015160608301525050565b5060a083015180516001600160a01b03908116610100878101919091526020830151610120880152604083015161014088015260609092015161016087015260c08501511661018086015260e08401516101a0860183905290615a4183870183615022565b9250808501519150508482036101c08601526148c58282615022565b602081526000612b1f6020830184615970565b6060815260006155fe6060830186615970565b60006020808385031215615a9657600080fd5b825167ffffffffffffffff811115615aad57600080fd5b8301601f81018513615abe57600080fd5b8051615acc614dc482615373565b81815260e09182028301840191848201919088841115615aeb57600080fd5b938501935b83851015615b815780858a031215615b085760008081fd5b615b10614d29565b8551615b1b81614a80565b815285870151615b2a81614a80565b818801526040868101519082015260608087015190820152608080870151615b518161496f565b9082015260a0868101519082015260c080870151615b6e8161496f565b9082015283529384019391850191615af0565b50979650505050505050565b6101208101615bee8286805115158252602081015115156020830152604081015160408301526060810151606083015260808101516001600160a01b03808216608085015260a083015160a08501528060c08401511660c085015250505050565b8360e08301526001600160a01b03831661010083015294935050505056fea26469706673582212209a0821b8d0e0d584f8a3d44469c86fb05dc17e11fce0e25a17cf53905ee054f064736f6c63430008100033", "deployedBytecode": "0x6080604052600436106101fe5760003560e01c80638b79543c1161011d578063c41c2f24116100b0578063df21a7dd1161007f578063f2fde38b11610064578063f2fde38b14610722578063fc0c546a14610742578063fe663f0f1461077657600080fd5b8063df21a7dd146106a0578063e5a6b10f146106ee57600080fd5b8063c41c2f2414610602578063d3419bf314610636578063d6dacc531461066a578063ddca3f431461068a57600080fd5b8063ad007d63116100ec578063ad007d631461053e578063b631b50014610572578063b7bad1b1146105a2578063bc8926e9146105e257600080fd5b80638b79543c146104985780638da5cb5b146104cc578063975057e7146104ea578063a32e1e961461051e57600080fd5b8063405b84fa11610195578063715018a611610164578063715018a6146104165780637258002c1461042b57806389701db51461044b5780638af560941461046b57600080fd5b8063405b84fa14610382578063637913ac146103a257806366248b86146103c257806369fe0e2d146103f657600080fd5b80632b267b4e116101d15780632b267b4e146102ae5780632bdfe004146102ce5780632d1a59031461031a578063313ce5671461034e57600080fd5b806301ffc9a7146102035780630cf8e858146102385780631982d6791461024d5780631ebc263f1461029b575b600080fd5b34801561020f57600080fd5b5061022361021e36600461492d565b610796565b60405190151581526020015b60405180910390f35b61024b6102463660046149cd565b610922565b005b34801561025957600080fd5b5061028d610268366004614a63565b507f000000000000000000000000000000000000000000000000000000000000000090565b60405190815260200161022f565b61028d6102a9366004614a8e565b610b23565b3480156102ba57600080fd5b5061028d6102c9366004614b56565b610d2c565b3480156102da57600080fd5b506103027f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161022f565b34801561032657600080fd5b5061028d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561035a57600080fd5b5061028d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561038e57600080fd5b5061028d61039d366004614bc0565b610d48565b3480156103ae57600080fd5b5061024b6103bd366004614a63565b6110c1565b3480156103ce57600080fd5b5061028d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561040257600080fd5b5061024b610411366004614bf0565b6111a6565b34801561042257600080fd5b5061024b611298565b34801561043757600080fd5b5061024b610446366004614c09565b611318565b34801561045757600080fd5b5061024b610466366004614bf0565b61140c565b34801561047757600080fd5b5061048b610486366004614bf0565b6116c0565b60405161022f9190614c37565b3480156104a457600080fd5b506103027f000000000000000000000000000000000000000000000000000000000000000081565b3480156104d857600080fd5b506000546001600160a01b0316610302565b3480156104f657600080fd5b506103027f000000000000000000000000000000000000000000000000000000000000000081565b34801561052a57600080fd5b5061028d610539366004614bf0565b611772565b34801561054a57600080fd5b506103027f000000000000000000000000000000000000000000000000000000000000000081565b34801561057e57600080fd5b5061022361058d366004614a63565b60046020526000908152604090205460ff1681565b3480156105ae57600080fd5b5061028d6105bd366004614a63565b507f000000000000000000000000000000000000000000000000000000000000000090565b3480156105ee57600080fd5b5061028d6105fd366004614dfb565b6119d9565b34801561060e57600080fd5b506103027f000000000000000000000000000000000000000000000000000000000000000081565b34801561064257600080fd5b506103027f000000000000000000000000000000000000000000000000000000000000000081565b34801561067657600080fd5b50600354610302906001600160a01b031681565b34801561069657600080fd5b5061028d60025481565b3480156106ac57600080fd5b506102236106bb366004614e84565b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161490565b3480156106fa57600080fd5b5061028d7f000000000000000000000000000000000000000000000000000000000000000081565b34801561072e57600080fd5b5061024b61073d366004614a63565b611aa9565b34801561074e57600080fd5b506103027f000000000000000000000000000000000000000000000000000000000000000081565b34801561078257600080fd5b5061028d610791366004614eb0565b611bbf565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167fedb527eb00000000000000000000000000000000000000000000000000000000148061082957507fffffffff0000000000000000000000000000000000000000000000000000000082167f2b267b4e00000000000000000000000000000000000000000000000000000000145b8061087557507fffffffff0000000000000000000000000000000000000000000000000000000082167fbc8926e900000000000000000000000000000000000000000000000000000000145b806108c157507fffffffff0000000000000000000000000000000000000000000000000000000082167ffe663f0f00000000000000000000000000000000000000000000000000000000145b8061090d57507fffffffff0000000000000000000000000000000000000000000000000000000082167fad007d6300000000000000000000000000000000000000000000000000000000145b8061091c575061091c82611bdf565b92915050565b6040517f6e49181f0000000000000000000000000000000000000000000000000000000081526004810188905230602482015287907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636e49181f90604401602060405180830381865afa1580156109a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109cc9190614f69565b610a02576040517fd8ead2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661eeee14610a8a573415610a6c576040517fbcfd35be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b47610a7833308a611cc2565b610a828147614fb5565b975050610a8e565b3496505b33600090815260046020908152604091829020548251601f8801839004830281018301909352868352610b19928b928b9260ff161591908a908a908190840183828082843760009201919091525050604080516020601f8c018190048102820181019092528a815292508a9150899081908401838280828437600092019190915250611cd192505050565b5050505050505050565b6040517f6e49181f000000000000000000000000000000000000000000000000000000008152600481018b90523060248201526000908b906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636e49181f90604401602060405180830381865afa158015610bac573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bd09190614f69565b610c06576040517fd8ead2c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661eeee14610c8e573415610c70576040517fbcfd35be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b47610c7c33308e611cc2565b610c868147614fb5565b9b5050610c92565b349a505b610d1c8b338e8c8c8c8c8c8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611ddb92505050565b9c9b505050505050505050505050565b6000610d3c88888887878761242d565b98975050505050505050565b6040517f6352211e000000000000000000000000000000000000000000000000000000008152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610dc9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ded9190614fc8565b836004610dfb8383836126e0565b6040517fdf21a7dd0000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301526024820188905286169063df21a7dd90604401602060405180830381865afa158015610e81573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea59190614f69565b610edb576040517f581010ed00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f6bb6a5ad000000000000000000000000000000000000000000000000000000008152600481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636bb6a5ad906024016020604051808303816000875af1158015610f5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f7f9190614fe5565b935083156110735760007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661eeee14610fc2576000610fc4565b845b604080516020810182526000815290517f0cf8e8580000000000000000000000000000000000000000000000000000000081529192506001600160a01b03881691630cf8e85891849161103f918c918b917f00000000000000000000000000000000000000000000000000000000000000009160040161504e565b6000604051808303818588803b15801561105857600080fd5b505af115801561106c573d6000803e3d6000fd5b5050505050505b604080518581523360208201526001600160a01b0387169188917fa7519e5f94697b7f53e97c5eb46a0c730a296ab686ab8fd333835c5f735784eb910160405180910390a350505092915050565b6000546001600160a01b0316331461113a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b600380547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040513381527f0a9a80fe9716605b3e52abb3d792d6a4e7816d6afc02a5a4ef023081feaf9f609060200160405180910390a250565b6000546001600160a01b0316331461121a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611131565b6302faf080811115611258576040517f45fbd9c100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002819055604080518281523360208201527fd7414e590e1cb532989ab2a34c8f4c2c17f7ab6f006efeeaef2e87cd5008c202910160405180910390a150565b6000546001600160a01b0316331461130c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611131565b61131660006128a4565b565b6000546001600160a01b0316331461138c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611131565b6001600160a01b03821660008181526004602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001685151590811790915591513381529192917fa2653e25a502c023a5830d0de847ef6f458387865b1f4f575d7594f9f2c0d71e910160405180910390a35050565b6040517f6352211e000000000000000000000000000000000000000000000000000000008152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa15801561148a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ae9190614fc8565b8160056114c36000546001600160a01b031690565b6001600160a01b0316336001600160a01b0316146114e38484848461290c565b600085815260016020908152604080832080548251818502810185019093528083529192909190849084015b8282101561158157600084815260209081902060408051608081018252600286029092018054835260019081015463ffffffff8082168587015264010000000082041692840192909252680100000000000000009091046001600160a01b03166060830152908352909201910161150f565b50505060008881526001602052604081209293506115a09291506148ce565b805160005b81811015610b1957600061161d8483815181106115c4576115c4615094565b6020026020010151600001518584815181106115e2576115e2615094565b60200260200101516020015163ffffffff1686858151811061160657611606615094565b60200260200101516040015163ffffffff16612ae0565b90506116468185848151811061163557611635615094565b602002602001015160600151612b26565b60011515818a7fcf0c92a2c6d7c42f488326b0cb900104b99984b6b218db81cd29371364a3525187868151811061167f5761167f615094565b602002602001015160600151336040516116af9291906001600160a01b0392831681529116602082015260400190565b60405180910390a4506001016115a5565b606060016000838152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b8282101561176757600084815260209081902060408051608081018252600286029092018054835260019081015463ffffffff8082168587015264010000000082041692840192909252680100000000000000009091046001600160a01b0316606083015290835290920191016116f5565b505050509050919050565b6040517fd49031c00000000000000000000000000000000000000000000000000000000081523060048201526024810182905260009081906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063d49031c090604401602060405180830381865afa1580156117fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061181f9190614fe5565b905060007f000000000000000000000000000000000000000000000000000000000000000060121461187c57611877827f00000000000000000000000000000000000000000000000000000000000000006012612d40565b61187e565b815b905060017f0000000000000000000000000000000000000000000000000000000000000000146119cf576119ca816118d77f0000000000000000000000000000000000000000000000000000000000000000600a6151e3565b6040517fa4d0caf20000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152600160248201527f000000000000000000000000000000000000000000000000000000000000000060448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a4d0caf290606401602060405180830381865afa1580156119a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119c59190614fe5565b612d9d565b6119d1565b805b949350505050565b6040517f6352211e000000000000000000000000000000000000000000000000000000008152600481018890526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015611a5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a7e9190614fc8565b886011611a8c8383836126e0565b611a9a8b8b8b8a8a8a612ea1565b9b9a5050505050505050505050565b6000546001600160a01b03163314611b1d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401611131565b6001600160a01b038116611bb3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401611131565b611bbc816128a4565b50565b600088886002611bd08383836126e0565b610d1c8c8c8c8b8b8b8b613112565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167fc07370e4000000000000000000000000000000000000000000000000000000001480611c7257507fffffffff0000000000000000000000000000000000000000000000000000000082167f2896000200000000000000000000000000000000000000000000000000000000145b8061091c57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000083161461091c565b611ccc8282613740565b505050565b600083611cdf576000611ce9565b611ce9868661388d565b90506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663e7c8e3e387611d2584896151ef565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815260048101929092526024820152604401600060405180830381600087803b158015611d7b57600080fd5b505af1158015611d8f573d6000803e3d6000fd5b50505050857f9ecaf7fc3dfffd6867c175d6e684b1f1e3aef019398ba8db2c1ffab4a09db2538683868633604051611dcb959493929190615202565b60405180910390a2505050505050565b60006001600160a01b038616611e1d576040517fa762251300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611e756040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b606060008060405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020018e81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000000000000000000000000000000000000000000081525090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632fa1b3918d838e7f00000000000000000000000000000000000000000000000000000000000000008f8d8d6040518863ffffffff1660e01b8152600401611f7e979695949392919061524f565b6000604051808303816000875af1158015611f9d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611fc591908101906153dc565b99509195509093509150811561212c576040517f5dd8f6aa000000000000000000000000000000000000000000000000000000008152600481018c90527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635dd8f6aa90602401602060405180830381865afa158015612053573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120779190614fc8565b6040517f8ae9c07b000000000000000000000000000000000000000000000000000000008152600481018d9052602481018490526001600160a01b038c8116604483015260c06064830152600060c48301528a15156084830152600160a48301529190911690638ae9c07b9060e4016020604051808303816000875af1158015612105573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121299190614fe5565b94505b88851015612166576040517f7b94612600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8251156123cf57600060405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020018f81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f0000000000000000000000000000000000000000000000000000000000000000815250905060006040518061014001604052808f6001600160a01b031681526020018e8152602001876020015181526020018481526020018381526020018881526020018d6001600160a01b031681526020018b151581526020018a815260200189815250905060008551905060005b818110156123ca57600087828151811061228257612282615094565b6020908102919091010151905060007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11127f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316016122e8575060208101515b60208083015160808701519091015281516040517fda9ee8b70000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063da9ee8b79083906123419089906004016155d8565b6000604051808303818588803b15801561235a57600080fd5b505af115801561236e573d6000803e3d6000fd5b505050505081600001516001600160a01b03167f16112c26e14efc4be6c690149aa5a1ba75160de245f60d2273e28adb277b9e12868460200151336040516123b8939291906155eb565b60405180910390a25050600101612266565b505050505b50505087816000015182602001517f133161f1c9161488f777ab9a26aae91d47c0d9a3fafb398960f138db02c737978c8b8f888b8b33604051612418979695949392919061561d565b60405180910390a45098975050505050505050565b6040517fc6644597000000000000000000000000000000000000000000000000000000008152600481018790526024810186905260448101859052600090819081906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c664459790606401610140604051808303816000875af11580156124c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124e7919061567e565b9150915085811015612525576040517fb01493c100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f6352211e000000000000000000000000000000000000000000000000000000008152600481018a90526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa1580156125a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125ca9190614fc8565b90506000806002546000146125e7576125e28c613cc4565b6125ed565b633b9aca005b90506000806126238e88602001517f00000000000000000000000000000000000000000000000000000000000000008987613e62565b92509050633b9aca00831461263757908101905b81600003612646576000612653565b6126538e8884888761470f565b9350801561267f576126688160025485612ae0565b6126729082614fb5565b975061267f30868a611cc2565b5050508a846000015185602001517f24352f49df447b14e0e08a323625c663d865ce20c343c4638af12e1dc48aa760858e88878c8f8f336040516126ca9897969594939291906156ad565b60405180910390a4505050509695505050505050565b336001600160a01b038416148015906127ad57506040517fc161c93f0000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b03848116602483015260448201849052606482018390527f0000000000000000000000000000000000000000000000000000000000000000169063c161c93f90608401602060405180830381865afa158015612787573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127ab9190614f69565b155b801561286d57506040517fc161c93f0000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b03848116602483015260006044830152606482018390527f0000000000000000000000000000000000000000000000000000000000000000169063c161c93f90608401602060405180830381865afa158015612847573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061286b9190614f69565b155b15611ccc576040517f075fd2b100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b801580156129235750336001600160a01b03851614155b80156129e357506040517fc161c93f0000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b03858116602483015260448201859052606482018490527f0000000000000000000000000000000000000000000000000000000000000000169063c161c93f90608401602060405180830381865afa1580156129bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129e19190614f69565b155b8015612aa357506040517fc161c93f0000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b03858116602483015260006044830152606482018490527f0000000000000000000000000000000000000000000000000000000000000000169063c161c93f90608401602060405180830381865afa158015612a7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612aa19190614f69565b155b15612ada576040517f075fd2b100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b600080612af28484633b9aca00612d9d565b612afc9085614fb5565b9050612b1185633b9aca006119c581856151ef565b612b1b9086614fb5565b9150505b9392505050565b6040517f86202650000000000000000000000000000000000000000000000000000000008152600160048201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660248301526000917f000000000000000000000000000000000000000000000000000000000000000090911690638620265090604401602060405180830381865afa158015612bd1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bf59190614fc8565b9050306001600160a01b03821603612c3757612ada83306001856000806040518060200160405280600081525060405180602001604052806000815250611ddb565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661eeee14612c72576000612c74565b835b60408051602081018252600080825291517f1ebc263f0000000000000000000000000000000000000000000000000000000081529293506001600160a01b03851692631ebc263f928592612cf6926001928b927f0000000000000000000000000000000000000000000000000000000000000000928c92918291600401615711565b60206040518083038185885af1158015612d14573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190612d399190614fe5565b5050505050565b6000828203612d50575082612b1f565b82821115612d7e57612d628383614fb5565b612d6d90600a6151e3565b612d779085615768565b9050612b1f565b612d888284614fb5565b612d9390600a6151e3565b612d7790856157d4565b600080807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff85870985870292508281108382030391505080600003612df557838281612deb57612deb6157a5565b0492505050612b1f565b838110612e38576040517f773cc18c0000000000000000000000000000000000000000000000000000000081526004810182905260248101859052604401611131565b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b6040517f25386715000000000000000000000000000000000000000000000000000000008152600481018790526024810186905260448101859052600090819081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632538671590606401610140604051808303816000875af1158015612f37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f5b919061567e565b9150915085811015612f99576040517fb01493c100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517f6352211e000000000000000000000000000000000000000000000000000000008152600481018a905260009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa15801561301c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130409190614fc8565b905060006002546000148061306457503360009081526004602052604090205460ff165b613076576130718c613cc4565b61307c565b633b9aca005b9050633b9aca00811461309b576130968c8686858561470f565b61309e565b60005b808503965092508383146130b7576130b7308988611cc2565b50505088826000015183602001517f8657a0c05a68a912c23c1bd00124afaa8c669063b046bd9bfd22b21d573c5e6d888c86898b336040516130fe9695949392919061580f565b60405180910390a450509695505050505050565b60006001600160a01b038416613154576040517ff74a1b6600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6131ac6040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b6040517fa2df1f950000000000000000000000000000000000000000000000000000000081526060906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a2df1f959061321c908d908d908d908b908b9060040161585a565b6000604051808303816000875af115801561323b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613263919081019061589a565b97509094509092509050868310156132a7576040517ff896960b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87156133e9576040517f5dd8f6aa000000000000000000000000000000000000000000000000000000008152600481018a90527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635dd8f6aa90602401602060405180830381865afa15801561332b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061334f9190614fc8565b6040517f1665bc0f0000000000000000000000000000000000000000000000000000000081526001600160a01b038c81166004830152602482018c9052604482018b905260a06064830152600060a4830181905260848301529190911690631665bc0f9060c401600060405180830381600087803b1580156133d057600080fd5b505af11580156133e4573d6000803e3d6000fd5b505050505b8051156136d457600060405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602001600081526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f0000000000000000000000000000000000000000000000000000000000000000815250905060006040518061012001604052808d6001600160a01b031681526020018c8152602001856020015181526020018b815260200160405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020018881526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000008152508152602001838152602001896001600160a01b0316815260200188815260200187815250905060008351905060005b818110156136cf57600085828151811061358757613587615094565b6020908102919091010151905060007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff11127f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316016135ed575060208101515b60208083015160a08701519091015281516040517f2b13c58f0000000000000000000000000000000000000000000000000000000081526001600160a01b0390911690632b13c58f908390613646908990600401615a5d565b6000604051808303818588803b15801561365f57600080fd5b505af1158015613673573d6000803e3d6000fd5b505050505081600001516001600160a01b03167f54b3744c489f40987dd2726ca12131243334e8292f567389f761c5a432d813e4868460200151336040516136bd93929190615a70565b60405180910390a2505060010161356b565b505050505b5081156136e6576136e6308684611cc2565b87816000015182602001517f2be10f2a0203c77d0fcaa9fd6484a8a1d6904de31cd820587f60c1c8c338c8148c898c888b8b3360405161372c979695949392919061561d565b60405180910390a450979650505050505050565b804710156137aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401611131565b6000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146137f7576040519150601f19603f3d011682016040523d82523d6000602084013e6137fc565b606091505b5050905080611ccc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401611131565b600082815260016020908152604080832080548251818502810185019093528083528493849084015b8282101561392857600084815260209081902060408051608081018252600286029092018054835260019081015463ffffffff8082168587015264010000000082041692840192909252680100000000000000009091046001600160a01b0316606083015290835290920191016138b6565b50505060008681526001602052604081209293506139479291506148ce565b8051839060005b81811015613c7c5782600003613a3e576000878152600160205260409020845185908390811061398057613980615094565b60209081029190910181015182546001818101855560009485529383902082516002909202019081559181015191909201805460408401516060909401516001600160a01b031668010000000000000000027fffffffff0000000000000000000000000000000000000000ffffffffffffffff63ffffffff958616640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000090931695909416949094171791909116919091179055613c74565b838181518110613a5057613a50615094565b6020026020010151600001518310613ae457838181518110613a7457613a74615094565b60200260200101516000015183039250613adb848281518110613a9957613a99615094565b602002602001015160000151858381518110613ab757613ab7615094565b60200260200101516020015163ffffffff1686848151811061160657611606615094565b85019450613c74565b60016000888152602001908152602001600020604051806080016040528085878581518110613b1557613b15615094565b602002602001015160000151038152602001868481518110613b3957613b39615094565b60200260200101516020015163ffffffff168152602001868481518110613b6257613b62615094565b60200260200101516040015163ffffffff168152602001868481518110613b8b57613b8b615094565b6020908102919091018101516060908101516001600160a01b039081169093528454600181810187556000968752958390208551600290920201908155918401519190940180546040850151949095015190921668010000000000000000027fffffffff0000000000000000000000000000000000000000ffffffffffffffff63ffffffff948516640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909616949092169390931793909317929092161790558351613c6b908490869084908110613ab757613ab7615094565b85019450600092505b60010161394e565b50604080518381523360208201528591879189917f59860d79d97c1fce2be7f987915c631471f4b08f671200463cc40a3380194ffb910160405180910390a450505092915050565b6040517f86202650000000000000000000000000000000000000000000000000000000008152600160048201526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116602483015260009182917f00000000000000000000000000000000000000000000000000000000000000001690638620265090604401602060405180830381865afa158015613d6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d939190614fc8565b6001600160a01b031603613dac5750633b9aca00919050565b6003546001600160a01b031615613e5a576003546040517f77695896000000000000000000000000000000000000000000000000000000008152600481018490526001600160a01b0390911690637769589690602401602060405180830381865afa925050508015613e3b575060408051601f3d908101601f19168201909252613e3891810190614fe5565b60015b613e4757506000919050565b633b9aca008111613e585792915050565b505b506000919050565b6040517f69e11cc50000000000000000000000000000000000000000000000000000000081526004810186905260248101859052604481018490528290600090633b9aca009082907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906369e11cc590606401600060405180830381865afa158015613efb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613f239190810190615a83565b905060005b8151811015614702576000828281518110613f4557613f45615094565b60200260200101519050600084826040015114613f7457613f6f898360400151633b9aca00612d9d565b613f76565b865b9050816040015185613f889190614fb5565b9450600081156146b65760c08301516001600160a01b0316156141c457633b9aca00891480613fd3575060c08301516001600160a01b031660009081526004602052604090205460ff165b15613fdf575080613ffd565b613fec826002548b612ae0565b82039050613ffa82886151ef565b96505b60006040518060c001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020018381526020017f000000000000000000000000000000000000000000000000000000000000000081526020018f81526020018d81526020018581525090508360c001516001600160a01b0316639d740bfa61eeee6001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316146140cc5760006140ce565b835b604080517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815285516001600160a01b039081166004830152602080880151602484015283880151604484015260608089015160648501526080808a0151608486015260a0808b01518051151560a488015293840151151560c48701529583015160e48601529082015161010485015281015182166101248401529283015161014483015260c090920151909116610164820152610184016000604051808303818588803b1580156141a557600080fd5b505af11580156141b9573d6000803e3d6000fd5b5050505050506146b0565b60608301511561464f5760608301516040517f862026500000000000000000000000000000000000000000000000000000000081526000916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163862026509161426d917f0000000000000000000000000000000000000000000000000000000000000000906004019182526001600160a01b0316602082015260400190565b602060405180830381865afa15801561428a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142ae9190614fc8565b90506001600160a01b0381166142f0576040517f6921234300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b306001600160a01b038216036143d1576040805160208082528183019092528493506000916020820181803683370190505090508e60405160200161433791815260200190565b60405160208183030381529060405290508460200151156143785761437385606001518460006040518060200160405280600081525085611cd1565b6143cb565b6143c98330876060015160006001600160a01b031689608001516001600160a01b0316036143a657336143ac565b88608001515b60008a600001516040518060200160405280600081525088611ddb565b505b50614649565b633b9aca008a14806143fb57506001600160a01b03811660009081526004602052604090205460ff165b1561440857829150614426565b614415836002548c612ae0565b8303915061442383896151ef565b97505b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661eeee14614461576000614463565b825b604080516020808252818301909252919250600091906020820181803683370190505090508f60405160200161449b91815260200190565b604051602081830303815290604052905085602001511561455d5760608601516040517f0cf8e8580000000000000000000000000000000000000000000000000000000081526001600160a01b03851691630cf8e8589185916145269189907f000000000000000000000000000000000000000000000000000000000000000090889060040161504e565b6000604051808303818588803b15801561453f57600080fd5b505af1158015614553573d6000803e3d6000fd5b5050505050614646565b826001600160a01b0316631ebc263f838860600151877f000000000000000000000000000000000000000000000000000000000000000060006001600160a01b03168c608001516001600160a01b0316036145b857336145be565b8b608001515b8c516040517fffffffff0000000000000000000000000000000000000000000000000000000060e089901b16815261460195949392916000918b90600401615711565b60206040518083038185885af115801561461f573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906146449190614fe5565b505b50505b506146b0565b60808301516000906001600160a01b031661466a5733614670565b83608001515b9050633b9aca008a03614685578291506146a3565b614692836002548c612ae0565b830391506146a083896151ef565b97505b6146ae308284611cc2565b505b81880397505b8a8c8e7f2a1f2df21da49f011c6165709ae4b279f8d6d7cffe9043c582352882d8c9698b8685336040516146ec93929190615b8d565b60405180910390a4836001019350505050613f28565b5050509550959350505050565b600061471e8460025484612ae0565b610100860151909150604f1c60019081160361487257600086815260016020818152604080842081516080810183528981526002805463ffffffff9081168387019081528a82168487019081526001600160a01b03808e16606087019081528754808c018955978c5298909a209451958402909401948555519390960180549251955190971668010000000000000000027fffffffff0000000000000000000000000000000000000000ffffffffffffffff958716640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909316939096169290921717929092169290921790925590549051859088907f77813be0661650ddc1a5193ff2837df4162b251cb432651e2c060c3fc39756be90614865908790899033909283526001600160a01b03918216602084015216604082015260600190565b60405180910390a46148c5565b61487c8184612b26565b604080516001600160a01b0385168152336020820152600091839189917fcf0c92a2c6d7c42f488326b0cb900104b99984b6b218db81cd29371364a35251910160405180910390a45b95945050505050565b5080546000825560020290600052602060002090810190611bbc91905b8082111561492957600081556001810180547fffffffff000000000000000000000000000000000000000000000000000000001690556002016148eb565b5090565b60006020828403121561493f57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114612b1f57600080fd5b6001600160a01b0381168114611bbc57600080fd5b60008083601f84011261499657600080fd5b50813567ffffffffffffffff8111156149ae57600080fd5b6020830191508360208285010111156149c657600080fd5b9250929050565b600080600080600080600060a0888a0312156149e857600080fd5b87359650602088013595506040880135614a018161496f565b9450606088013567ffffffffffffffff80821115614a1e57600080fd5b614a2a8b838c01614984565b909650945060808a0135915080821115614a4357600080fd5b50614a508a828b01614984565b989b979a50959850939692959293505050565b600060208284031215614a7557600080fd5b8135612b1f8161496f565b8015158114611bbc57600080fd5b6000806000806000806000806000806101008b8d031215614aae57600080fd5b8a35995060208b0135985060408b0135614ac78161496f565b975060608b0135614ad78161496f565b965060808b0135955060a08b0135614aee81614a80565b945060c08b013567ffffffffffffffff80821115614b0b57600080fd5b614b178e838f01614984565b909650945060e08d0135915080821115614b3057600080fd5b50614b3d8d828e01614984565b915080935050809150509295989b9194979a5092959850565b600080600080600080600060c0888a031215614b7157600080fd5b8735965060208801359550604088013594506060880135614b918161496f565b93506080880135925060a088013567ffffffffffffffff811115614bb457600080fd5b614a508a828b01614984565b60008060408385031215614bd357600080fd5b823591506020830135614be58161496f565b809150509250929050565b600060208284031215614c0257600080fd5b5035919050565b60008060408385031215614c1c57600080fd5b8235614c278161496f565b91506020830135614be581614a80565b602080825282518282018190526000919060409081850190868401855b82811015614ca0578151805185528681015163ffffffff908116888701528682015116868601526060908101516001600160a01b03169085015260809093019290850190600101614c54565b5091979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff81118282101715614d0057614d00614cad565b60405290565b6040805190810167ffffffffffffffff81118282101715614d0057614d00614cad565b60405160e0810167ffffffffffffffff81118282101715614d0057614d00614cad565b604051601f8201601f1916810167ffffffffffffffff81118282101715614d7557614d75614cad565b604052919050565b600067ffffffffffffffff821115614d9757614d97614cad565b50601f01601f191660200190565b600082601f830112614db657600080fd5b8135614dc9614dc482614d7d565b614d4c565b818152846020838601011115614dde57600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600080600060e0888a031215614e1657600080fd5b8735965060208801359550604088013594506060880135614e368161496f565b93506080880135925060a0880135614e4d8161496f565b915060c088013567ffffffffffffffff811115614e6957600080fd5b614e758a828b01614da5565b91505092959891949750929550565b60008060408385031215614e9757600080fd5b8235614ea28161496f565b946020939093013593505050565b600080600080600080600080610100898b031215614ecd57600080fd5b8835614ed88161496f565b975060208901359650604089013595506060890135614ef68161496f565b94506080890135935060a0890135614f0d8161496f565b925060c089013567ffffffffffffffff80821115614f2a57600080fd5b614f368c838d01614da5565b935060e08b0135915080821115614f4c57600080fd5b50614f598b828c01614da5565b9150509295985092959890939650565b600060208284031215614f7b57600080fd5b8151612b1f81614a80565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561091c5761091c614f86565b600060208284031215614fda57600080fd5b8151612b1f8161496f565b600060208284031215614ff757600080fd5b5051919050565b60005b83811015615019578181015183820152602001615001565b50506000910152565b6000815180845261503a816020860160208601614ffe565b601f01601f19169290920160200192915050565b8481528360208201526001600160a01b038316604082015260a06060820152600060a082015260c06080820152600061508a60c0830184615022565b9695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600181815b8085111561511c57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561510257615102614f86565b8085161561510f57918102915b93841c93908002906150c8565b509250929050565b6000826151335750600161091c565b816151405750600061091c565b816001811461515657600281146151605761517c565b600191505061091c565b60ff84111561517157615171614f86565b50506001821b61091c565b5060208310610133831016604e8410600b841016171561519f575081810a61091c565b6151a983836150c3565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156151db576151db614f86565b029392505050565b6000612b1f8383615124565b8082018082111561091c5761091c614f86565b85815284602082015260a06040820152600061522160a0830186615022565b82810360608401526152338186615022565b9150506001600160a01b03831660808301529695505050505050565b60006101406001600160a01b03808b168452615298602085018b6001600160a01b0381511682526020810151602083015260408101516040830152606081015160608301525050565b8860a08501528760c085015280871660e085015250806101008401526152c081840186615022565b90508281036101208401526152d58185615022565b9a9950505050505050505050565b80516152ee8161496f565b919050565b6000610120828403121561530657600080fd5b61530e614cdc565b9050815181526020820151602082015260408201516040820152606082015160608201526080820151608082015260a082015160a082015260c082015160c082015261535c60e083016152e3565b60e082015261010080830151818301525092915050565b600067ffffffffffffffff82111561538d5761538d614cad565b5060051b60200190565b600082601f8301126153a857600080fd5b81516153b6614dc482614d7d565b8181528460208386010111156153cb57600080fd5b6119d1826020830160208701614ffe565b60008060008061018085870312156153f357600080fd5b6153fd86866152f3565b9350610120850151925061014085015167ffffffffffffffff8082111561542357600080fd5b818701915087601f83011261543757600080fd5b81516020615447614dc483615373565b82815260069290921b8401810191818101908b84111561546657600080fd5b948201945b838610156154b2576040868d0312156154845760008081fd5b61548c614d06565b86516154978161496f565b8152868401518482015282526040909501949082019061546b565b6101608b01519097509450505050808211156154cd57600080fd5b506154da87828801615397565b91505092959194509250565b80516001600160a01b031682526000610200602083810151858201526040808501518187015260608086015180516001600160a01b0316828901529283015160808801529082015160a087015281015160c086015250608083015180516001600160a01b031660e08601526020810151610100860152604081015161012086015260608101516101408601525060a083015161016085015260c08301516001600160a01b0381166101808601525060e08301518015156101a086015250610100830151816101c08601526155bc82860182615022565b9150506101208301518482036101e08601526148c58282615022565b602081526000612b1f60208301846154e6565b6060815260006155fe60608301866154e6565b90508360208301526001600160a01b0383166040830152949350505050565b60006001600160a01b03808a168352808916602084015287604084015286606084015260e0608084015261565460e0840187615022565b83810360a08501526156668187615022565b92505080841660c08401525098975050505050505050565b600080610140838503121561569257600080fd5b61569c84846152f3565b915061012083015190509250929050565b60006001600160a01b03808b16835289602084015288604084015287606084015286608084015260e060a08401528460e08401526101008587828601376000848701820152931660c083015250601f909201601f1916909101019695505050505050565b60006101008983528860208401526001600160a01b03808916604085015280881660608501525085608084015284151560a08401528060c0840152600081840152506101208060e08401526152d581840185615022565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156157a0576157a0614f86565b500290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261580a577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60006001600160a01b03808916835287602084015286604084015285606084015260c0608084015261584460c0840186615022565b915080841660a084015250979650505050505050565b6001600160a01b038616815284602082015283604082015260a06060820152600061588860a0830185615022565b8281036080840152610d3c8185615022565b60008060008061018085870312156158b157600080fd5b6158bb86866152f3565b9350610120850151925061014085015167ffffffffffffffff808211156158e157600080fd5b818701915087601f8301126158f557600080fd5b81516020615905614dc483615373565b82815260069290921b8401810191818101908b84111561592457600080fd5b948201945b838610156154b2576040868d0312156159425760008081fd5b61594a614d06565b86516159558161496f565b81528684015184820152825260409095019490820190615929565b80516001600160a01b0316825260006101e060208301516020850152604083015160408501526060830151606085015260808301516159dc60808601826001600160a01b0381511682526020810151602083015260408101516040830152606081015160608301525050565b5060a083015180516001600160a01b03908116610100878101919091526020830151610120880152604083015161014088015260609092015161016087015260c08501511661018086015260e08401516101a0860183905290615a4183870183615022565b9250808501519150508482036101c08601526148c58282615022565b602081526000612b1f6020830184615970565b6060815260006155fe6060830186615970565b60006020808385031215615a9657600080fd5b825167ffffffffffffffff811115615aad57600080fd5b8301601f81018513615abe57600080fd5b8051615acc614dc482615373565b81815260e09182028301840191848201919088841115615aeb57600080fd5b938501935b83851015615b815780858a031215615b085760008081fd5b615b10614d29565b8551615b1b81614a80565b815285870151615b2a81614a80565b818801526040868101519082015260608087015190820152608080870151615b518161496f565b9082015260a0868101519082015260c080870151615b6e8161496f565b9082015283529384019391850191615af0565b50979650505050505050565b6101208101615bee8286805115158252602081015115156020830152604081015160408301526060810151606083015260808101516001600160a01b03808216608085015260a083015160a08501528060c08401511660c085015250505050565b8360e08301526001600160a01b03831661010083015294935050505056fea26469706673582212209a0821b8d0e0d584f8a3d44469c86fb05dc17e11fce0e25a17cf53905ee054f064736f6c63430008100033", "devdoc": { diff --git a/deployments/mainnet/JBETHPaymentTerminal3_1.json b/deployments/mainnet/JBETHPaymentTerminal3_1.json index ecef97c97..ffbdc8974 100644 --- a/deployments/mainnet/JBETHPaymentTerminal3_1.json +++ b/deployments/mainnet/JBETHPaymentTerminal3_1.json @@ -1883,7 +1883,7 @@ ], "numDeployments": 1, "solcInputHash": "60cd95dca5edde649565e9f7f43720b6", - "metadata": "{\"compiler\":{\"version\":\"0.8.16+commit.07a7930e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_baseWeightCurrency\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBOperatorStore\",\"name\":\"_operatorStore\",\"type\":\"address\"},{\"internalType\":\"contract IJBProjects\",\"name\":\"_projects\",\"type\":\"address\"},{\"internalType\":\"contract IJBDirectory\",\"name\":\"_directory\",\"type\":\"address\"},{\"internalType\":\"contract IJBSplitsStore\",\"name\":\"_splitsStore\",\"type\":\"address\"},{\"internalType\":\"contract IJBPrices\",\"name\":\"_prices\",\"type\":\"address\"},{\"internalType\":\"contract IJBSingleTokenPaymentTerminalStore\",\"name\":\"_store\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"FEE_TOO_HIGH\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INADEQUATE_DISTRIBUTION_AMOUNT\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INADEQUATE_RECLAIM_AMOUNT\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INADEQUATE_TOKEN_COUNT\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NO_MSG_VALUE_ALLOWED\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PAY_TO_ZERO_ADDRESS\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"prod1\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"denominator\",\"type\":\"uint256\"}],\"name\":\"PRBMath__MulDivOverflow\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PROJECT_TERMINAL_MISMATCH\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"REDEEM_TO_ZERO_ADDRESS\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TERMINAL_IN_SPLIT_ZERO_ADDRESS\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TERMINAL_TOKENS_INCOMPATIBLE\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UNAUTHORIZED\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"refundedFees\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AddToBalance\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IJBPayDelegate\",\"name\":\"delegate\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"currentFundingCycleConfiguration\",\"type\":\"uint256\"},{\"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\"},{\"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\":\"forwardedAmount\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"projectTokenCount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"preferClaimedTokens\",\"type\":\"bool\"},{\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"struct JBDidPayData\",\"name\":\"data\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"delegatedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"DelegateDidPay\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IJBRedemptionDelegate\",\"name\":\"delegate\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"currentFundingCycleConfiguration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"projectTokenCount\",\"type\":\"uint256\"},{\"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\":\"reclaimedAmount\",\"type\":\"tuple\"},{\"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\":\"forwardedAmount\",\"type\":\"tuple\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"struct JBDidRedeemData\",\"name\":\"data\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"delegatedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"DelegateDidRedeem\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleConfiguration\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleNumber\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"distributedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"beneficiaryDistributionAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"DistributePayouts\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"domain\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"group\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"preferClaimed\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"preferAddToBalance\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"percent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"lockedUntil\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBSplitAllocator\",\"name\":\"allocator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"struct JBSplit\",\"name\":\"split\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"netAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"DistributeToPayoutSplit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"feeProjectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"reason\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"FeeReverted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"feeDiscount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"HoldFee\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"contract IJBPaymentTerminal\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Migrate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleConfiguration\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleNumber\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"beneficiaryTokenCount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Pay\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"preferClaimed\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"preferAddToBalance\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"percent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"lockedUntil\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBSplitAllocator\",\"name\":\"allocator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"struct JBSplit\",\"name\":\"split\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"reason\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"PayoutReverted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"wasHeld\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"ProcessFee\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleConfiguration\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleNumber\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenCount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"reclaimedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"RedeemTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"refundedFees\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"leftoverAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"RefundHeldFees\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"SetFee\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IJBFeeGauge\",\"name\":\"feeGauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"SetFeeGauge\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"addrs\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"flag\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"SetFeelessAddress\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleConfiguration\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleNumber\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"distributedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"netDistributedamount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"UseAllowance\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"}],\"name\":\"acceptsToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"addToBalanceOf\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_shouldRefundHeldFees\",\"type\":\"bool\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"addToBalanceOf\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"baseWeightCurrency\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currency\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"currencyForToken\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"}],\"name\":\"currentEthOverflowOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"decimalsForToken\",\"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\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_currency\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_minReturnedTokens\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"distributePayoutsOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"netLeftoverDistributionAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"feeGauge\",\"outputs\":[{\"internalType\":\"contract IJBFeeGauge\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"}],\"name\":\"heldFeesOf\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"fee\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"feeDiscount\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"internalType\":\"struct JBFee[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isFeelessAddress\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBPaymentTerminal\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"migrate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"operatorStore\",\"outputs\":[{\"internalType\":\"contract IJBOperatorStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_minReturnedTokens\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"_preferClaimedTokens\",\"type\":\"bool\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"pay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"payoutSplitsGroup\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"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\"}],\"name\":\"processFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"projects\",\"outputs\":[{\"internalType\":\"contract IJBProjects\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_holder\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_tokenCount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_minReturnedTokens\",\"type\":\"uint256\"},{\"internalType\":\"address payable\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"redeemTokensOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"reclaimAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_fee\",\"type\":\"uint256\"}],\"name\":\"setFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IJBFeeGauge\",\"name\":\"_feeGauge\",\"type\":\"address\"}],\"name\":\"setFeeGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_flag\",\"type\":\"bool\"}],\"name\":\"setFeelessAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"splitsStore\",\"outputs\":[{\"internalType\":\"contract IJBSplitsStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"store\",\"outputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminalStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_currency\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_minReturnedTokens\",\"type\":\"uint256\"},{\"internalType\":\"address payable\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"useAllowanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"netDistributedAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Inherits from - JBPayoutRedemptionPaymentTerminal3_1: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\",\"kind\":\"dev\",\"methods\":{\"acceptsToken(address,uint256)\":{\"params\":{\"_projectId\":\"The project ID to check for token acceptance.\",\"_token\":\"The token to check if this terminal accepts or not.\"},\"returns\":{\"_0\":\"The flag.\"}},\"addToBalanceOf(uint256,uint256,address,bool,string,bytes)\":{\"params\":{\"_amount\":\"The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\",\"_memo\":\"A memo to pass along to the emitted event.\",\"_metadata\":\"Extra data to pass along to the emitted event.\",\"_projectId\":\"The ID of the project to which the funds received belong.\",\"_shouldRefundHeldFees\":\"A flag indicating if held fees should be refunded based on the amount being added.\",\"_token\":\"The token being paid. This terminal ignores this property since it only manages one currency. \"}},\"addToBalanceOf(uint256,uint256,address,string,bytes)\":{\"params\":{\"_amount\":\"The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\",\"_memo\":\"A memo to pass along to the emitted event.\",\"_metadata\":\"Extra data to pass along to the emitted event.\",\"_projectId\":\"The ID of the project to which the funds received belong.\",\"_token\":\"The token being paid. This terminal ignores this property since it only manages one currency. \"}},\"constructor\":{\"params\":{\"_baseWeightCurrency\":\"The currency to base token issuance on.\",\"_directory\":\"A contract storing directories of terminals and controllers for each project.\",\"_operatorStore\":\"A contract storing operator assignments.\",\"_owner\":\"The address that will own this contract.\",\"_prices\":\"A contract that exposes price feeds.\",\"_projects\":\"A contract which mints ERC-721's that represent project ownership and transfers.\",\"_splitsStore\":\"A contract that stores splits for each project.\",\"_store\":\"A contract that stores the terminal's data.\"}},\"currencyForToken(address)\":{\"params\":{\"_token\":\"The token to check for the currency of.\"},\"returns\":{\"_0\":\"The currency index.\"}},\"currentEthOverflowOf(uint256)\":{\"details\":\"The current overflow is represented as a fixed point number with 18 decimals.\",\"params\":{\"_projectId\":\"The ID of the project to get overflow for.\"},\"returns\":{\"_0\":\"The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\"}},\"decimalsForToken(address)\":{\"params\":{\"_token\":\"The token to check for the decimals of.\"},\"returns\":{\"_0\":\"The number of decimals for the token.\"}},\"distributePayoutsOf(uint256,uint256,uint256,address,uint256,bytes)\":{\"details\":\"Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\",\"params\":{\"_amount\":\"The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\",\"_currency\":\"The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\",\"_metadata\":\"Bytes to send along to the emitted event, if provided.\",\"_minReturnedTokens\":\"The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\",\"_projectId\":\"The ID of the project having its payouts distributed.\",\"_token\":\"The token being distributed. This terminal ignores this property since it only manages one token. \"},\"returns\":{\"netLeftoverDistributionAmount\":\"The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\"}},\"heldFeesOf(uint256)\":{\"params\":{\"_projectId\":\"The ID of the project for which fees are being held.\"},\"returns\":{\"_0\":\"An array of fees that are being held.\"}},\"migrate(uint256,address)\":{\"details\":\"Only a project's owner or a designated operator can migrate it.\",\"params\":{\"_projectId\":\"The ID of the project being migrated.\",\"_to\":\"The terminal contract that will gain the project's funds.\"},\"returns\":{\"balance\":\"The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pay(uint256,uint256,address,address,uint256,bool,string,bytes)\":{\"params\":{\"_amount\":\"The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\",\"_beneficiary\":\"The address to mint tokens for and pass along to the funding cycle's data source and delegate.\",\"_memo\":\"A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\",\"_metadata\":\"Bytes to send along to the data source, delegate, and emitted event, if provided.\",\"_minReturnedTokens\":\"The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\",\"_preferClaimedTokens\":\"A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\",\"_projectId\":\"The ID of the project being paid.\",\"_token\":\"The token being paid. This terminal ignores this property since it only manages one token. \"},\"returns\":{\"_0\":\"The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\"}},\"processFees(uint256)\":{\"details\":\"Only a project owner, an operator, or the contract's owner can process held fees.\",\"params\":{\"_projectId\":\"The ID of the project whos held fees should be processed.\"}},\"redeemTokensOf(address,uint256,uint256,address,uint256,address,string,bytes)\":{\"details\":\"Only a token holder or a designated operator can redeem its tokens.\",\"params\":{\"_beneficiary\":\"The address to send the terminal tokens to.\",\"_holder\":\"The account to redeem tokens for.\",\"_memo\":\"A memo to pass along to the emitted event.\",\"_metadata\":\"Bytes to send along to the data source, delegate, and emitted event, if provided.\",\"_minReturnedTokens\":\"The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\",\"_projectId\":\"The ID of the project to which the tokens being redeemed belong.\",\"_token\":\"The token being reclaimed. This terminal ignores this property since it only manages one token. \",\"_tokenCount\":\"The number of project tokens to redeem, as a fixed point number with 18 decimals.\"},\"returns\":{\"reclaimAmount\":\"The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"setFee(uint256)\":{\"details\":\"Only the owner of this contract can change the fee.\",\"params\":{\"_fee\":\"The new fee, out of MAX_FEE.\"}},\"setFeeGauge(address)\":{\"details\":\"Only the owner of this contract can change the fee gauge.\",\"params\":{\"_feeGauge\":\"The new fee gauge.\"}},\"setFeelessAddress(address,bool)\":{\"details\":\"Only the owner of this contract can set addresses as feeless.\",\"params\":{\"_address\":\"The address that can be paid towards while still bypassing fees.\",\"_flag\":\"A flag indicating whether the terminal should be feeless or not.\"}},\"supportsInterface(bytes4)\":{\"details\":\" See {IERC165-supportsInterface}.\",\"params\":{\"_interfaceId\":\"The ID of the interface to check for adherance to.\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"useAllowanceOf(uint256,uint256,uint256,address,uint256,address,string,bytes)\":{\"details\":\"Only a project's owner or a designated operator can use its allowance.Incurs the protocol fee.\",\"params\":{\"_amount\":\"The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\",\"_beneficiary\":\"The address to send the funds to.\",\"_currency\":\"The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\",\"_memo\":\"A memo to pass along to the emitted event.\",\"_metadata\":\"Bytes to send along to the emitted event, if provided.\",\"_minReturnedTokens\":\"The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\",\"_projectId\":\"The ID of the project to use the allowance of.\",\"_token\":\"The token being distributed. This terminal ignores this property since it only manages one token. \"},\"returns\":{\"netDistributedAmount\":\"The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\"}}},\"version\":1},\"userdoc\":{\"errors\":{\"PRBMath__MulDivOverflow(uint256,uint256)\":[{\"notice\":\"Emitted when the result overflows uint256.\"}]},\"kind\":\"user\",\"methods\":{\"acceptsToken(address,uint256)\":{\"notice\":\"A flag indicating if this terminal accepts the specified token.\"},\"addToBalanceOf(uint256,uint256,address,bool,string,bytes)\":{\"notice\":\"Receives funds belonging to the specified project.\"},\"addToBalanceOf(uint256,uint256,address,string,bytes)\":{\"notice\":\"Receives funds belonging to the specified project.\"},\"baseWeightCurrency()\":{\"notice\":\"The currency to base token issuance on.\"},\"currency()\":{\"notice\":\"The currency to use when resolving price feeds for this terminal.\"},\"currencyForToken(address)\":{\"notice\":\"The currency that should be used for the specified token.\"},\"currentEthOverflowOf(uint256)\":{\"notice\":\"Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\"},\"decimals()\":{\"notice\":\"The number of decimals the token fixed point amounts are expected to have.\"},\"decimalsForToken(address)\":{\"notice\":\"The decimals that should be used in fixed number accounting for the specified token.\"},\"directory()\":{\"notice\":\"The directory of terminals and controllers for projects.\"},\"distributePayoutsOf(uint256,uint256,uint256,address,uint256,bytes)\":{\"notice\":\"Distributes payouts for a project with the distribution limit of its current funding cycle.\"},\"fee()\":{\"notice\":\"The platform fee percent.\"},\"feeGauge()\":{\"notice\":\"The data source that returns a discount to apply to a project's fee.\"},\"heldFeesOf(uint256)\":{\"notice\":\"The fees that are currently being held to be processed later for each project.\"},\"isFeelessAddress(address)\":{\"notice\":\"Addresses that can be paid towards from this terminal without incurring a fee.\"},\"migrate(uint256,address)\":{\"notice\":\"Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\"},\"operatorStore()\":{\"notice\":\" A contract storing operator assignments.\"},\"pay(uint256,uint256,address,address,uint256,bool,string,bytes)\":{\"notice\":\"Contribute tokens to a project.\"},\"payoutSplitsGroup()\":{\"notice\":\"The group that payout splits coming from this terminal are identified by.\"},\"prices()\":{\"notice\":\"The contract that exposes price feeds.\"},\"processFees(uint256)\":{\"notice\":\"Process any fees that are being held for the project.\"},\"projects()\":{\"notice\":\"Mints ERC-721's that represent project ownership and transfers.\"},\"redeemTokensOf(address,uint256,uint256,address,uint256,address,string,bytes)\":{\"notice\":\"Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\"},\"setFee(uint256)\":{\"notice\":\"Allows the fee to be updated.\"},\"setFeeGauge(address)\":{\"notice\":\"Allows the fee gauge to be updated.\"},\"setFeelessAddress(address,bool)\":{\"notice\":\"Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\"},\"splitsStore()\":{\"notice\":\"The contract that stores splits for each project.\"},\"store()\":{\"notice\":\"The contract that stores and manages the terminal's data.\"},\"supportsInterface(bytes4)\":{\"notice\":\"Indicates if this contract adheres to the specified interface.\"},\"token()\":{\"notice\":\"The token that this terminal accepts.\"},\"useAllowanceOf(uint256,uint256,uint256,address,uint256,address,string,bytes)\":{\"notice\":\"Allows a project to send funds from its overflow up to the preconfigured allowance.\"}},\"notice\":\"Manages all inflows and outflows of ETH funds into the protocol ecosystem.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/JBETHPaymentTerminal3_1.sol\":\"JBETHPaymentTerminal3_1\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0x24e0364e503a9bbde94c715d26573a76f14cd2a202d45f96f52134ab806b67b9\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool _approved) external;\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x516a22876c1fab47f49b1bc22b4614491cd05338af8bd2e7b382da090a079990\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3777e696b62134e6177440dbe6e6601c0c156a443f57167194b67e75527439de\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165Checker.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Library used to query support of an interface declared via {IERC165}.\\n *\\n * Note that these functions return the actual result of the query: they do not\\n * `revert` if an interface is not supported. It is up to the caller to decide\\n * what to do in these cases.\\n */\\nlibrary ERC165Checker {\\n // As per the EIP-165 spec, no interface should ever match 0xffffffff\\n bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;\\n\\n /**\\n * @dev Returns true if `account` supports the {IERC165} interface,\\n */\\n function supportsERC165(address account) internal view returns (bool) {\\n // Any contract that implements ERC165 must explicitly indicate support of\\n // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid\\n return\\n _supportsERC165Interface(account, type(IERC165).interfaceId) &&\\n !_supportsERC165Interface(account, _INTERFACE_ID_INVALID);\\n }\\n\\n /**\\n * @dev Returns true if `account` supports the interface defined by\\n * `interfaceId`. Support for {IERC165} itself is queried automatically.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {\\n // query support of both ERC165 as per the spec and support of _interfaceId\\n return supportsERC165(account) && _supportsERC165Interface(account, interfaceId);\\n }\\n\\n /**\\n * @dev Returns a boolean array where each value corresponds to the\\n * interfaces passed in and whether they're supported or not. This allows\\n * you to batch check interfaces for a contract where your expectation\\n * is that some interfaces may not be supported.\\n *\\n * See {IERC165-supportsInterface}.\\n *\\n * _Available since v3.4._\\n */\\n function getSupportedInterfaces(address account, bytes4[] memory interfaceIds)\\n internal\\n view\\n returns (bool[] memory)\\n {\\n // an array of booleans corresponding to interfaceIds and whether they're supported or not\\n bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);\\n\\n // query support of ERC165 itself\\n if (supportsERC165(account)) {\\n // query support of each interface in interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n interfaceIdsSupported[i] = _supportsERC165Interface(account, interfaceIds[i]);\\n }\\n }\\n\\n return interfaceIdsSupported;\\n }\\n\\n /**\\n * @dev Returns true if `account` supports all the interfaces defined in\\n * `interfaceIds`. Support for {IERC165} itself is queried automatically.\\n *\\n * Batch-querying can lead to gas savings by skipping repeated checks for\\n * {IERC165} support.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {\\n // query support of ERC165 itself\\n if (!supportsERC165(account)) {\\n return false;\\n }\\n\\n // query support of each interface in _interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n if (!_supportsERC165Interface(account, interfaceIds[i])) {\\n return false;\\n }\\n }\\n\\n // all interfaces supported\\n return true;\\n }\\n\\n /**\\n * @notice Query if a contract implements an interface, does not check ERC165 support\\n * @param account The address of the contract to query for support of an interface\\n * @param interfaceId The interface identifier, as specified in ERC-165\\n * @return true if the contract at account indicates support of the interface with\\n * identifier interfaceId, false otherwise\\n * @dev Assumes that account contains a contract that supports ERC165, otherwise\\n * the behavior of this method is undefined. This precondition can be checked\\n * with {supportsERC165}.\\n * Interface identification is specified in ERC-165.\\n */\\n function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) {\\n bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);\\n (bool success, bytes memory result) = account.staticcall{gas: 30000}(encodedParams);\\n if (result.length < 32) return false;\\n return success && abi.decode(result, (bool));\\n }\\n}\\n\",\"keccak256\":\"0xf7291d7213336b00ee7edbf7cd5034778dd7b0bda2a7489e664f1e5cacc6c24e\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"@paulrberg/contracts/math/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\nimport \\\"prb-math/contracts/PRBMath.sol\\\";\\n\",\"keccak256\":\"0x42821345981bc0434a90ba2268a2f5278dfe9e38166981d72fc7f3b776a29495\",\"license\":\"Unlicense\"},\"contracts/JBETHPaymentTerminal3_1.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport '@openzeppelin/contracts/utils/Address.sol';\\nimport './abstract/JBPayoutRedemptionPaymentTerminal3_1.sol';\\nimport './libraries/JBSplitsGroups.sol';\\n\\n/**\\n @notice\\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\\n\\n @dev\\n Inherits from -\\n JBPayoutRedemptionPaymentTerminal3_1: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\\n*/\\ncontract JBETHPaymentTerminal3_1 is JBPayoutRedemptionPaymentTerminal3_1 {\\n //*********************************************************************//\\n // -------------------------- internal views ------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Checks the balance of tokens in this contract.\\n\\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\\n */\\n function _balance() internal view override returns (uint256) {\\n return address(this).balance;\\n }\\n\\n //*********************************************************************//\\n // -------------------------- constructor ---------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @param _baseWeightCurrency The currency to base token issuance on.\\n @param _operatorStore A contract storing operator assignments.\\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\\n @param _directory A contract storing directories of terminals and controllers for each project.\\n @param _splitsStore A contract that stores splits for each project.\\n @param _prices A contract that exposes price feeds.\\n @param _store A contract that stores the terminal's data.\\n @param _owner The address that will own this contract.\\n */\\n constructor(\\n uint256 _baseWeightCurrency,\\n IJBOperatorStore _operatorStore,\\n IJBProjects _projects,\\n IJBDirectory _directory,\\n IJBSplitsStore _splitsStore,\\n IJBPrices _prices,\\n IJBSingleTokenPaymentTerminalStore _store,\\n address _owner\\n )\\n JBPayoutRedemptionPaymentTerminal3_1(\\n JBTokens.ETH,\\n 18, // 18 decimals.\\n JBCurrencies.ETH,\\n _baseWeightCurrency,\\n JBSplitsGroups.ETH_PAYOUT,\\n _operatorStore,\\n _projects,\\n _directory,\\n _splitsStore,\\n _prices,\\n _store,\\n _owner\\n )\\n // solhint-disable-next-line no-empty-blocks\\n {\\n\\n }\\n\\n //*********************************************************************//\\n // ---------------------- internal transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Transfers tokens.\\n\\n @param _from The address from which the transfer should originate.\\n @param _to The address to which the transfer should go.\\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\\n */\\n function _transferFrom(\\n address _from,\\n address payable _to,\\n uint256 _amount\\n ) internal override {\\n _from; // Prevents unused var compiler and natspec complaints.\\n\\n Address.sendValue(_to, _amount);\\n }\\n}\\n\",\"keccak256\":\"0x51cd7cb442d31c0cede341af67b5ed069d467a72cb812dad5c0763f51960bbe5\",\"license\":\"MIT\"},\"contracts/abstract/JBOperatable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport './../interfaces/IJBOperatable.sol';\\n\\n/** \\n @notice\\n Modifiers to allow access to functions based on the message sender's operator status.\\n\\n @dev\\n Adheres to -\\n IJBOperatable: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n*/\\nabstract contract JBOperatable is IJBOperatable {\\n //*********************************************************************//\\n // --------------------------- custom errors -------------------------- //\\n //*********************************************************************//\\n error UNAUTHORIZED();\\n\\n //*********************************************************************//\\n // ---------------------------- modifiers ---------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Only allows the speficied account or an operator of the account to proceed. \\n\\n @param _account The account to check for.\\n @param _domain The domain namespace to look for an operator within. \\n @param _permissionIndex The index of the permission to check for. \\n */\\n modifier requirePermission(\\n address _account,\\n uint256 _domain,\\n uint256 _permissionIndex\\n ) {\\n _requirePermission(_account, _domain, _permissionIndex);\\n _;\\n }\\n\\n /** \\n @notice\\n Only allows the speficied account, an operator of the account to proceed, or a truthy override flag. \\n\\n @param _account The account to check for.\\n @param _domain The domain namespace to look for an operator within. \\n @param _permissionIndex The index of the permission to check for. \\n @param _override A condition to force allowance for.\\n */\\n modifier requirePermissionAllowingOverride(\\n address _account,\\n uint256 _domain,\\n uint256 _permissionIndex,\\n bool _override\\n ) {\\n _requirePermissionAllowingOverride(_account, _domain, _permissionIndex, _override);\\n _;\\n }\\n\\n //*********************************************************************//\\n // ---------------- public immutable stored properties --------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n A contract storing operator assignments.\\n */\\n IJBOperatorStore public immutable override operatorStore;\\n\\n //*********************************************************************//\\n // -------------------------- constructor ---------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @param _operatorStore A contract storing operator assignments.\\n */\\n constructor(IJBOperatorStore _operatorStore) {\\n operatorStore = _operatorStore;\\n }\\n\\n //*********************************************************************//\\n // -------------------------- internal views ------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Require the message sender is either the account or has the specified permission.\\n\\n @param _account The account to allow.\\n @param _domain The domain namespace within which the permission index will be checked.\\n @param _permissionIndex The permission index that an operator must have within the specified domain to be allowed.\\n */\\n function _requirePermission(\\n address _account,\\n uint256 _domain,\\n uint256 _permissionIndex\\n ) internal view {\\n if (\\n msg.sender != _account &&\\n !operatorStore.hasPermission(msg.sender, _account, _domain, _permissionIndex) &&\\n !operatorStore.hasPermission(msg.sender, _account, 0, _permissionIndex)\\n ) revert UNAUTHORIZED();\\n }\\n\\n /** \\n @notice\\n Require the message sender is either the account, has the specified permission, or the override condition is true.\\n\\n @param _account The account to allow.\\n @param _domain The domain namespace within which the permission index will be checked.\\n @param _domain The permission index that an operator must have within the specified domain to be allowed.\\n @param _override The override condition to allow.\\n */\\n function _requirePermissionAllowingOverride(\\n address _account,\\n uint256 _domain,\\n uint256 _permissionIndex,\\n bool _override\\n ) internal view {\\n if (\\n !_override &&\\n msg.sender != _account &&\\n !operatorStore.hasPermission(msg.sender, _account, _domain, _permissionIndex) &&\\n !operatorStore.hasPermission(msg.sender, _account, 0, _permissionIndex)\\n ) revert UNAUTHORIZED();\\n }\\n}\\n\",\"keccak256\":\"0x9e62cac5c464eb973f881cf6c373b95aab31d2ddbeb048ee7ad82b5c9ab28add\",\"license\":\"MIT\"},\"contracts/abstract/JBPayoutRedemptionPaymentTerminal3_1.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport '@openzeppelin/contracts/access/Ownable.sol';\\nimport '@openzeppelin/contracts/utils/introspection/ERC165Checker.sol';\\nimport '@paulrberg/contracts/math/PRBMath.sol';\\nimport './../interfaces/IJBController.sol';\\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal3_1.sol';\\nimport './../libraries/JBConstants.sol';\\nimport './../libraries/JBCurrencies.sol';\\nimport './../libraries/JBFixedPointNumber.sol';\\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\\nimport './../libraries/JBOperations.sol';\\nimport './../libraries/JBTokens.sol';\\nimport './../structs/JBPayDelegateAllocation.sol';\\nimport './../structs/JBTokenAmount.sol';\\nimport './JBOperatable.sol';\\nimport './JBSingleTokenPaymentTerminal.sol';\\n\\n/**\\n @notice\\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\\n\\n @dev\\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\\n\\n @dev\\n Adheres to -\\n IJBPayoutRedemptionPaymentTerminal3_1: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n\\n @dev\\n Inherits from -\\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\\n*/\\nabstract contract JBPayoutRedemptionPaymentTerminal3_1 is\\n JBSingleTokenPaymentTerminal,\\n JBOperatable,\\n Ownable,\\n IJBPayoutRedemptionPaymentTerminal3_1\\n{\\n // A library that parses the packed funding cycle metadata into a friendlier format.\\n using JBFundingCycleMetadataResolver for JBFundingCycle;\\n\\n //*********************************************************************//\\n // --------------------------- custom errors ------------------------- //\\n //*********************************************************************//\\n error FEE_TOO_HIGH();\\n error INADEQUATE_DISTRIBUTION_AMOUNT();\\n error INADEQUATE_RECLAIM_AMOUNT();\\n error INADEQUATE_TOKEN_COUNT();\\n error NO_MSG_VALUE_ALLOWED();\\n error PAY_TO_ZERO_ADDRESS();\\n error PROJECT_TERMINAL_MISMATCH();\\n error REDEEM_TO_ZERO_ADDRESS();\\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\\n error TERMINAL_TOKENS_INCOMPATIBLE();\\n\\n //*********************************************************************//\\n // ---------------------------- modifiers ---------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n A modifier that verifies this terminal is a terminal of provided project ID.\\n */\\n modifier isTerminalOf(uint256 _projectId) {\\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\\n _;\\n }\\n\\n //*********************************************************************//\\n // --------------------- internal stored constants ------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Maximum fee that can be set for a funding cycle configuration.\\n\\n @dev\\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\\n */\\n uint256 internal constant _FEE_CAP = 50_000_000;\\n\\n /**\\n @notice\\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\\n */\\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\\n\\n //*********************************************************************//\\n // --------------------- internal stored properties ------------------ //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Fees that are being held to be processed later.\\n\\n _projectId The ID of the project for which fees are being held.\\n */\\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\\n\\n //*********************************************************************//\\n // ---------------- public immutable stored properties --------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Mints ERC-721's that represent project ownership and transfers.\\n */\\n IJBProjects public immutable override projects;\\n\\n /**\\n @notice\\n The directory of terminals and controllers for projects.\\n */\\n IJBDirectory public immutable override directory;\\n\\n /**\\n @notice\\n The contract that stores splits for each project.\\n */\\n IJBSplitsStore public immutable override splitsStore;\\n\\n /**\\n @notice\\n The contract that exposes price feeds.\\n */\\n IJBPrices public immutable override prices;\\n\\n /**\\n @notice\\n The contract that stores and manages the terminal's data.\\n */\\n IJBSingleTokenPaymentTerminalStore public immutable override store;\\n\\n /**\\n @notice\\n The currency to base token issuance on.\\n\\n @dev\\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\\n */\\n uint256 public immutable override baseWeightCurrency;\\n\\n /**\\n @notice\\n The group that payout splits coming from this terminal are identified by.\\n */\\n uint256 public immutable override payoutSplitsGroup;\\n\\n //*********************************************************************//\\n // --------------------- public stored properties -------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The platform fee percent.\\n\\n @dev\\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\\n */\\n uint256 public override fee = 25_000_000; // 2.5%\\n\\n /**\\n @notice\\n The data source that returns a discount to apply to a project's fee.\\n */\\n IJBFeeGauge public override feeGauge;\\n\\n /**\\n @notice\\n Addresses that can be paid towards from this terminal without incurring a fee.\\n\\n @dev\\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\\n\\n _address The address that can be paid toward.\\n */\\n mapping(address => bool) public override isFeelessAddress;\\n\\n //*********************************************************************//\\n // ------------------------- external views -------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\\n\\n @dev\\n The current overflow is represented as a fixed point number with 18 decimals.\\n\\n @param _projectId The ID of the project to get overflow for.\\n\\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\\n */\\n function currentEthOverflowOf(uint256 _projectId)\\n external\\n view\\n virtual\\n override\\n returns (uint256)\\n {\\n // Get this terminal's current overflow.\\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\\n\\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\\n uint256 _adjustedOverflow = (decimals == 18)\\n ? _overflow\\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\\n\\n // Return the amount converted to ETH.\\n return\\n (currency == JBCurrencies.ETH)\\n ? _adjustedOverflow\\n : PRBMath.mulDiv(\\n _adjustedOverflow,\\n 10**decimals,\\n prices.priceFor(currency, JBCurrencies.ETH, decimals)\\n );\\n }\\n\\n /**\\n @notice\\n The fees that are currently being held to be processed later for each project.\\n\\n @param _projectId The ID of the project for which fees are being held.\\n\\n @return An array of fees that are being held.\\n */\\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\\n return _heldFeesOf[_projectId];\\n }\\n\\n //*********************************************************************//\\n // -------------------------- public views --------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Indicates if this contract adheres to the specified interface.\\n\\n @dev \\n See {IERC165-supportsInterface}.\\n\\n @param _interfaceId The ID of the interface to check for adherance to.\\n */\\n function supportsInterface(bytes4 _interfaceId)\\n public\\n view\\n virtual\\n override(JBSingleTokenPaymentTerminal, IERC165)\\n returns (bool)\\n {\\n return\\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal3_1).interfaceId ||\\n _interfaceId == type(IJBPayoutTerminal3_1).interfaceId ||\\n _interfaceId == type(IJBAllowanceTerminal3_1).interfaceId ||\\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\\n _interfaceId == type(IJBOperatable).interfaceId ||\\n super.supportsInterface(_interfaceId);\\n }\\n\\n //*********************************************************************//\\n // -------------------------- internal views ------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Checks the balance of tokens in this contract.\\n\\n @return The contract's balance.\\n */\\n function _balance() internal view virtual returns (uint256);\\n\\n //*********************************************************************//\\n // -------------------------- constructor ---------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @param _token The token that this terminal manages.\\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\\n @param _currency The currency that this terminal's token adheres to for price feeds.\\n @param _baseWeightCurrency The currency to base token issuance on.\\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\\n @param _operatorStore A contract storing operator assignments.\\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\\n @param _directory A contract storing directories of terminals and controllers for each project.\\n @param _splitsStore A contract that stores splits for each project.\\n @param _prices A contract that exposes price feeds.\\n @param _store A contract that stores the terminal's data.\\n @param _owner The address that will own this contract.\\n */\\n constructor(\\n // payable constructor save the gas used to check msg.value==0\\n address _token,\\n uint256 _decimals,\\n uint256 _currency,\\n uint256 _baseWeightCurrency,\\n uint256 _payoutSplitsGroup,\\n IJBOperatorStore _operatorStore,\\n IJBProjects _projects,\\n IJBDirectory _directory,\\n IJBSplitsStore _splitsStore,\\n IJBPrices _prices,\\n IJBSingleTokenPaymentTerminalStore _store,\\n address _owner\\n )\\n payable\\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\\n JBOperatable(_operatorStore)\\n {\\n baseWeightCurrency = _baseWeightCurrency;\\n payoutSplitsGroup = _payoutSplitsGroup;\\n projects = _projects;\\n directory = _directory;\\n splitsStore = _splitsStore;\\n prices = _prices;\\n store = _store;\\n\\n transferOwnership(_owner);\\n }\\n\\n //*********************************************************************//\\n // ---------------------- external transactions ---------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Contribute tokens to a project.\\n\\n @param _projectId The ID of the project being paid.\\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\\n\\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\\n */\\n function pay(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n // ETH shouldn't be sent if this terminal's token isn't ETH.\\n if (token != JBTokens.ETH) {\\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\\n\\n // Get a reference to the balance before receiving tokens.\\n uint256 _balanceBefore = _balance();\\n\\n // Transfer tokens to this terminal from the msg sender.\\n _transferFrom(msg.sender, payable(address(this)), _amount);\\n\\n // The amount should reflect the change in balance.\\n _amount = _balance() - _balanceBefore;\\n }\\n // If this terminal's token is ETH, override _amount with msg.value.\\n else _amount = msg.value;\\n\\n return\\n _pay(\\n _amount,\\n msg.sender,\\n _projectId,\\n _beneficiary,\\n _minReturnedTokens,\\n _preferClaimedTokens,\\n _memo,\\n _metadata\\n );\\n }\\n\\n /**\\n @notice\\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\\n\\n @dev\\n Only a token holder or a designated operator can redeem its tokens.\\n\\n @param _holder The account to redeem tokens for.\\n @param _projectId The ID of the project to which the tokens being redeemed belong.\\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\\n @param _beneficiary The address to send the terminal tokens to.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\\n\\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\\n */\\n function redeemTokensOf(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n address _token,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string memory _memo,\\n bytes memory _metadata\\n )\\n external\\n virtual\\n override\\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\\n returns (uint256 reclaimAmount)\\n {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n return\\n _redeemTokensOf(\\n _holder,\\n _projectId,\\n _tokenCount,\\n _minReturnedTokens,\\n _beneficiary,\\n _memo,\\n _metadata\\n );\\n }\\n\\n /**\\n @notice\\n Distributes payouts for a project with the distribution limit of its current funding cycle.\\n\\n @dev\\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\\n\\n @dev\\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\\n\\n @dev\\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\\n\\n @param _projectId The ID of the project having its payouts distributed.\\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\\n @param _metadata Bytes to send along to the emitted event, if provided.\\n\\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\\n */\\n function distributePayoutsOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n address _token,\\n uint256 _minReturnedTokens,\\n bytes calldata _metadata\\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _metadata);\\n }\\n\\n /**\\n @notice\\n Allows a project to send funds from its overflow up to the preconfigured allowance.\\n\\n @dev\\n Only a project's owner or a designated operator can use its allowance.\\n\\n @dev\\n Incurs the protocol fee.\\n\\n @param _projectId The ID of the project to use the allowance of.\\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\\n @param _beneficiary The address to send the funds to.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Bytes to send along to the emitted event, if provided.\\n\\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\\n */\\n function useAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n address _token,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string memory _memo,\\n bytes calldata _metadata\\n )\\n external\\n virtual\\n override\\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\\n returns (uint256 netDistributedAmount)\\n {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n return\\n _useAllowanceOf(\\n _projectId,\\n _amount,\\n _currency,\\n _minReturnedTokens,\\n _beneficiary,\\n _memo,\\n _metadata\\n );\\n }\\n\\n /**\\n @notice\\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\\n\\n @dev\\n Only a project's owner or a designated operator can migrate it.\\n\\n @param _projectId The ID of the project being migrated.\\n @param _to The terminal contract that will gain the project's funds.\\n\\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\\n */\\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\\n external\\n virtual\\n override\\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\\n returns (uint256 balance)\\n {\\n // The terminal being migrated to must accept the same token as this terminal.\\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\\n\\n // Record the migration in the store.\\n balance = store.recordMigration(_projectId);\\n\\n // Transfer the balance if needed.\\n if (balance > 0) {\\n // Trigger any inherited pre-transfer logic.\\n _beforeTransferTo(address(_to), balance);\\n\\n // If this terminal's token is ETH, send it in msg.value.\\n uint256 _payableValue = token == JBTokens.ETH ? balance : 0;\\n\\n // Withdraw the balance to transfer to the new terminal;\\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\\n }\\n\\n emit Migrate(_projectId, _to, balance, msg.sender);\\n }\\n\\n /**\\n @notice\\n Receives funds belonging to the specified project.\\n\\n @param _projectId The ID of the project to which the funds received belong.\\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Extra data to pass along to the emitted event.\\n */\\n function addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable virtual override isTerminalOf(_projectId) {\\n // Do not refund held fees by default.\\n addToBalanceOf(_projectId, _amount, _token, false, _memo, _metadata);\\n }\\n\\n /**\\n @notice\\n Process any fees that are being held for the project.\\n\\n @dev\\n Only a project owner, an operator, or the contract's owner can process held fees.\\n\\n @param _projectId The ID of the project whos held fees should be processed.\\n */\\n function processFees(uint256 _projectId)\\n external\\n virtual\\n override\\n requirePermissionAllowingOverride(\\n projects.ownerOf(_projectId),\\n _projectId,\\n JBOperations.PROCESS_FEES,\\n msg.sender == owner()\\n )\\n {\\n // Get a reference to the project's held fees.\\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\\n\\n // Delete the held fees.\\n delete _heldFeesOf[_projectId];\\n\\n // Push array length in stack\\n uint256 _heldFeeLength = _heldFees.length;\\n\\n // Process each fee.\\n for (uint256 _i; _i < _heldFeeLength; ) {\\n // Get the fee amount.\\n uint256 _amount = _feeAmount(\\n _heldFees[_i].amount,\\n _heldFees[_i].fee,\\n _heldFees[_i].feeDiscount\\n );\\n\\n // Process the fee.\\n _processFee(_amount, _heldFees[_i].beneficiary, _projectId);\\n\\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n\\n /**\\n @notice\\n Allows the fee to be updated.\\n\\n @dev\\n Only the owner of this contract can change the fee.\\n\\n @param _fee The new fee, out of MAX_FEE.\\n */\\n function setFee(uint256 _fee) external virtual override onlyOwner {\\n // The provided fee must be within the max.\\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\\n\\n // Store the new fee.\\n fee = _fee;\\n\\n emit SetFee(_fee, msg.sender);\\n }\\n\\n /**\\n @notice\\n Allows the fee gauge to be updated.\\n\\n @dev\\n Only the owner of this contract can change the fee gauge.\\n\\n @param _feeGauge The new fee gauge.\\n */\\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\\n // Store the new fee gauge.\\n feeGauge = _feeGauge;\\n\\n emit SetFeeGauge(_feeGauge, msg.sender);\\n }\\n\\n /**\\n @notice\\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\\n\\n @dev\\n Only the owner of this contract can set addresses as feeless.\\n\\n @param _address The address that can be paid towards while still bypassing fees.\\n @param _flag A flag indicating whether the terminal should be feeless or not.\\n */\\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\\n // Set the flag value.\\n isFeelessAddress[_address] = _flag;\\n\\n emit SetFeelessAddress(_address, _flag, msg.sender);\\n }\\n\\n //*********************************************************************//\\n // ----------------------- public transactions ----------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Receives funds belonging to the specified project.\\n\\n @param _projectId The ID of the project to which the funds received belong.\\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Extra data to pass along to the emitted event.\\n */\\n function addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n bool _shouldRefundHeldFees,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) public payable virtual override isTerminalOf(_projectId) {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\\n if (token != JBTokens.ETH) {\\n // Amount must be greater than 0.\\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\\n\\n // Get a reference to the balance before receiving tokens.\\n uint256 _balanceBefore = _balance();\\n\\n // Transfer tokens to this terminal from the msg sender.\\n _transferFrom(msg.sender, payable(address(this)), _amount);\\n\\n // The amount should reflect the change in balance.\\n _amount = _balance() - _balanceBefore;\\n }\\n // If the terminal's token is ETH, override `_amount` with msg.value.\\n else _amount = msg.value;\\n\\n // Add to balance.\\n _addToBalanceOf(_projectId, _amount, _shouldRefundHeldFees, _memo, _metadata);\\n }\\n\\n //*********************************************************************//\\n // ---------------------- internal transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Transfers tokens.\\n\\n @param _from The address from which the transfer should originate.\\n @param _to The address to which the transfer should go.\\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\\n */\\n function _transferFrom(\\n address _from,\\n address payable _to,\\n uint256 _amount\\n ) internal virtual {\\n _from; // Prevents unused var compiler and natspec complaints.\\n _to; // Prevents unused var compiler and natspec complaints.\\n _amount; // Prevents unused var compiler and natspec complaints.\\n }\\n\\n /** \\n @notice\\n Logic to be triggered before transferring tokens from this terminal.\\n\\n @param _to The address to which the transfer is going.\\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\\n */\\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\\n _to; // Prevents unused var compiler and natspec complaints.\\n _amount; // Prevents unused var compiler and natspec complaints.\\n }\\n\\n /** \\n @notice\\n Logic to be triggered if a transfer should be undone\\n\\n @param _to The address to which the transfer went.\\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\\n */\\n function _cancelTransferTo(address _to, uint256 _amount) internal virtual {\\n _to; // Prevents unused var compiler and natspec complaints.\\n _amount; // Prevents unused var compiler and natspec complaints.\\n }\\n\\n /**\\n @notice\\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\\n\\n @dev\\n Only a token holder or a designated operator can redeem its tokens.\\n\\n @param _holder The account to redeem tokens for.\\n @param _projectId The ID of the project to which the tokens being redeemed belong.\\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\\n @param _beneficiary The address to send the terminal tokens to.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\\n\\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\\n */\\n function _redeemTokensOf(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string memory _memo,\\n bytes memory _metadata\\n ) internal returns (uint256 reclaimAmount) {\\n // Can't send reclaimed funds to the zero address.\\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\\n\\n // Define variables that will be needed outside the scoped section below.\\n // Keep a reference to the funding cycle during which the redemption is being made.\\n JBFundingCycle memory _fundingCycle;\\n\\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\\n {\\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\\n\\n // Record the redemption.\\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\\n _holder,\\n _projectId,\\n _tokenCount,\\n _memo,\\n _metadata\\n );\\n\\n // The amount being reclaimed must be at least as much as was expected.\\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\\n\\n // Burn the project tokens.\\n if (_tokenCount > 0)\\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\\n _holder,\\n _projectId,\\n _tokenCount,\\n '',\\n false\\n );\\n\\n // If delegate allocations were specified by the data source, fulfill them.\\n if (_delegateAllocations.length != 0) {\\n // Keep a reference to the token amount being forwarded to the delegate.\\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\\n\\n JBDidRedeemData memory _data = JBDidRedeemData(\\n _holder,\\n _projectId,\\n _fundingCycle.configuration,\\n _tokenCount,\\n JBTokenAmount(token, reclaimAmount, decimals, currency),\\n _forwardedAmount,\\n _beneficiary,\\n _memo,\\n _metadata\\n );\\n\\n uint256 _numDelegates = _delegateAllocations.length;\\n\\n for (uint256 _i; _i < _numDelegates; ) {\\n // Get a reference to the delegate being iterated on.\\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\\n\\n // Trigger any inherited pre-transfer logic.\\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\\n\\n // Keep track of the msg.value to use in the delegate call\\n uint256 _payableValue;\\n\\n // If this terminal's token is ETH, send it in msg.value.\\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\\n\\n // Pass the correct token forwardedAmount to the delegate\\n _data.forwardedAmount.value = _delegateAllocation.amount;\\n\\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\\n\\n emit DelegateDidRedeem(\\n _delegateAllocation.delegate,\\n _data,\\n _delegateAllocation.amount,\\n msg.sender\\n );\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n }\\n\\n // Send the reclaimed funds to the beneficiary.\\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\\n\\n emit RedeemTokens(\\n _fundingCycle.configuration,\\n _fundingCycle.number,\\n _projectId,\\n _holder,\\n _beneficiary,\\n _tokenCount,\\n reclaimAmount,\\n _memo,\\n _metadata,\\n msg.sender\\n );\\n }\\n\\n /**\\n @notice\\n Distributes payouts for a project with the distribution limit of its current funding cycle.\\n\\n @dev\\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\\n\\n @dev\\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\\n\\n @dev\\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\\n\\n @param _projectId The ID of the project having its payouts distributed.\\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\\n @param _metadata Bytes to send along to the emitted event, if provided.\\n\\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\\n */\\n function _distributePayoutsOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n uint256 _minReturnedTokens,\\n bytes calldata _metadata\\n ) internal returns (uint256 netLeftoverDistributionAmount) {\\n // Record the distribution.\\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\\n _projectId,\\n _amount,\\n _currency\\n );\\n\\n // The amount being distributed must be at least as much as was expected.\\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\\n\\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\\n // and receive any extra distributable funds not allocated to payout splits.\\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\\n\\n // Define variables that will be needed outside the scoped section below.\\n // Keep a reference to the fee amount that was paid.\\n uint256 _fee;\\n\\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\\n {\\n // Get the amount of discount that should be applied to any fees taken.\\n // If the fee is zero, set the discount to 100% for convenience.\\n uint256 _feeDiscount = fee == 0\\n ? JBConstants.MAX_FEE_DISCOUNT\\n : _currentFeeDiscount(_projectId);\\n\\n // The amount distributed that is eligible for incurring fees.\\n uint256 _feeEligibleDistributionAmount;\\n\\n // The amount leftover after distributing to the splits.\\n uint256 _leftoverDistributionAmount;\\n\\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\\n _projectId,\\n _fundingCycle.configuration,\\n payoutSplitsGroup,\\n _distributedAmount,\\n _feeDiscount\\n );\\n\\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\\n unchecked {\\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\\n }\\n }\\n\\n // Take the fee.\\n _fee = _feeEligibleDistributionAmount != 0\\n ? _takeFeeFrom(\\n _projectId,\\n _fundingCycle,\\n _feeEligibleDistributionAmount,\\n _projectOwner,\\n _feeDiscount\\n )\\n : 0;\\n\\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\\n if (_leftoverDistributionAmount != 0) {\\n // Subtract the fee from the net leftover amount.\\n netLeftoverDistributionAmount =\\n _leftoverDistributionAmount -\\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\\n\\n // Transfer the amount to the project owner.\\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\\n }\\n }\\n\\n emit DistributePayouts(\\n _fundingCycle.configuration,\\n _fundingCycle.number,\\n _projectId,\\n _projectOwner,\\n _amount,\\n _distributedAmount,\\n _fee,\\n netLeftoverDistributionAmount,\\n _metadata,\\n msg.sender\\n );\\n }\\n\\n /**\\n @notice\\n Allows a project to send funds from its overflow up to the preconfigured allowance.\\n\\n @dev\\n Only a project's owner or a designated operator can use its allowance.\\n\\n @dev\\n Incurs the protocol fee.\\n\\n @param _projectId The ID of the project to use the allowance of.\\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\\n @param _beneficiary The address to send the funds to.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Bytes to send along to the emitted event, if provided.\\n\\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\\n */\\n function _useAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string memory _memo,\\n bytes calldata _metadata\\n ) internal returns (uint256 netDistributedAmount) {\\n // Record the use of the allowance.\\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\\n _projectId,\\n _amount,\\n _currency\\n );\\n\\n // The amount being withdrawn must be at least as much as was expected.\\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\\n\\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\\n {\\n // Keep a reference to the fee amount that was paid.\\n uint256 _fee;\\n\\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\\n address _projectOwner = projects.ownerOf(_projectId);\\n\\n // Get the amount of discount that should be applied to any fees taken.\\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\\n ? JBConstants.MAX_FEE_DISCOUNT\\n : _currentFeeDiscount(_projectId);\\n\\n // Take a fee from the `_distributedAmount`, if needed.\\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\\n ? 0\\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\\n\\n unchecked {\\n // The net amount is the withdrawn amount without the fee.\\n netDistributedAmount = _distributedAmount - _fee;\\n }\\n\\n // Transfer any remaining balance to the beneficiary.\\n if (netDistributedAmount > 0)\\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\\n }\\n\\n emit UseAllowance(\\n _fundingCycle.configuration,\\n _fundingCycle.number,\\n _projectId,\\n _beneficiary,\\n _amount,\\n _distributedAmount,\\n netDistributedAmount,\\n _memo,\\n _metadata,\\n msg.sender\\n );\\n }\\n\\n /**\\n @notice\\n Pays out splits for a project's funding cycle configuration.\\n\\n @param _projectId The ID of the project for which payout splits are being distributed.\\n @param _domain The domain of the splits to distribute the payout between.\\n @param _group The group of the splits to distribute the payout between.\\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\\n\\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\\n */\\n function _distributeToPayoutSplitsOf(\\n uint256 _projectId,\\n uint256 _domain,\\n uint256 _group,\\n uint256 _amount,\\n uint256 _feeDiscount\\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\\n // Set the leftover amount to the initial amount.\\n leftoverAmount = _amount;\\n // The total percentage available to split\\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\\n\\n // Get a reference to the project's payout splits.\\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\\n\\n // Transfer between all splits.\\n for (uint256 _i; _i < _splits.length; ) {\\n // Get a reference to the split being iterated on.\\n JBSplit memory _split = _splits[_i];\\n\\n // The amount to send towards the split.\\n uint256 _payoutAmount = _split.percent == leftoverPercentage\\n ? leftoverAmount\\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\\n\\n // Decrement the leftover percentage.\\n leftoverPercentage -= _split.percent;\\n\\n // The payout amount substracting any applicable incurred fees.\\n uint256 _netPayoutAmount = _distributeToPayoutSplit(\\n _split,\\n _projectId,\\n _group,\\n _payoutAmount,\\n _feeDiscount\\n );\\n\\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\\n if (_netPayoutAmount != 0 && _netPayoutAmount != _payoutAmount)\\n feeEligibleDistributionAmount += _payoutAmount;\\n\\n if (_payoutAmount > 0) {\\n // Subtract from the amount to be sent to the beneficiary.\\n unchecked {\\n leftoverAmount = leftoverAmount - _payoutAmount;\\n }\\n }\\n\\n emit DistributeToPayoutSplit(\\n _projectId,\\n _domain,\\n _group,\\n _split,\\n _payoutAmount,\\n _netPayoutAmount,\\n msg.sender\\n );\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n\\n /**\\n @notice\\n Pays out a split for a project's funding cycle configuration.\\n \\n @param _split The split to distribute payouts to.\\n @param _amount The total amount being distributed to the split, as a fixed point number with the same number of decimals as this terminal.\\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\\n\\n @return netPayoutAmount The amount sent to the split after subtracting fees.\\n */\\n function _distributeToPayoutSplit(\\n JBSplit memory _split,\\n uint256 _projectId,\\n uint256 _group,\\n uint256 _amount,\\n uint256 _feeDiscount\\n ) internal returns (uint256 netPayoutAmount) {\\n // If there's an allocator set, transfer to its `allocate` function.\\n if (_split.allocator != IJBSplitAllocator(address(0))) {\\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\\n if (\\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_split.allocator)]\\n )\\n netPayoutAmount = _amount;\\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\\n else {\\n unchecked {\\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\\n }\\n }\\n\\n // Trigger any inherited pre-transfer logic.\\n _beforeTransferTo(address(_split.allocator), netPayoutAmount);\\n\\n // Create the data to send to the allocator.\\n JBSplitAllocationData memory _data = JBSplitAllocationData(\\n token,\\n netPayoutAmount,\\n decimals,\\n _projectId,\\n _group,\\n _split\\n );\\n\\n // Trigger the allocator's `allocate` function.\\n uint256 _error;\\n bytes memory _reason;\\n\\n if (\\n ERC165Checker.supportsInterface(\\n address(_split.allocator),\\n type(IJBSplitAllocator).interfaceId\\n )\\n )\\n // If this terminal's token is ETH, send it in msg.value.\\n try _split.allocator.allocate{value: token == JBTokens.ETH ? netPayoutAmount : 0}(_data) {\\n\\n } catch (bytes memory reason) {\\n _reason = reason;\\n _error = 1;\\n }\\n else _error = 2;\\n\\n\\n if (_error != 0) {\\n // Trigger any inhereted post-transfer cancelation logic.\\n _cancelTransferTo(address(_split.allocator), netPayoutAmount);\\n\\n // Set the net payout amount to 0 to signal the reversion.\\n netPayoutAmount = 0;\\n\\n // Add undistributed amount back to project's balance.\\n store.recordAddedBalanceFor(_projectId, _amount);\\n\\n emit PayoutReverted(_projectId, _split, _amount, _error == 1 ? _reason : abi.encode(\\\"IERC165 fail\\\"), msg.sender);\\n }\\n\\n // Otherwise, if a project is specified, make a payment to it.\\n } else if (_split.projectId != 0) {\\n // Get a reference to the Juicebox terminal being used.\\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\\n\\n // The project must have a terminal to send funds to.\\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\\n\\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\\n if (\\n _terminal == this ||\\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\\n isFeelessAddress[address(_terminal)]\\n )\\n netPayoutAmount = _amount;\\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\\n else {\\n unchecked {\\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\\n }\\n }\\n\\n // Trigger any inherited pre-transfer logic.\\n _beforeTransferTo(address(_terminal), netPayoutAmount);\\n\\n // Send the projectId in the metadata.\\n bytes memory _projectMetadata = new bytes(32);\\n _projectMetadata = bytes(abi.encodePacked(_projectId));\\n\\n // Add to balance if prefered.\\n if (_split.preferAddToBalance)\\n try\\n _terminal.addToBalanceOf{value: token == JBTokens.ETH ? netPayoutAmount : 0}(\\n _split.projectId,\\n netPayoutAmount,\\n token,\\n '',\\n _projectMetadata\\n )\\n {} catch (bytes memory reason) {\\n // Trigger any inhereted post-transfer cancelation logic.\\n _cancelTransferTo(address(_terminal), netPayoutAmount);\\n\\n // Set the net payout amount to 0 to signal the reversion.\\n netPayoutAmount = 0;\\n\\n // Add undistributed amount back to project's balance.\\n store.recordAddedBalanceFor(_projectId, _amount);\\n\\n emit PayoutReverted(_projectId, _split, _amount, reason, msg.sender);\\n }\\n else\\n try\\n _terminal.pay{value: token == JBTokens.ETH ? netPayoutAmount : 0}(\\n _split.projectId,\\n netPayoutAmount,\\n token,\\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\\n 0,\\n _split.preferClaimed,\\n '',\\n _projectMetadata\\n )\\n {} catch (bytes memory reason) {\\n // Trigger any inhereted post-transfer cancelation logic.\\n _cancelTransferTo(address(_terminal), netPayoutAmount);\\n\\n // Set the net payout amount to 0 to signal the reversion.\\n netPayoutAmount = 0;\\n\\n // Add undistributed amount back to project's balance.\\n store.recordAddedBalanceFor(_projectId, _amount);\\n\\n emit PayoutReverted(_projectId, _split, _amount, reason, msg.sender);\\n }\\n } else {\\n // Keep a reference to the beneficiary.\\n address payable _beneficiary = _split.beneficiary != address(0)\\n ? _split.beneficiary\\n : payable(msg.sender);\\n\\n // If there's a full discount, this distribution is not eligible for a fee.\\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\\n netPayoutAmount = _amount;\\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\\n else {\\n unchecked {\\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\\n }\\n }\\n\\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\\n _transferFrom(address(this), _beneficiary, netPayoutAmount);\\n }\\n }\\n\\n /**\\n @notice\\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\\n\\n @param _projectId The ID of the project having fees taken from.\\n @param _fundingCycle The funding cycle during which the fee is being taken.\\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\\n @param _beneficiary The address to mint the platforms tokens for.\\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\\n\\n @return feeAmount The amount of the fee taken.\\n */\\n function _takeFeeFrom(\\n uint256 _projectId,\\n JBFundingCycle memory _fundingCycle,\\n uint256 _amount,\\n address _beneficiary,\\n uint256 _feeDiscount\\n ) internal returns (uint256 feeAmount) {\\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\\n\\n if (_fundingCycle.shouldHoldFees()) {\\n // Store the held fee.\\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\\n\\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\\n } else {\\n // Process the fee.\\n _processFee(feeAmount, _beneficiary, _projectId); // Take the fee.\\n\\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\\n }\\n }\\n\\n /**\\n @notice\\n Process a fee of the specified amount.\\n\\n @param _amount The fee amount, as a floating point number with 18 decimals.\\n @param _beneficiary The address to mint the platform's tokens for.\\n @param _from The project ID the fee is being paid from.\\n */\\n function _processFee(\\n uint256 _amount,\\n address _beneficiary,\\n uint256 _from\\n ) internal {\\n // Get the terminal for the protocol project.\\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\\n\\n // If this terminal's token is ETH, send it in msg.value.\\n uint256 _payableValue = token == JBTokens.ETH ? _amount : 0;\\n\\n // Send the projectId in the metadata.\\n bytes memory _projectMetadata = new bytes(32);\\n _projectMetadata = bytes(abi.encodePacked(_from));\\n\\n // Trigger any inherited pre-transfer logic if funds will be transferred.\\n if (address(_terminal) != address(this)) _beforeTransferTo(address(_terminal), _amount);\\n\\n try\\n // Send the fee.\\n _terminal.pay{value: _payableValue}(\\n _FEE_BENEFICIARY_PROJECT_ID,\\n _amount,\\n token,\\n _beneficiary,\\n 0,\\n false,\\n '',\\n _projectMetadata\\n )\\n {} catch (bytes memory reason) {\\n // Trigger any inhereted post-transfer cancelation logic if the pre-transfer logic was triggered.\\n if (address(_terminal) != address(this)) _cancelTransferTo(address(_terminal), _amount);\\n\\n // Add fee amount back to project's balance.\\n store.recordAddedBalanceFor(_from, _amount);\\n\\n emit FeeReverted(_from, _FEE_BENEFICIARY_PROJECT_ID, _amount, reason, msg.sender);\\n }\\n }\\n\\n /**\\n @notice\\n Contribute tokens to a project.\\n\\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\\n @param _payer The address making the payment.\\n @param _projectId The ID of the project being paid.\\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\\n\\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\\n */\\n function _pay(\\n uint256 _amount,\\n address _payer,\\n uint256 _projectId,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string memory _memo,\\n bytes memory _metadata\\n ) internal returns (uint256 beneficiaryTokenCount) {\\n // Cant send tokens to the zero address.\\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\\n\\n // Define variables that will be needed outside the scoped section below.\\n // Keep a reference to the funding cycle during which the payment is being made.\\n JBFundingCycle memory _fundingCycle;\\n\\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\\n {\\n JBPayDelegateAllocation[] memory _delegateAllocations;\\n uint256 _tokenCount;\\n\\n // Bundle the amount info into a JBTokenAmount struct.\\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\\n\\n // Record the payment.\\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\\n _payer,\\n _bundledAmount,\\n _projectId,\\n baseWeightCurrency,\\n _beneficiary,\\n _memo,\\n _metadata\\n );\\n\\n // Mint the tokens if needed.\\n if (_tokenCount > 0)\\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\\n _projectId,\\n _tokenCount,\\n _beneficiary,\\n '',\\n _preferClaimedTokens,\\n true\\n );\\n\\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\\n\\n // If delegate allocations were specified by the data source, fulfill them.\\n if (_delegateAllocations.length != 0) {\\n // Keep a reference to the token amount being forwarded to the delegate.\\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\\n\\n JBDidPayData memory _data = JBDidPayData(\\n _payer,\\n _projectId,\\n _fundingCycle.configuration,\\n _bundledAmount,\\n _forwardedAmount,\\n beneficiaryTokenCount,\\n _beneficiary,\\n _preferClaimedTokens,\\n _memo,\\n _metadata\\n );\\n\\n // Get a reference to the number of delegates to allocate to.\\n uint256 _numDelegates = _delegateAllocations.length;\\n\\n for (uint256 _i; _i < _numDelegates; ) {\\n // Get a reference to the delegate being iterated on.\\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\\n\\n // Trigger any inherited pre-transfer logic.\\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\\n\\n // Keep track of the msg.value to use in the delegate call\\n uint256 _payableValue;\\n\\n // If this terminal's token is ETH, send it in msg.value.\\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\\n\\n // Pass the correct token forwardedAmount to the delegate\\n _data.forwardedAmount.value = _delegateAllocation.amount;\\n\\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\\n\\n emit DelegateDidPay(\\n _delegateAllocation.delegate,\\n _data,\\n _delegateAllocation.amount,\\n msg.sender\\n );\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n }\\n\\n emit Pay(\\n _fundingCycle.configuration,\\n _fundingCycle.number,\\n _projectId,\\n _payer,\\n _beneficiary,\\n _amount,\\n beneficiaryTokenCount,\\n _memo,\\n _metadata,\\n msg.sender\\n );\\n }\\n\\n /**\\n @notice\\n Receives funds belonging to the specified project.\\n\\n @param _projectId The ID of the project to which the funds received belong.\\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Extra data to pass along to the emitted event.\\n */\\n function _addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n bool _shouldRefundHeldFees,\\n string memory _memo,\\n bytes memory _metadata\\n ) internal {\\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\\n\\n // Record the added funds with any refunded fees.\\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\\n\\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\\n }\\n\\n /**\\n @notice\\n Refund fees based on the specified amount.\\n\\n @param _projectId The project for which fees are being refunded.\\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\\n\\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\\n */\\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\\n internal\\n returns (uint256 refundedFees)\\n {\\n // Get a reference to the project's held fees.\\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\\n\\n // Delete the current held fees.\\n delete _heldFeesOf[_projectId];\\n\\n // Get a reference to the leftover amount once all fees have been settled.\\n uint256 leftoverAmount = _amount;\\n\\n // Push length in stack\\n uint256 _heldFeesLength = _heldFees.length;\\n\\n // Process each fee.\\n for (uint256 _i; _i < _heldFeesLength; ) {\\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\\n else if (leftoverAmount >= _heldFees[_i].amount) {\\n unchecked {\\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\\n refundedFees += _feeAmount(\\n _heldFees[_i].amount,\\n _heldFees[_i].fee,\\n _heldFees[_i].feeDiscount\\n );\\n }\\n } else {\\n unchecked {\\n _heldFeesOf[_projectId].push(\\n JBFee(\\n _heldFees[_i].amount - leftoverAmount,\\n _heldFees[_i].fee,\\n _heldFees[_i].feeDiscount,\\n _heldFees[_i].beneficiary\\n )\\n );\\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\\n }\\n leftoverAmount = 0;\\n }\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n\\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\\n }\\n\\n /** \\n @notice \\n Returns the fee amount based on the provided amount for the specified project.\\n\\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\\n @param _fee The percentage of the fee, out of MAX_FEE. \\n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\\n\\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\\n */\\n function _feeAmount(\\n uint256 _amount,\\n uint256 _fee,\\n uint256 _feeDiscount\\n ) internal pure returns (uint256) {\\n // Calculate the discounted fee.\\n uint256 _discountedFee = _fee -\\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\\n\\n // The amount of tokens from the `_amount` to pay as a fee.\\n return\\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\\n }\\n\\n /** \\n @notice\\n Get the fee discount from the fee gauge for the specified project.\\n\\n @param _projectId The ID of the project to get a fee discount for.\\n \\n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\\n */\\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\\n if (\\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\\n IJBPaymentTerminal(address(0))\\n ) return JBConstants.MAX_FEE_DISCOUNT;\\n\\n // Get the fee discount.\\n if (feeGauge != IJBFeeGauge(address(0)))\\n // If the guage reverts, keep the discount at 0.\\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\\n // If the fee discount is greater than the max, we ignore the return value\\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\\n } catch {\\n return 0;\\n }\\n\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0x1af3116bfcffd711bd25c79f41f389a1a163716420d22869c072e83e4be60c68\",\"license\":\"MIT\"},\"contracts/abstract/JBSingleTokenPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\\nimport './../interfaces/IJBSingleTokenPaymentTerminal.sol';\\n\\n/**\\n @notice\\n Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\\n\\n @dev\\n Adheres to -\\n IJBSingleTokenPaymentTerminals: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n\\n @dev\\n Inherits from -\\n ERC165: Introspection on interface adherance. \\n*/\\nabstract contract JBSingleTokenPaymentTerminal is ERC165, IJBSingleTokenPaymentTerminal {\\n //*********************************************************************//\\n // ---------------- public immutable stored properties --------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The token that this terminal accepts.\\n */\\n address public immutable override token;\\n\\n /**\\n @notice\\n The number of decimals the token fixed point amounts are expected to have.\\n */\\n uint256 public immutable override decimals;\\n\\n /**\\n @notice\\n The currency to use when resolving price feeds for this terminal.\\n */\\n uint256 public immutable override currency;\\n\\n //*********************************************************************//\\n // ------------------------- external views -------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n A flag indicating if this terminal accepts the specified token.\\n\\n @param _token The token to check if this terminal accepts or not.\\n @param _projectId The project ID to check for token acceptance.\\n\\n @return The flag.\\n */\\n function acceptsToken(address _token, uint256 _projectId) external view override returns (bool) {\\n _projectId; // Prevents unused var compiler and natspec complaints.\\n\\n return _token == token;\\n }\\n\\n /** \\n @notice\\n The decimals that should be used in fixed number accounting for the specified token.\\n\\n @param _token The token to check for the decimals of.\\n\\n @return The number of decimals for the token.\\n */\\n function decimalsForToken(address _token) external view override returns (uint256) {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n return decimals;\\n }\\n\\n /** \\n @notice\\n The currency that should be used for the specified token.\\n\\n @param _token The token to check for the currency of.\\n\\n @return The currency index.\\n */\\n function currencyForToken(address _token) external view override returns (uint256) {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n return currency;\\n }\\n\\n //*********************************************************************//\\n // -------------------------- public views --------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Indicates if this contract adheres to the specified interface.\\n\\n @dev \\n See {IERC165-supportsInterface}.\\n\\n @param _interfaceId The ID of the interface to check for adherance to.\\n */\\n function supportsInterface(bytes4 _interfaceId)\\n public\\n view\\n virtual\\n override(ERC165, IERC165)\\n returns (bool)\\n {\\n return\\n _interfaceId == type(IJBPaymentTerminal).interfaceId ||\\n _interfaceId == type(IJBSingleTokenPaymentTerminal).interfaceId ||\\n super.supportsInterface(_interfaceId);\\n }\\n\\n //*********************************************************************//\\n // -------------------------- constructor ---------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @param _token The token that this terminal manages.\\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\\n @param _currency The currency that this terminal's token adheres to for price feeds.\\n */\\n constructor(\\n address _token,\\n uint256 _decimals,\\n uint256 _currency\\n ) {\\n token = _token;\\n decimals = _decimals;\\n currency = _currency;\\n }\\n}\\n\",\"keccak256\":\"0xdc82ad3e01b918d3d21ffea8c9f30950d81e225137c851599d028dcd22125f89\",\"license\":\"MIT\"},\"contracts/enums/JBBallotState.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nenum JBBallotState {\\n Active,\\n Approved,\\n Failed\\n}\\n\",\"keccak256\":\"0x891fcac63470398b3a11239da7feba6b07d640809fcefd2404303b823d7378f8\",\"license\":\"MIT\"},\"contracts/interfaces/IJBAllowanceTerminal3_1.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBAllowanceTerminal3_1 {\\n function useAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n address _token,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external returns (uint256 netDistributedAmount);\\n}\\n\",\"keccak256\":\"0x4e1ef83fc258e44f7880005b7944e3b4799d87129b2300236d93269a00adb4ee\",\"license\":\"MIT\"},\"contracts/interfaces/IJBController.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBFundAccessConstraints.sol';\\nimport './../structs/JBFundingCycleData.sol';\\nimport './../structs/JBFundingCycleMetadata.sol';\\nimport './../structs/JBGroupedSplits.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBMigratable.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBSplitsStore.sol';\\nimport './IJBTokenStore.sol';\\n\\ninterface IJBController is IERC165 {\\n event LaunchProject(uint256 configuration, uint256 projectId, string memo, address caller);\\n\\n event LaunchFundingCycles(uint256 configuration, uint256 projectId, string memo, address caller);\\n\\n event ReconfigureFundingCycles(\\n uint256 configuration,\\n uint256 projectId,\\n string memo,\\n address caller\\n );\\n\\n event SetFundAccessConstraints(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n JBFundAccessConstraints constraints,\\n address caller\\n );\\n\\n event DistributeReservedTokens(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address beneficiary,\\n uint256 tokenCount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n address caller\\n );\\n\\n event DistributeToReservedTokenSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n uint256 tokenCount,\\n address caller\\n );\\n\\n event MintTokens(\\n address indexed beneficiary,\\n uint256 indexed projectId,\\n uint256 tokenCount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n uint256 reservedRate,\\n address caller\\n );\\n\\n event BurnTokens(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 tokenCount,\\n string memo,\\n address caller\\n );\\n\\n event Migrate(uint256 indexed projectId, IJBMigratable to, address caller);\\n\\n event PrepMigration(uint256 indexed projectId, address from, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function tokenStore() external view returns (IJBTokenStore);\\n\\n function splitsStore() external view returns (IJBSplitsStore);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function reservedTokenBalanceOf(uint256 _projectId, uint256 _reservedRate)\\n external\\n view\\n returns (uint256);\\n\\n function distributionLimitOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n IJBPaymentTerminal _terminal,\\n address _token\\n ) external view returns (uint256 distributionLimit, uint256 distributionLimitCurrency);\\n\\n function overflowAllowanceOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n IJBPaymentTerminal _terminal,\\n address _token\\n ) external view returns (uint256 overflowAllowance, uint256 overflowAllowanceCurrency);\\n\\n function totalOutstandingTokensOf(uint256 _projectId, uint256 _reservedRate)\\n external\\n view\\n returns (uint256);\\n\\n function getFundingCycleOf(uint256 _projectId, uint256 _configuration)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function latestConfiguredFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (\\n JBFundingCycle memory,\\n JBFundingCycleMetadata memory metadata,\\n JBBallotState\\n );\\n\\n function currentFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function queuedFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function launchProjectFor(\\n address _owner,\\n JBProjectMetadata calldata _projectMetadata,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n IJBPaymentTerminal[] memory _terminals,\\n string calldata _memo\\n ) external returns (uint256 projectId);\\n\\n function launchFundingCyclesFor(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n IJBPaymentTerminal[] memory _terminals,\\n string calldata _memo\\n ) external returns (uint256 configuration);\\n\\n function reconfigureFundingCyclesOf(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n string calldata _memo\\n ) external returns (uint256);\\n\\n function mintTokensOf(\\n uint256 _projectId,\\n uint256 _tokenCount,\\n address _beneficiary,\\n string calldata _memo,\\n bool _preferClaimedTokens,\\n bool _useReservedRate\\n ) external returns (uint256 beneficiaryTokenCount);\\n\\n function burnTokensOf(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n string calldata _memo,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function distributeReservedTokensOf(uint256 _projectId, string memory _memo)\\n external\\n returns (uint256);\\n\\n function migrate(uint256 _projectId, IJBMigratable _to) external;\\n}\\n\",\"keccak256\":\"0xb1ee4b41f2a06f28f69c74cb729b8964f2e75f3c545a68f85bd9082b5575bc85\",\"license\":\"MIT\"},\"contracts/interfaces/IJBDirectory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBProjects.sol';\\n\\ninterface IJBDirectory {\\n event SetController(uint256 indexed projectId, address indexed controller, address caller);\\n\\n event AddTerminal(uint256 indexed projectId, IJBPaymentTerminal indexed terminal, address caller);\\n\\n event SetTerminals(uint256 indexed projectId, IJBPaymentTerminal[] terminals, address caller);\\n\\n event SetPrimaryTerminal(\\n uint256 indexed projectId,\\n address indexed token,\\n IJBPaymentTerminal indexed terminal,\\n address caller\\n );\\n\\n event SetIsAllowedToSetFirstController(address indexed addr, bool indexed flag, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function controllerOf(uint256 _projectId) external view returns (address);\\n\\n function isAllowedToSetFirstController(address _address) external view returns (bool);\\n\\n function terminalsOf(uint256 _projectId) external view returns (IJBPaymentTerminal[] memory);\\n\\n function isTerminalOf(uint256 _projectId, IJBPaymentTerminal _terminal)\\n external\\n view\\n returns (bool);\\n\\n function primaryTerminalOf(uint256 _projectId, address _token)\\n external\\n view\\n returns (IJBPaymentTerminal);\\n\\n function setControllerOf(uint256 _projectId, address _controller) external;\\n\\n function setTerminalsOf(uint256 _projectId, IJBPaymentTerminal[] calldata _terminals) external;\\n\\n function setPrimaryTerminalOf(\\n uint256 _projectId,\\n address _token,\\n IJBPaymentTerminal _terminal\\n ) external;\\n\\n function setIsAllowedToSetFirstController(address _address, bool _flag) external;\\n}\\n\",\"keccak256\":\"0x715321646db00514d1355ed43c40cd3f01e94959552fd07797b315d9c49cdb1d\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFeeGauge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBFeeGauge {\\n function currentDiscountFor(uint256 _projectId) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x8e19959617191320fe1210760860e668a57319258c0c74fcfabac829ae0222c0\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFeeHoldingTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBFeeHoldingTerminal {\\n function addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n bool _shouldRefundHeldFees,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable;\\n}\\n\",\"keccak256\":\"0x8c9edae0768a737097835b8b9ef4a60f000de122a867c90f20cfc653287541a4\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleBallot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../enums/JBBallotState.sol';\\n\\ninterface IJBFundingCycleBallot is IERC165 {\\n function duration() external view returns (uint256);\\n\\n function stateOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n uint256 _start\\n ) external view returns (JBBallotState);\\n}\\n\",\"keccak256\":\"0x49553a56209237846bc400cf27f260824a6bd06fd8094a7eb5abb9de75779598\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../enums/JBBallotState.sol';\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBFundingCycleData.sol';\\n\\ninterface IJBFundingCycleStore {\\n event Configure(\\n uint256 indexed configuration,\\n uint256 indexed projectId,\\n JBFundingCycleData data,\\n uint256 metadata,\\n uint256 mustStartAtOrAfter,\\n address caller\\n );\\n\\n event Init(uint256 indexed configuration, uint256 indexed projectId, uint256 indexed basedOn);\\n\\n function latestConfigurationOf(uint256 _projectId) external view returns (uint256);\\n\\n function get(uint256 _projectId, uint256 _configuration)\\n external\\n view\\n returns (JBFundingCycle memory);\\n\\n function latestConfiguredOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBBallotState ballotState);\\n\\n function queuedOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentBallotStateOf(uint256 _projectId) external view returns (JBBallotState);\\n\\n function configureFor(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n uint256 _metadata,\\n uint256 _mustStartAtOrAfter\\n ) external returns (JBFundingCycle memory fundingCycle);\\n}\\n\",\"keccak256\":\"0xaead823851433be0c2ddc8f8086813e6cd647de3a1bc0f7570a5d6b38c378b5a\",\"license\":\"MIT\"},\"contracts/interfaces/IJBMigratable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBMigratable {\\n function prepForMigrationOf(uint256 _projectId, address _from) external;\\n}\\n\",\"keccak256\":\"0xc81053e4b4754fc510aa04fecd3ab1460f01e3e27761e7a8c94f631a978ae127\",\"license\":\"MIT\"},\"contracts/interfaces/IJBOperatable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBOperatorStore.sol';\\n\\ninterface IJBOperatable {\\n function operatorStore() external view returns (IJBOperatorStore);\\n}\\n\",\"keccak256\":\"0x09a55a91c6ce3625379334271d236cfa47bf36522a91568b406bf06f7239407e\",\"license\":\"MIT\"},\"contracts/interfaces/IJBOperatorStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBOperatorData.sol';\\n\\ninterface IJBOperatorStore {\\n event SetOperator(\\n address indexed operator,\\n address indexed account,\\n uint256 indexed domain,\\n uint256[] permissionIndexes,\\n uint256 packed\\n );\\n\\n function permissionsOf(\\n address _operator,\\n address _account,\\n uint256 _domain\\n ) external view returns (uint256);\\n\\n function hasPermission(\\n address _operator,\\n address _account,\\n uint256 _domain,\\n uint256 _permissionIndex\\n ) external view returns (bool);\\n\\n function hasPermissions(\\n address _operator,\\n address _account,\\n uint256 _domain,\\n uint256[] calldata _permissionIndexes\\n ) external view returns (bool);\\n\\n function setOperator(JBOperatorData calldata _operatorData) external;\\n\\n function setOperators(JBOperatorData[] calldata _operatorData) external;\\n}\\n\",\"keccak256\":\"0x17f4929812a356984795fafed8cb2be816a025c9a0771d85595ac0b5ff3cffc5\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPayDelegate.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBDidPayData.sol';\\n\\n/**\\n @title\\n Pay delegate\\n\\n @notice\\n Delegate called after JBTerminal.pay(..) logic completion (if passed by the funding cycle datasource)\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n*/\\ninterface IJBPayDelegate is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.pay(..), after the execution of its logic\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control\\n \\n @param _data the data passed by the terminal, as a JBDidPayData struct:\\n address payer;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n JBTokenAmount amount;\\n JBTokenAmount forwardedAmount;\\n uint256 projectTokenCount;\\n address beneficiary;\\n bool preferClaimedTokens;\\n string memo;\\n bytes metadata;\\n */\\n function didPay(JBDidPayData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0xa797de18b69eceba117e1f0b3810cf3cc2d2791417d580a5bdc510d1b868ab26\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\n\\ninterface IJBPaymentTerminal is IERC165 {\\n function acceptsToken(address _token, uint256 _projectId) external view returns (bool);\\n\\n function currencyForToken(address _token) external view returns (uint256);\\n\\n function decimalsForToken(address _token) external view returns (uint256);\\n\\n // Return value must be a fixed point number with 18 decimals.\\n function currentEthOverflowOf(uint256 _projectId) external view returns (uint256);\\n\\n function pay(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable returns (uint256 beneficiaryTokenCount);\\n\\n function addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable;\\n}\\n\",\"keccak256\":\"0xb7826f5ed609359ce322c09e83236c47ba385df1c3cad3607e56fd0a2e00eee2\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPayoutRedemptionPaymentTerminal3_1.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBFee.sol';\\nimport './IJBAllowanceTerminal3_1.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFeeGauge.sol';\\nimport './IJBFeeHoldingTerminal.sol';\\nimport './IJBPayDelegate.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBPayoutTerminal3_1.sol';\\nimport './IJBPrices.sol';\\nimport './IJBProjects.sol';\\nimport './IJBRedemptionDelegate.sol';\\nimport './IJBRedemptionTerminal.sol';\\nimport './IJBSingleTokenPaymentTerminalStore.sol';\\nimport './IJBSplitsStore.sol';\\n\\ninterface IJBPayoutRedemptionPaymentTerminal3_1 is\\n IJBPaymentTerminal,\\n IJBPayoutTerminal3_1,\\n IJBAllowanceTerminal3_1,\\n IJBRedemptionTerminal,\\n IJBFeeHoldingTerminal\\n{\\n event AddToBalance(\\n uint256 indexed projectId,\\n uint256 amount,\\n uint256 refundedFees,\\n string memo,\\n bytes metadata,\\n address caller\\n );\\n\\n event Migrate(\\n uint256 indexed projectId,\\n IJBPaymentTerminal indexed to,\\n uint256 amount,\\n address caller\\n );\\n\\n event DistributePayouts(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address beneficiary,\\n uint256 amount,\\n uint256 distributedAmount,\\n uint256 fee,\\n uint256 beneficiaryDistributionAmount,\\n bytes metadata,\\n address caller\\n );\\n\\n event UseAllowance(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address beneficiary,\\n uint256 amount,\\n uint256 distributedAmount,\\n uint256 netDistributedamount,\\n string memo,\\n bytes metadata,\\n address caller\\n );\\n\\n event HoldFee(\\n uint256 indexed projectId,\\n uint256 indexed amount,\\n uint256 indexed fee,\\n uint256 feeDiscount,\\n address beneficiary,\\n address caller\\n );\\n\\n event ProcessFee(\\n uint256 indexed projectId,\\n uint256 indexed amount,\\n bool indexed wasHeld,\\n address beneficiary,\\n address caller\\n );\\n\\n event RefundHeldFees(\\n uint256 indexed projectId,\\n uint256 indexed amount,\\n uint256 indexed refundedFees,\\n uint256 leftoverAmount,\\n address caller\\n );\\n\\n event Pay(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address payer,\\n address beneficiary,\\n uint256 amount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n bytes metadata,\\n address caller\\n );\\n\\n event DelegateDidPay(\\n IJBPayDelegate indexed delegate,\\n JBDidPayData data,\\n uint256 delegatedAmount,\\n address caller\\n );\\n\\n event RedeemTokens(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address holder,\\n address beneficiary,\\n uint256 tokenCount,\\n uint256 reclaimedAmount,\\n string memo,\\n bytes metadata,\\n address caller\\n );\\n\\n event DelegateDidRedeem(\\n IJBRedemptionDelegate indexed delegate,\\n JBDidRedeemData data,\\n uint256 delegatedAmount,\\n address caller\\n );\\n\\n event DistributeToPayoutSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n uint256 amount,\\n uint256 netAmount,\\n address caller\\n );\\n\\n event SetFee(uint256 fee, address caller);\\n\\n event SetFeeGauge(IJBFeeGauge indexed feeGauge, address caller);\\n\\n event SetFeelessAddress(address indexed addrs, bool indexed flag, address caller);\\n\\n event PayoutReverted(uint256 indexed projectId, JBSplit split, uint256 amount, bytes reason, address caller);\\n\\n event FeeReverted(\\n uint256 indexed projectId,\\n uint256 indexed feeProjectId,\\n uint256 amount,\\n bytes reason,\\n address caller\\n );\\n\\n function projects() external view returns (IJBProjects);\\n\\n function splitsStore() external view returns (IJBSplitsStore);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function prices() external view returns (IJBPrices);\\n\\n function store() external view returns (IJBSingleTokenPaymentTerminalStore);\\n\\n function baseWeightCurrency() external view returns (uint256);\\n\\n function payoutSplitsGroup() external view returns (uint256);\\n\\n function heldFeesOf(uint256 _projectId) external view returns (JBFee[] memory);\\n\\n function fee() external view returns (uint256);\\n\\n function feeGauge() external view returns (IJBFeeGauge);\\n\\n function isFeelessAddress(address _contract) external view returns (bool);\\n\\n function migrate(uint256 _projectId, IJBPaymentTerminal _to) external returns (uint256 balance);\\n\\n function processFees(uint256 _projectId) external;\\n\\n function setFee(uint256 _fee) external;\\n\\n function setFeeGauge(IJBFeeGauge _feeGauge) external;\\n\\n function setFeelessAddress(address _contract, bool _flag) external;\\n}\\n\",\"keccak256\":\"0xe823526fd535dc962784820cac32e6fdd56f2a5020dbf9883979b9ddfcc093fa\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPayoutTerminal3_1.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBPayoutTerminal3_1 {\\n function distributePayoutsOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n address _token,\\n uint256 _minReturnedTokens,\\n bytes calldata _metadata\\n ) external returns (uint256 netLeftoverDistributionAmount);\\n}\\n\",\"keccak256\":\"0x415707a4902f90945ecee641e96dd88c733b1d159c35c1184e665ca3509ffe49\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPriceFeed.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBPriceFeed {\\n function currentPrice(uint256 _targetDecimals) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x57c71282fec1b34b00cf991ffed2e36031c393e35bfa7ca5d723eb6572fb7122\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPrices.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBPriceFeed.sol';\\n\\ninterface IJBPrices {\\n event AddFeed(uint256 indexed currency, uint256 indexed base, IJBPriceFeed feed);\\n\\n function feedFor(uint256 _currency, uint256 _base) external view returns (IJBPriceFeed);\\n\\n function priceFor(\\n uint256 _currency,\\n uint256 _base,\\n uint256 _decimals\\n ) external view returns (uint256);\\n\\n function addFeedFor(\\n uint256 _currency,\\n uint256 _base,\\n IJBPriceFeed _priceFeed\\n ) external;\\n}\\n\",\"keccak256\":\"0x82a175b1f4b95b506c98406576cd59cbe04615e3df24f9cf3587b61b8ee323b1\",\"license\":\"MIT\"},\"contracts/interfaces/IJBProjects.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBTokenUriResolver.sol';\\n\\ninterface IJBProjects is IERC721 {\\n event Create(\\n uint256 indexed projectId,\\n address indexed owner,\\n JBProjectMetadata metadata,\\n address caller\\n );\\n\\n event SetMetadata(uint256 indexed projectId, JBProjectMetadata metadata, address caller);\\n\\n event SetTokenUriResolver(IJBTokenUriResolver indexed resolver, address caller);\\n\\n function count() external view returns (uint256);\\n\\n function metadataContentOf(uint256 _projectId, uint256 _domain)\\n external\\n view\\n returns (string memory);\\n\\n function tokenUriResolver() external view returns (IJBTokenUriResolver);\\n\\n function createFor(address _owner, JBProjectMetadata calldata _metadata)\\n external\\n returns (uint256 projectId);\\n\\n function setMetadataOf(uint256 _projectId, JBProjectMetadata calldata _metadata) external;\\n\\n function setTokenUriResolver(IJBTokenUriResolver _newResolver) external;\\n}\\n\",\"keccak256\":\"0x7cfc021d0bd7e73b1ba8f4845d7d35e3419d6a14d3d25ca3a8010e7f91062fe4\",\"license\":\"MIT\"},\"contracts/interfaces/IJBRedemptionDelegate.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBDidRedeemData.sol';\\n\\n/**\\n @title\\n Redemption delegate\\n\\n @notice\\n Delegate called after JBTerminal.redeemTokensOf(..) logic completion (if passed by the funding cycle datasource)\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n*/\\ninterface IJBRedemptionDelegate is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.redeemTokensOf(..), after the execution of its logic\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control\\n \\n @param _data the data passed by the terminal, as a JBDidRedeemData struct:\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 projectTokenCount;\\n JBTokenAmount reclaimedAmount;\\n JBTokenAmount forwardedAmount;\\n address payable beneficiary;\\n string memo;\\n bytes metadata;\\n */\\n function didRedeem(JBDidRedeemData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0x172d2c0be65e72e54f71ae521907067f0fa30e8ca05c4f88826903208aa437e2\",\"license\":\"MIT\"},\"contracts/interfaces/IJBRedemptionTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBRedemptionTerminal {\\n function redeemTokensOf(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n address _token,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external returns (uint256 reclaimAmount);\\n}\\n\",\"keccak256\":\"0xe26a6a03468401b802ae5328b39a266f53b9331a1c077fcbf7719d10ba74ff44\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSingleTokenPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBPaymentTerminal.sol';\\n\\ninterface IJBSingleTokenPaymentTerminal is IJBPaymentTerminal {\\n function token() external view returns (address);\\n\\n function currency() external view returns (uint256);\\n\\n function decimals() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xf6e78323caa9af7bbf024f44b2032a83fed0394e0b3a242a6346e73c85b2e46f\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSingleTokenPaymentTerminalStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBPayDelegateAllocation.sol';\\nimport './../structs/JBRedemptionDelegateAllocation.sol';\\nimport './../structs/JBTokenAmount.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBPrices.sol';\\nimport './IJBSingleTokenPaymentTerminal.sol';\\n\\ninterface IJBSingleTokenPaymentTerminalStore {\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function prices() external view returns (IJBPrices);\\n\\n function balanceOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\\n external\\n view\\n returns (uint256);\\n\\n function usedDistributionLimitOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _fundingCycleNumber\\n ) external view returns (uint256);\\n\\n function usedOverflowAllowanceOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _fundingCycleConfiguration\\n ) external view returns (uint256);\\n\\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\\n external\\n view\\n returns (uint256);\\n\\n function currentTotalOverflowOf(\\n uint256 _projectId,\\n uint256 _decimals,\\n uint256 _currency\\n ) external view returns (uint256);\\n\\n function currentReclaimableOverflowOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n bool _useTotalOverflow\\n ) external view returns (uint256);\\n\\n function currentReclaimableOverflowOf(\\n uint256 _projectId,\\n uint256 _tokenCount,\\n uint256 _totalSupply,\\n uint256 _overflow\\n ) external view returns (uint256);\\n\\n function recordPaymentFrom(\\n address _payer,\\n JBTokenAmount memory _amount,\\n uint256 _projectId,\\n uint256 _baseWeightCurrency,\\n address _beneficiary,\\n string calldata _memo,\\n bytes calldata _metadata\\n )\\n external\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 tokenCount,\\n JBPayDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n );\\n\\n function recordRedemptionFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n string calldata _memo,\\n bytes calldata _metadata\\n )\\n external\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 reclaimAmount,\\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n );\\n\\n function recordDistributionFor(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n ) external returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount);\\n\\n function recordUsedAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n ) external returns (JBFundingCycle memory fundingCycle, uint256 withdrawnAmount);\\n\\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external;\\n\\n function recordMigration(uint256 _projectId) external returns (uint256 balance);\\n}\\n\",\"keccak256\":\"0xd78929c9371fd7895b829ef5e4ad4b3786523c3580ac3f6f5f25d2b5941c0dd3\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSplitAllocator.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport '../structs/JBSplitAllocationData.sol';\\n\\n/**\\n @title\\n Split allocator\\n\\n @notice\\n Provide a way to process a single split with extra logic\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n\\n @dev\\n The contract address should be set as an allocator in the adequate split\\n*/\\ninterface IJBSplitAllocator is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.distributePayoutOf(..), during the processing of the split including it\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control. The token and/or eth are optimistically transfered\\n to the allocator for its logic.\\n \\n @param _data the data passed by the terminal, as a JBSplitAllocationData struct:\\n address token;\\n uint256 amount;\\n uint256 decimals;\\n uint256 projectId;\\n uint256 group;\\n JBSplit split;\\n */\\n function allocate(JBSplitAllocationData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0x5efb6f51fc161f42ff58989386ad99028e4039a0ba897d66f358c3dfcf686105\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSplitsStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBGroupedSplits.sol';\\nimport './../structs/JBSplit.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBProjects.sol';\\n\\ninterface IJBSplitsStore {\\n event SetSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n address caller\\n );\\n\\n function projects() external view returns (IJBProjects);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function splitsOf(\\n uint256 _projectId,\\n uint256 _domain,\\n uint256 _group\\n ) external view returns (JBSplit[] memory);\\n\\n function set(\\n uint256 _projectId,\\n uint256 _domain,\\n JBGroupedSplits[] memory _groupedSplits\\n ) external;\\n}\\n\",\"keccak256\":\"0x66dab3dd394e318b850401ca92c2963b906cc0ad5562fa5d4f6f850175d1c77a\",\"license\":\"MIT\"},\"contracts/interfaces/IJBToken.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBToken {\\n function projectId() external view returns (uint256);\\n\\n function decimals() external view returns (uint8);\\n\\n function totalSupply(uint256 _projectId) external view returns (uint256);\\n\\n function balanceOf(address _account, uint256 _projectId) external view returns (uint256);\\n\\n function mint(\\n uint256 _projectId,\\n address _account,\\n uint256 _amount\\n ) external;\\n\\n function burn(\\n uint256 _projectId,\\n address _account,\\n uint256 _amount\\n ) external;\\n\\n function approve(\\n uint256,\\n address _spender,\\n uint256 _amount\\n ) external;\\n\\n function transfer(\\n uint256 _projectId,\\n address _to,\\n uint256 _amount\\n ) external;\\n\\n function transferFrom(\\n uint256 _projectId,\\n address _from,\\n address _to,\\n uint256 _amount\\n ) external;\\n}\\n\",\"keccak256\":\"0xe8969210417736c85d71101bf1c0bd8ebbf9d1e62a93e758148bd5709a6c7097\",\"license\":\"MIT\"},\"contracts/interfaces/IJBTokenStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBProjects.sol';\\nimport './IJBToken.sol';\\n\\ninterface IJBTokenStore {\\n event Issue(\\n uint256 indexed projectId,\\n IJBToken indexed token,\\n string name,\\n string symbol,\\n address caller\\n );\\n\\n event Mint(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 amount,\\n bool tokensWereClaimed,\\n bool preferClaimedTokens,\\n address caller\\n );\\n\\n event Burn(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 amount,\\n uint256 initialUnclaimedBalance,\\n uint256 initialClaimedBalance,\\n bool preferClaimedTokens,\\n address caller\\n );\\n\\n event Claim(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 initialUnclaimedBalance,\\n uint256 amount,\\n address caller\\n );\\n\\n event Set(uint256 indexed projectId, IJBToken indexed newToken, address caller);\\n\\n event Transfer(\\n address indexed holder,\\n uint256 indexed projectId,\\n address indexed recipient,\\n uint256 amount,\\n address caller\\n );\\n\\n function tokenOf(uint256 _projectId) external view returns (IJBToken);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function unclaimedBalanceOf(address _holder, uint256 _projectId) external view returns (uint256);\\n\\n function unclaimedTotalSupplyOf(uint256 _projectId) external view returns (uint256);\\n\\n function totalSupplyOf(uint256 _projectId) external view returns (uint256);\\n\\n function balanceOf(address _holder, uint256 _projectId) external view returns (uint256 _result);\\n\\n function issueFor(\\n uint256 _projectId,\\n string calldata _name,\\n string calldata _symbol\\n ) external returns (IJBToken token);\\n\\n function setFor(uint256 _projectId, IJBToken _token) external;\\n\\n function burnFrom(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function mintFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function claimFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount\\n ) external;\\n\\n function transferFrom(\\n address _holder,\\n uint256 _projectId,\\n address _recipient,\\n uint256 _amount\\n ) external;\\n}\\n\",\"keccak256\":\"0x98459e3af050d41dfeffdc97f1c93330207ba450f8ff3613224b49a89eeca9c6\",\"license\":\"MIT\"},\"contracts/interfaces/IJBTokenUriResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBTokenUriResolver {\\n function getUri(uint256 _projectId) external view returns (string memory tokenUri);\\n}\\n\",\"keccak256\":\"0xd267fd8ca7c21c2c71794acdb9a98314c33a35fc559e0bf0897a6686d196d174\",\"license\":\"MIT\"},\"contracts/libraries/JBConstants.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/**\\n @notice\\n Global constants used across Juicebox contracts.\\n*/\\nlibrary JBConstants {\\n uint256 public constant MAX_RESERVED_RATE = 10_000;\\n uint256 public constant MAX_REDEMPTION_RATE = 10_000;\\n uint256 public constant MAX_DISCOUNT_RATE = 1_000_000_000;\\n uint256 public constant SPLITS_TOTAL_PERCENT = 1_000_000_000;\\n uint256 public constant MAX_FEE = 1_000_000_000;\\n uint256 public constant MAX_FEE_DISCOUNT = 1_000_000_000;\\n}\\n\",\"keccak256\":\"0x34362846a1cd428a8bdedf4ab6857e11402f345cb87b994b2e7fb6d2474b808d\",\"license\":\"MIT\"},\"contracts/libraries/JBCurrencies.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBCurrencies {\\n uint256 public constant ETH = 1;\\n uint256 public constant USD = 2;\\n}\\n\",\"keccak256\":\"0x7e417ff25c173608ee4fe6d9fc3dcd5e1458c78c889af12bac47b1189a436076\",\"license\":\"MIT\"},\"contracts/libraries/JBFixedPointNumber.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nlibrary JBFixedPointNumber {\\n function adjustDecimals(\\n uint256 _value,\\n uint256 _decimals,\\n uint256 _targetDecimals\\n ) internal pure returns (uint256) {\\n // If decimals need adjusting, multiply or divide the price by the decimal adjuster to get the normalized result.\\n if (_targetDecimals == _decimals) return _value;\\n else if (_targetDecimals > _decimals) return _value * 10**(_targetDecimals - _decimals);\\n else return _value / 10**(_decimals - _targetDecimals);\\n }\\n}\\n\",\"keccak256\":\"0x18efac48269f3a3bd7e9a1c770776f950e0afa86769e6f8b128002c3b8c6742c\",\"license\":\"MIT\"},\"contracts/libraries/JBFundingCycleMetadataResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBFundingCycleMetadata.sol';\\nimport './../structs/JBGlobalFundingCycleMetadata.sol';\\nimport './JBConstants.sol';\\nimport './JBGlobalFundingCycleMetadataResolver.sol';\\n\\nlibrary JBFundingCycleMetadataResolver {\\n function global(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (JBGlobalFundingCycleMetadata memory)\\n {\\n return JBGlobalFundingCycleMetadataResolver.expandMetadata(uint8(_fundingCycle.metadata >> 8));\\n }\\n\\n function reservedRate(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n return uint256(uint16(_fundingCycle.metadata >> 24));\\n }\\n\\n function redemptionRate(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n // Redemption rate is a number 0-10000. It's inverse was stored so the most common case of 100% results in no storage needs.\\n return JBConstants.MAX_REDEMPTION_RATE - uint256(uint16(_fundingCycle.metadata >> 40));\\n }\\n\\n function ballotRedemptionRate(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (uint256)\\n {\\n // Redemption rate is a number 0-10000. It's inverse was stored so the most common case of 100% results in no storage needs.\\n return JBConstants.MAX_REDEMPTION_RATE - uint256(uint16(_fundingCycle.metadata >> 56));\\n }\\n\\n function payPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 72) & 1) == 1;\\n }\\n\\n function distributionsPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 73) & 1) == 1;\\n }\\n\\n function redeemPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 74) & 1) == 1;\\n }\\n\\n function burnPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 75) & 1) == 1;\\n }\\n\\n function mintingAllowed(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 76) & 1) == 1;\\n }\\n\\n function terminalMigrationAllowed(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 77) & 1) == 1;\\n }\\n\\n function controllerMigrationAllowed(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 78) & 1) == 1;\\n }\\n\\n function shouldHoldFees(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 79) & 1) == 1;\\n }\\n\\n function preferClaimedTokenOverride(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 80) & 1) == 1;\\n }\\n\\n function useTotalOverflowForRedemptions(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 81) & 1) == 1;\\n }\\n\\n function useDataSourceForPay(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return (_fundingCycle.metadata >> 82) & 1 == 1;\\n }\\n\\n function useDataSourceForRedeem(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return (_fundingCycle.metadata >> 83) & 1 == 1;\\n }\\n\\n function dataSource(JBFundingCycle memory _fundingCycle) internal pure returns (address) {\\n return address(uint160(_fundingCycle.metadata >> 84));\\n }\\n\\n function metadata(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n return uint256(uint8(_fundingCycle.metadata >> 244));\\n }\\n\\n /**\\n @notice\\n Pack the funding cycle metadata.\\n\\n @param _metadata The metadata to validate and pack.\\n\\n @return packed The packed uint256 of all metadata params. The first 8 bits specify the version.\\n */\\n function packFundingCycleMetadata(JBFundingCycleMetadata memory _metadata)\\n internal\\n pure\\n returns (uint256 packed)\\n {\\n // version 1 in the bits 0-7 (8 bits).\\n packed = 1;\\n // global metadta in bits 8-23 (16 bits).\\n packed |=\\n JBGlobalFundingCycleMetadataResolver.packFundingCycleGlobalMetadata(_metadata.global) <<\\n 8;\\n // reserved rate in bits 24-39 (16 bits).\\n packed |= _metadata.reservedRate << 24;\\n // redemption rate in bits 40-55 (16 bits).\\n // redemption rate is a number 0-10000. Store the reverse so the most common case of 100% results in no storage needs.\\n packed |= (JBConstants.MAX_REDEMPTION_RATE - _metadata.redemptionRate) << 40;\\n // ballot redemption rate rate in bits 56-71 (16 bits).\\n // ballot redemption rate is a number 0-10000. Store the reverse so the most common case of 100% results in no storage needs.\\n packed |= (JBConstants.MAX_REDEMPTION_RATE - _metadata.ballotRedemptionRate) << 56;\\n // pause pay in bit 72.\\n if (_metadata.pausePay) packed |= 1 << 72;\\n // pause tap in bit 73.\\n if (_metadata.pauseDistributions) packed |= 1 << 73;\\n // pause redeem in bit 74.\\n if (_metadata.pauseRedeem) packed |= 1 << 74;\\n // pause burn in bit 75.\\n if (_metadata.pauseBurn) packed |= 1 << 75;\\n // allow minting in bit 76.\\n if (_metadata.allowMinting) packed |= 1 << 76;\\n // allow terminal migration in bit 77.\\n if (_metadata.allowTerminalMigration) packed |= 1 << 77;\\n // allow controller migration in bit 78.\\n if (_metadata.allowControllerMigration) packed |= 1 << 78;\\n // hold fees in bit 79.\\n if (_metadata.holdFees) packed |= 1 << 79;\\n // prefer claimed token override in bit 80.\\n if (_metadata.preferClaimedTokenOverride) packed |= 1 << 80;\\n // useTotalOverflowForRedemptions in bit 81.\\n if (_metadata.useTotalOverflowForRedemptions) packed |= 1 << 81;\\n // use pay data source in bit 82.\\n if (_metadata.useDataSourceForPay) packed |= 1 << 82;\\n // use redeem data source in bit 83.\\n if (_metadata.useDataSourceForRedeem) packed |= 1 << 83;\\n // data source address in bits 84-243.\\n packed |= uint256(uint160(address(_metadata.dataSource))) << 84;\\n // metadata in bits 244-252 (8 bits).\\n packed |= _metadata.metadata << 244;\\n }\\n\\n /**\\n @notice\\n Expand the funding cycle metadata.\\n\\n @param _fundingCycle The funding cycle having its metadata expanded.\\n\\n @return metadata The metadata object.\\n */\\n function expandMetadata(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (JBFundingCycleMetadata memory)\\n {\\n return\\n JBFundingCycleMetadata(\\n global(_fundingCycle),\\n reservedRate(_fundingCycle),\\n redemptionRate(_fundingCycle),\\n ballotRedemptionRate(_fundingCycle),\\n payPaused(_fundingCycle),\\n distributionsPaused(_fundingCycle),\\n redeemPaused(_fundingCycle),\\n burnPaused(_fundingCycle),\\n mintingAllowed(_fundingCycle),\\n terminalMigrationAllowed(_fundingCycle),\\n controllerMigrationAllowed(_fundingCycle),\\n shouldHoldFees(_fundingCycle),\\n preferClaimedTokenOverride(_fundingCycle),\\n useTotalOverflowForRedemptions(_fundingCycle),\\n useDataSourceForPay(_fundingCycle),\\n useDataSourceForRedeem(_fundingCycle),\\n dataSource(_fundingCycle),\\n metadata(_fundingCycle)\\n );\\n }\\n}\\n\",\"keccak256\":\"0x3d045c38593102cfb6ac67f3ddf2232e1ff5518d6d021423ae2681387599fbd3\",\"license\":\"MIT\"},\"contracts/libraries/JBGlobalFundingCycleMetadataResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport './../structs/JBFundingCycleMetadata.sol';\\n\\nlibrary JBGlobalFundingCycleMetadataResolver {\\n function setTerminalsAllowed(uint8 _data) internal pure returns (bool) {\\n return (_data & 1) == 1;\\n }\\n\\n function setControllerAllowed(uint8 _data) internal pure returns (bool) {\\n return ((_data >> 1) & 1) == 1;\\n }\\n\\n function transfersPaused(uint8 _data) internal pure returns (bool) {\\n return ((_data >> 2) & 1) == 1;\\n }\\n\\n /**\\n @notice\\n Pack the global funding cycle metadata.\\n\\n @param _metadata The metadata to validate and pack.\\n\\n @return packed The packed uint256 of all global metadata params. The first 8 bits specify the version.\\n */\\n function packFundingCycleGlobalMetadata(JBGlobalFundingCycleMetadata memory _metadata)\\n internal\\n pure\\n returns (uint256 packed)\\n {\\n // allow set terminals in bit 0.\\n if (_metadata.allowSetTerminals) packed |= 1;\\n // allow set controller in bit 1.\\n if (_metadata.allowSetController) packed |= 1 << 1;\\n // pause transfers in bit 2.\\n if (_metadata.pauseTransfers) packed |= 1 << 2;\\n }\\n\\n /**\\n @notice\\n Expand the global funding cycle metadata.\\n\\n @param _packedMetadata The packed metadata to expand.\\n\\n @return metadata The global metadata object.\\n */\\n function expandMetadata(uint8 _packedMetadata)\\n internal\\n pure\\n returns (JBGlobalFundingCycleMetadata memory metadata)\\n {\\n return\\n JBGlobalFundingCycleMetadata(\\n setTerminalsAllowed(_packedMetadata),\\n setControllerAllowed(_packedMetadata),\\n transfersPaused(_packedMetadata)\\n );\\n }\\n}\\n\",\"keccak256\":\"0x0d998f938026edeb755987a79421267cf860801161b5f171206a200b60f1061f\",\"license\":\"MIT\"},\"contracts/libraries/JBOperations.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBOperations {\\n uint256 public constant RECONFIGURE = 1;\\n uint256 public constant REDEEM = 2;\\n uint256 public constant MIGRATE_CONTROLLER = 3;\\n uint256 public constant MIGRATE_TERMINAL = 4;\\n uint256 public constant PROCESS_FEES = 5;\\n uint256 public constant SET_METADATA = 6;\\n uint256 public constant ISSUE = 7;\\n uint256 public constant SET_TOKEN = 8;\\n uint256 public constant MINT = 9;\\n uint256 public constant BURN = 10;\\n uint256 public constant CLAIM = 11;\\n uint256 public constant TRANSFER = 12;\\n uint256 public constant REQUIRE_CLAIM = 13; // unused in v3\\n uint256 public constant SET_CONTROLLER = 14;\\n uint256 public constant SET_TERMINALS = 15;\\n uint256 public constant SET_PRIMARY_TERMINAL = 16;\\n uint256 public constant USE_ALLOWANCE = 17;\\n uint256 public constant SET_SPLITS = 18;\\n}\\n\",\"keccak256\":\"0x7f8e501e6890297f4015b1c27cebdb44fadbf21204bea1f3162f5388c060f690\",\"license\":\"MIT\"},\"contracts/libraries/JBSplitsGroups.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBSplitsGroups {\\n uint256 public constant ETH_PAYOUT = 1;\\n uint256 public constant RESERVED_TOKENS = 2;\\n}\\n\",\"keccak256\":\"0x4183db6087bd8db645fc3a0d3d8afb0d6356e003650793f63c301ebbbae47269\",\"license\":\"MIT\"},\"contracts/libraries/JBTokens.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBTokens {\\n /** \\n @notice \\n The ETH token address in Juicebox is represented by 0x000000000000000000000000000000000000EEEe.\\n */\\n address public constant ETH = address(0x000000000000000000000000000000000000EEEe);\\n}\\n\",\"keccak256\":\"0xecf82992f7b827766aa55f16872517a646521eef414d8cc9786617ea377e5463\",\"license\":\"MIT\"},\"contracts/structs/JBDidPayData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member payer The address from which the payment originated.\\n @member projectId The ID of the project for which the payment was made.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the payment is being made.\\n @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.\\n @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.\\n @member projectTokenCount The number of project tokens minted for the beneficiary.\\n @member beneficiary The address to which the tokens were minted.\\n @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.\\n @member memo The memo that is being emitted alongside the payment.\\n @member metadata Extra data to send to the delegate.\\n*/\\nstruct JBDidPayData {\\n address payer;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n JBTokenAmount amount;\\n JBTokenAmount forwardedAmount;\\n uint256 projectTokenCount;\\n address beneficiary;\\n bool preferClaimedTokens;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0xf3c664309b37790f16047ae97b0459889ae0242dfcde7fc8902c8d10c7f8e6b6\",\"license\":\"MIT\"},\"contracts/structs/JBDidRedeemData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member holder The holder of the tokens being redeemed.\\n @member projectId The ID of the project with which the redeemed tokens are associated.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the redemption is being made.\\n @member projectTokenCount The number of project tokens being redeemed.\\n @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.\\n @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.\\n @member beneficiary The address to which the reclaimed amount will be sent.\\n @member memo The memo that is being emitted alongside the redemption.\\n @member metadata Extra data to send to the delegate.\\n*/\\nstruct JBDidRedeemData {\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 projectTokenCount;\\n JBTokenAmount reclaimedAmount;\\n JBTokenAmount forwardedAmount;\\n address payable beneficiary;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0xe2c401f39723a7ce915b8bef328744c66daaf57460843964b941456c2258a412\",\"license\":\"MIT\"},\"contracts/structs/JBFee.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member amount The total amount the fee was taken from, as a fixed point number with the same number of decimals as the terminal in which this struct was created.\\n @member fee The percent of the fee, out of MAX_FEE.\\n @member feeDiscount The discount of the fee.\\n @member beneficiary The address that will receive the tokens that are minted as a result of the fee payment.\\n*/\\nstruct JBFee {\\n uint256 amount;\\n uint32 fee;\\n uint32 feeDiscount;\\n address beneficiary;\\n}\\n\",\"keccak256\":\"0xf4759ff41fe7f1db0fd1ccc7b2a326b239389fd8d69df9b9ed5e1d5926f6fe38\",\"license\":\"MIT\"},\"contracts/structs/JBFundAccessConstraints.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBPaymentTerminal.sol';\\n\\n/** \\n @member terminal The terminal within which the distribution limit and the overflow allowance applies.\\n @member token The token for which the fund access constraints apply.\\n @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.\\n @member distributionLimitCurrency The currency of the distribution limit.\\n @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.\\n @member overflowAllowanceCurrency The currency of the overflow allowance.\\n*/\\nstruct JBFundAccessConstraints {\\n IJBPaymentTerminal terminal;\\n address token;\\n uint256 distributionLimit;\\n uint256 distributionLimitCurrency;\\n uint256 overflowAllowance;\\n uint256 overflowAllowanceCurrency;\\n}\\n\",\"keccak256\":\"0x85ebaa57b788cbdedc7a3d0eec4892eda5d79db7c1a6103797f10d0d989775b2\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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.\\n @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.\\n @member basedOn The `configuration` of the funding cycle that was active when this cycle was created.\\n @member start The timestamp marking the moment from which the funding cycle is considered active. It is a unix timestamp measured in seconds.\\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n @member metadata Extra data that can be associated with a funding cycle.\\n*/\\nstruct JBFundingCycle {\\n uint256 number;\\n uint256 configuration;\\n uint256 basedOn;\\n uint256 start;\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n uint256 metadata;\\n}\\n\",\"keccak256\":\"0xcdd3ac9b6fa67e62ada88d09b73bc35ade1cd77d43db712289266a788928b4c2\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycleData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n*/\\nstruct JBFundingCycleData {\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n}\\n\",\"keccak256\":\"0x2aa6368bf4dfc5797e8b02a978293de0c777fae2658de2c825a103587240f3b0\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycleMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBGlobalFundingCycleMetadata.sol';\\n\\n/** \\n @member global Data used globally in non-migratable ecosystem contracts.\\n @member reservedRate The reserved rate of the funding cycle. This number is a percentage calculated out of `JBConstants.MAX_RESERVED_RATE`.\\n @member redemptionRate The redemption rate of the funding cycle. This number is a percentage calculated out of `JBConstants.MAX_REDEMPTION_RATE`.\\n @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`.\\n @member pausePay A flag indicating if the pay functionality should be paused during the funding cycle.\\n @member pauseDistributions A flag indicating if the distribute functionality should be paused during the funding cycle.\\n @member pauseRedeem A flag indicating if the redeem functionality should be paused during the funding cycle.\\n @member pauseBurn A flag indicating if the burn functionality should be paused during the funding cycle.\\n @member allowMinting A flag indicating if minting tokens should be allowed during this funding cycle.\\n @member allowTerminalMigration A flag indicating if migrating terminals should be allowed during this funding cycle.\\n @member allowControllerMigration A flag indicating if migrating controllers should be allowed during this funding cycle.\\n @member holdFees A flag indicating if fees should be held during this funding cycle.\\n @member preferClaimedTokenOverride A flag indicating if claimed tokens should always be prefered to unclaimed tokens when minting.\\n @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.\\n @member useDataSourceForPay A flag indicating if the data source should be used for pay transactions during this funding cycle.\\n @member useDataSourceForRedeem A flag indicating if the data source should be used for redeem transactions during this funding cycle.\\n @member dataSource The data source to use during this funding cycle.\\n @member metadata Metadata of the metadata, up to uint8 in size.\\n*/\\nstruct JBFundingCycleMetadata {\\n JBGlobalFundingCycleMetadata global;\\n uint256 reservedRate;\\n uint256 redemptionRate;\\n uint256 ballotRedemptionRate;\\n bool pausePay;\\n bool pauseDistributions;\\n bool pauseRedeem;\\n bool pauseBurn;\\n bool allowMinting;\\n bool allowTerminalMigration;\\n bool allowControllerMigration;\\n bool holdFees;\\n bool preferClaimedTokenOverride;\\n bool useTotalOverflowForRedemptions;\\n bool useDataSourceForPay;\\n bool useDataSourceForRedeem;\\n address dataSource;\\n uint256 metadata;\\n}\\n\",\"keccak256\":\"0x783604440cac8d176332eab28166f188ee5c230378c08cfc95fea4f7187dc77d\",\"license\":\"MIT\"},\"contracts/structs/JBGlobalFundingCycleMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member allowSetTerminals A flag indicating if setting terminals should be allowed during this funding cycle.\\n @member allowSetController A flag indicating if setting a new controller should be allowed during this funding cycle.\\n @member pauseTransfers A flag indicating if the project token transfer functionality should be paused during the funding cycle.\\n*/\\nstruct JBGlobalFundingCycleMetadata {\\n bool allowSetTerminals;\\n bool allowSetController;\\n bool pauseTransfers;\\n}\\n\",\"keccak256\":\"0x05d85530305fec6d6eca54cdbc2cd9110cbda0146598032b0203aa4b622944ff\",\"license\":\"MIT\"},\"contracts/structs/JBGroupedSplits.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBSplit.sol';\\n\\n/** \\n @member group The group indentifier.\\n @member splits The splits to associate with the group.\\n*/\\nstruct JBGroupedSplits {\\n uint256 group;\\n JBSplit[] splits;\\n}\\n\",\"keccak256\":\"0x80be1b220da4ac04851ea540ebb94c1ec2b0442ec5bd1e88fdf78a56becd8b5a\",\"license\":\"MIT\"},\"contracts/structs/JBOperatorData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member operator The address of the operator.\\n @member domain The domain within which the operator is being given permissions. A domain of 0 is a wildcard domain, which gives an operator access to all domains.\\n @member permissionIndexes The indexes of the permissions the operator is being given.\\n*/\\nstruct JBOperatorData {\\n address operator;\\n uint256 domain;\\n uint256[] permissionIndexes;\\n}\\n\",\"keccak256\":\"0x3b85be7b69515976ee10770776283911666aceca820b0cf4e201ea4dbffeb6f0\",\"license\":\"MIT\"},\"contracts/structs/JBPayDelegateAllocation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '../interfaces/IJBPayDelegate.sol';\\n\\n/** \\n @member delegate A delegate contract to use for subsequent calls.\\n @member amount The amount to send to the delegate.\\n*/\\nstruct JBPayDelegateAllocation {\\n IJBPayDelegate delegate;\\n uint256 amount;\\n}\\n\",\"keccak256\":\"0xb4e558dc62231d89e9b48998012577d22c3e52b58e23401f22d9096827f6ea0c\",\"license\":\"MIT\"},\"contracts/structs/JBProjectMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member content The metadata content.\\n @member domain The domain within which the metadata applies.\\n*/\\nstruct JBProjectMetadata {\\n string content;\\n uint256 domain;\\n}\\n\",\"keccak256\":\"0x90ad7b1014c0a9f945fe7a2efde9d5de41e40574fa27969070b1d2ff52033ea0\",\"license\":\"MIT\"},\"contracts/structs/JBRedemptionDelegateAllocation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '../interfaces/IJBRedemptionDelegate.sol';\\n\\n/** \\n @member delegate A delegate contract to use for subsequent calls.\\n @member amount The amount to send to the delegate.\\n*/\\nstruct JBRedemptionDelegateAllocation {\\n IJBRedemptionDelegate delegate;\\n uint256 amount;\\n}\\n\",\"keccak256\":\"0x10c29d33dd0d875a0d4692a2b9a9355c2ebf433cc06a9a60253d4366b60d4d31\",\"license\":\"MIT\"},\"contracts/structs/JBSplit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBSplitAllocator.sol';\\n\\n/** \\n @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.\\n @member preferAddToBalance A flag indicating if a distribution to a project should prefer triggering it's addToBalance function instead of its pay function.\\n @member percent The percent of the whole group that this split occupies. This number is out of `JBConstants.SPLITS_TOTAL_PERCENT`.\\n @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.\\n @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.\\n @member lockedUntil Specifies if the split should be unchangeable until the specified time, with the exception of extending the locked period.\\n @member allocator If an allocator is specified, funds will be sent to the allocator contract along with all properties of this split.\\n*/\\nstruct JBSplit {\\n bool preferClaimed;\\n bool preferAddToBalance;\\n uint256 percent;\\n uint256 projectId;\\n address payable beneficiary;\\n uint256 lockedUntil;\\n IJBSplitAllocator allocator;\\n}\\n\",\"keccak256\":\"0xc80a16606da8abf76d0f73abc38aee041e24f29342c1939018f70c286e89f105\",\"license\":\"MIT\"},\"contracts/structs/JBSplitAllocationData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBSplit.sol';\\n\\n/** \\n @member token The token being sent to the split allocator.\\n @member amount The amount being sent to the split allocator, as a fixed point number.\\n @member decimals The number of decimals in the amount.\\n @member projectId The project to which the split belongs.\\n @member group The group to which the split belongs.\\n @member split The split that caused the allocation.\\n*/\\nstruct JBSplitAllocationData {\\n address token;\\n uint256 amount;\\n uint256 decimals;\\n uint256 projectId;\\n uint256 group;\\n JBSplit split;\\n}\\n\",\"keccak256\":\"0x39f5c41bd31d36774744698ac94484b6cab62d7038df2f29d947668959782e63\",\"license\":\"MIT\"},\"contracts/structs/JBTokenAmount.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/* \\n @member token The token the payment was made in.\\n @member value The amount of tokens that was paid, as a fixed point number.\\n @member decimals The number of decimals included in the value fixed point number.\\n @member currency The expected currency of the value.\\n**/\\nstruct JBTokenAmount {\\n address token;\\n uint256 value;\\n uint256 decimals;\\n uint256 currency;\\n}\\n\",\"keccak256\":\"0x4a778e779ba257ba5638c5469e07a4d21b55a3128d56db5a0fdfacb1f3301c51\",\"license\":\"MIT\"},\"prb-math/contracts/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivFixedPointOverflow(uint256 prod1);\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivOverflow(uint256 prod1, uint256 denominator);\\n\\n/// @notice Emitted when one of the inputs is type(int256).min.\\nerror PRBMath__MulDivSignedInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows int256.\\nerror PRBMath__MulDivSignedOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is MIN_SD59x18.\\nerror PRBMathSD59x18__AbsInputTooSmall();\\n\\n/// @notice Emitted when ceiling a number overflows SD59x18.\\nerror PRBMathSD59x18__CeilOverflow(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__DivInputTooSmall();\\n\\n/// @notice Emitted when one of the intermediary unsigned results overflows SD59x18.\\nerror PRBMathSD59x18__DivOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathSD59x18__ExpInputTooBig(int256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathSD59x18__Exp2InputTooBig(int256 x);\\n\\n/// @notice Emitted when flooring a number underflows SD59x18.\\nerror PRBMathSD59x18__FloorUnderflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format overflows SD59x18.\\nerror PRBMathSD59x18__FromIntOverflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format underflows SD59x18.\\nerror PRBMathSD59x18__FromIntUnderflow(int256 x);\\n\\n/// @notice Emitted when the product of the inputs is negative.\\nerror PRBMathSD59x18__GmNegativeProduct(int256 x, int256 y);\\n\\n/// @notice Emitted when multiplying the inputs overflows SD59x18.\\nerror PRBMathSD59x18__GmOverflow(int256 x, int256 y);\\n\\n/// @notice Emitted when the input is less than or equal to zero.\\nerror PRBMathSD59x18__LogInputTooSmall(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__MulInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__MulOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__PowuOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is negative.\\nerror PRBMathSD59x18__SqrtNegativeInput(int256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows SD59x18.\\nerror PRBMathSD59x18__SqrtOverflow(int256 x);\\n\\n/// @notice Emitted when addition overflows UD60x18.\\nerror PRBMathUD60x18__AddOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when ceiling a number overflows UD60x18.\\nerror PRBMathUD60x18__CeilOverflow(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathUD60x18__ExpInputTooBig(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathUD60x18__Exp2InputTooBig(uint256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format format overflows UD60x18.\\nerror PRBMathUD60x18__FromUintOverflow(uint256 x);\\n\\n/// @notice Emitted when multiplying the inputs overflows UD60x18.\\nerror PRBMathUD60x18__GmOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when the input is less than 1.\\nerror PRBMathUD60x18__LogInputTooSmall(uint256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows UD60x18.\\nerror PRBMathUD60x18__SqrtOverflow(uint256 x);\\n\\n/// @notice Emitted when subtraction underflows UD60x18.\\nerror PRBMathUD60x18__SubUnderflow(uint256 x, uint256 y);\\n\\n/// @dev Common mathematical functions used in both PRBMathSD59x18 and PRBMathUD60x18. Note that this shared library\\n/// does not always assume the signed 59.18-decimal fixed-point or the unsigned 60.18-decimal fixed-point\\n/// representation. When it does not, it is explicitly mentioned in the NatSpec documentation.\\nlibrary PRBMath {\\n /// STRUCTS ///\\n\\n struct SD59x18 {\\n int256 value;\\n }\\n\\n struct UD60x18 {\\n uint256 value;\\n }\\n\\n /// STORAGE ///\\n\\n /// @dev How many trailing decimals can be represented.\\n uint256 internal constant SCALE = 1e18;\\n\\n /// @dev Largest power of two divisor of SCALE.\\n uint256 internal constant SCALE_LPOTD = 262144;\\n\\n /// @dev SCALE inverted mod 2^256.\\n uint256 internal constant SCALE_INVERSE =\\n 78156646155174841979727994598816262306175212592076161876661_508869554232690281;\\n\\n /// FUNCTIONS ///\\n\\n /// @notice Calculates the binary exponent of x using the binary fraction method.\\n /// @dev Has to use 192.64-bit fixed-point numbers.\\n /// See https://ethereum.stackexchange.com/a/96594/24693.\\n /// @param x The exponent as an unsigned 192.64-bit fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp2(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n // Start from 0.5 in the 192.64-bit fixed-point format.\\n result = 0x800000000000000000000000000000000000000000000000;\\n\\n // Multiply the result by root(2, 2^-i) when the bit at position i is 1. None of the intermediary results overflows\\n // because the initial result is 2^191 and all magic factors are less than 2^65.\\n if (x & 0x8000000000000000 > 0) {\\n result = (result * 0x16A09E667F3BCC909) >> 64;\\n }\\n if (x & 0x4000000000000000 > 0) {\\n result = (result * 0x1306FE0A31B7152DF) >> 64;\\n }\\n if (x & 0x2000000000000000 > 0) {\\n result = (result * 0x1172B83C7D517ADCE) >> 64;\\n }\\n if (x & 0x1000000000000000 > 0) {\\n result = (result * 0x10B5586CF9890F62A) >> 64;\\n }\\n if (x & 0x800000000000000 > 0) {\\n result = (result * 0x1059B0D31585743AE) >> 64;\\n }\\n if (x & 0x400000000000000 > 0) {\\n result = (result * 0x102C9A3E778060EE7) >> 64;\\n }\\n if (x & 0x200000000000000 > 0) {\\n result = (result * 0x10163DA9FB33356D8) >> 64;\\n }\\n if (x & 0x100000000000000 > 0) {\\n result = (result * 0x100B1AFA5ABCBED61) >> 64;\\n }\\n if (x & 0x80000000000000 > 0) {\\n result = (result * 0x10058C86DA1C09EA2) >> 64;\\n }\\n if (x & 0x40000000000000 > 0) {\\n result = (result * 0x1002C605E2E8CEC50) >> 64;\\n }\\n if (x & 0x20000000000000 > 0) {\\n result = (result * 0x100162F3904051FA1) >> 64;\\n }\\n if (x & 0x10000000000000 > 0) {\\n result = (result * 0x1000B175EFFDC76BA) >> 64;\\n }\\n if (x & 0x8000000000000 > 0) {\\n result = (result * 0x100058BA01FB9F96D) >> 64;\\n }\\n if (x & 0x4000000000000 > 0) {\\n result = (result * 0x10002C5CC37DA9492) >> 64;\\n }\\n if (x & 0x2000000000000 > 0) {\\n result = (result * 0x1000162E525EE0547) >> 64;\\n }\\n if (x & 0x1000000000000 > 0) {\\n result = (result * 0x10000B17255775C04) >> 64;\\n }\\n if (x & 0x800000000000 > 0) {\\n result = (result * 0x1000058B91B5BC9AE) >> 64;\\n }\\n if (x & 0x400000000000 > 0) {\\n result = (result * 0x100002C5C89D5EC6D) >> 64;\\n }\\n if (x & 0x200000000000 > 0) {\\n result = (result * 0x10000162E43F4F831) >> 64;\\n }\\n if (x & 0x100000000000 > 0) {\\n result = (result * 0x100000B1721BCFC9A) >> 64;\\n }\\n if (x & 0x80000000000 > 0) {\\n result = (result * 0x10000058B90CF1E6E) >> 64;\\n }\\n if (x & 0x40000000000 > 0) {\\n result = (result * 0x1000002C5C863B73F) >> 64;\\n }\\n if (x & 0x20000000000 > 0) {\\n result = (result * 0x100000162E430E5A2) >> 64;\\n }\\n if (x & 0x10000000000 > 0) {\\n result = (result * 0x1000000B172183551) >> 64;\\n }\\n if (x & 0x8000000000 > 0) {\\n result = (result * 0x100000058B90C0B49) >> 64;\\n }\\n if (x & 0x4000000000 > 0) {\\n result = (result * 0x10000002C5C8601CC) >> 64;\\n }\\n if (x & 0x2000000000 > 0) {\\n result = (result * 0x1000000162E42FFF0) >> 64;\\n }\\n if (x & 0x1000000000 > 0) {\\n result = (result * 0x10000000B17217FBB) >> 64;\\n }\\n if (x & 0x800000000 > 0) {\\n result = (result * 0x1000000058B90BFCE) >> 64;\\n }\\n if (x & 0x400000000 > 0) {\\n result = (result * 0x100000002C5C85FE3) >> 64;\\n }\\n if (x & 0x200000000 > 0) {\\n result = (result * 0x10000000162E42FF1) >> 64;\\n }\\n if (x & 0x100000000 > 0) {\\n result = (result * 0x100000000B17217F8) >> 64;\\n }\\n if (x & 0x80000000 > 0) {\\n result = (result * 0x10000000058B90BFC) >> 64;\\n }\\n if (x & 0x40000000 > 0) {\\n result = (result * 0x1000000002C5C85FE) >> 64;\\n }\\n if (x & 0x20000000 > 0) {\\n result = (result * 0x100000000162E42FF) >> 64;\\n }\\n if (x & 0x10000000 > 0) {\\n result = (result * 0x1000000000B17217F) >> 64;\\n }\\n if (x & 0x8000000 > 0) {\\n result = (result * 0x100000000058B90C0) >> 64;\\n }\\n if (x & 0x4000000 > 0) {\\n result = (result * 0x10000000002C5C860) >> 64;\\n }\\n if (x & 0x2000000 > 0) {\\n result = (result * 0x1000000000162E430) >> 64;\\n }\\n if (x & 0x1000000 > 0) {\\n result = (result * 0x10000000000B17218) >> 64;\\n }\\n if (x & 0x800000 > 0) {\\n result = (result * 0x1000000000058B90C) >> 64;\\n }\\n if (x & 0x400000 > 0) {\\n result = (result * 0x100000000002C5C86) >> 64;\\n }\\n if (x & 0x200000 > 0) {\\n result = (result * 0x10000000000162E43) >> 64;\\n }\\n if (x & 0x100000 > 0) {\\n result = (result * 0x100000000000B1721) >> 64;\\n }\\n if (x & 0x80000 > 0) {\\n result = (result * 0x10000000000058B91) >> 64;\\n }\\n if (x & 0x40000 > 0) {\\n result = (result * 0x1000000000002C5C8) >> 64;\\n }\\n if (x & 0x20000 > 0) {\\n result = (result * 0x100000000000162E4) >> 64;\\n }\\n if (x & 0x10000 > 0) {\\n result = (result * 0x1000000000000B172) >> 64;\\n }\\n if (x & 0x8000 > 0) {\\n result = (result * 0x100000000000058B9) >> 64;\\n }\\n if (x & 0x4000 > 0) {\\n result = (result * 0x10000000000002C5D) >> 64;\\n }\\n if (x & 0x2000 > 0) {\\n result = (result * 0x1000000000000162E) >> 64;\\n }\\n if (x & 0x1000 > 0) {\\n result = (result * 0x10000000000000B17) >> 64;\\n }\\n if (x & 0x800 > 0) {\\n result = (result * 0x1000000000000058C) >> 64;\\n }\\n if (x & 0x400 > 0) {\\n result = (result * 0x100000000000002C6) >> 64;\\n }\\n if (x & 0x200 > 0) {\\n result = (result * 0x10000000000000163) >> 64;\\n }\\n if (x & 0x100 > 0) {\\n result = (result * 0x100000000000000B1) >> 64;\\n }\\n if (x & 0x80 > 0) {\\n result = (result * 0x10000000000000059) >> 64;\\n }\\n if (x & 0x40 > 0) {\\n result = (result * 0x1000000000000002C) >> 64;\\n }\\n if (x & 0x20 > 0) {\\n result = (result * 0x10000000000000016) >> 64;\\n }\\n if (x & 0x10 > 0) {\\n result = (result * 0x1000000000000000B) >> 64;\\n }\\n if (x & 0x8 > 0) {\\n result = (result * 0x10000000000000006) >> 64;\\n }\\n if (x & 0x4 > 0) {\\n result = (result * 0x10000000000000003) >> 64;\\n }\\n if (x & 0x2 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n if (x & 0x1 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n\\n // We're doing two things at the same time:\\n //\\n // 1. Multiply the result by 2^n + 1, where \\\"2^n\\\" is the integer part and the one is added to account for\\n // the fact that we initially set the result to 0.5. This is accomplished by subtracting from 191\\n // rather than 192.\\n // 2. Convert the result to the unsigned 60.18-decimal fixed-point format.\\n //\\n // This works because 2^(191-ip) = 2^ip / 2^191, where \\\"ip\\\" is the integer part \\\"2^n\\\".\\n result *= SCALE;\\n result >>= (191 - (x >> 64));\\n }\\n }\\n\\n /// @notice Finds the zero-based index of the first one in the binary representation of x.\\n /// @dev See the note on msb in the \\\"Find First Set\\\" Wikipedia article https://en.wikipedia.org/wiki/Find_first_set\\n /// @param x The uint256 number for which to find the index of the most significant bit.\\n /// @return msb The index of the most significant bit as an uint256.\\n function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\\n if (x >= 2**128) {\\n x >>= 128;\\n msb += 128;\\n }\\n if (x >= 2**64) {\\n x >>= 64;\\n msb += 64;\\n }\\n if (x >= 2**32) {\\n x >>= 32;\\n msb += 32;\\n }\\n if (x >= 2**16) {\\n x >>= 16;\\n msb += 16;\\n }\\n if (x >= 2**8) {\\n x >>= 8;\\n msb += 8;\\n }\\n if (x >= 2**4) {\\n x >>= 4;\\n msb += 4;\\n }\\n if (x >= 2**2) {\\n x >>= 2;\\n msb += 2;\\n }\\n if (x >= 2**1) {\\n // No need to shift x any more.\\n msb += 1;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.\\n ///\\n /// Requirements:\\n /// - The denominator cannot be zero.\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The multiplicand as an uint256.\\n /// @param y The multiplier as an uint256.\\n /// @param denominator The divisor as an uint256.\\n /// @return result The result as an uint256.\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n unchecked {\\n result = prod0 / denominator;\\n }\\n return result;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n if (prod1 >= denominator) {\\n revert PRBMath__MulDivOverflow(prod1, denominator);\\n }\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n unchecked {\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 lpotdod = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by lpotdod.\\n denominator := div(denominator, lpotdod)\\n\\n // Divide [prod1 prod0] by lpotdod.\\n prod0 := div(prod0, lpotdod)\\n\\n // Flip lpotdod such that it is 2^256 / lpotdod. If lpotdod is zero, then it becomes one.\\n lpotdod := add(div(sub(0, lpotdod), lpotdod), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * lpotdod;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f71e18) with full precision.\\n ///\\n /// @dev Variant of \\\"mulDiv\\\" with constant folding, i.e. in which the denominator is always 1e18. Before returning the\\n /// final result, we add 1 if (x * y) % SCALE >= HALF_SCALE. Without this, 6.6e-19 would be truncated to 0 instead of\\n /// being rounded to 1e-18. See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717.\\n ///\\n /// Requirements:\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - The body is purposely left uncommented; see the NatSpec comments in \\\"PRBMath.mulDiv\\\" to understand how this works.\\n /// - It is assumed that the result can never be type(uint256).max when x and y solve the following two equations:\\n /// 1. x * y = type(uint256).max * SCALE\\n /// 2. (x * y) % SCALE >= SCALE / 2\\n ///\\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function mulDivFixedPoint(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n uint256 prod0;\\n uint256 prod1;\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n if (prod1 >= SCALE) {\\n revert PRBMath__MulDivFixedPointOverflow(prod1);\\n }\\n\\n uint256 remainder;\\n uint256 roundUpUnit;\\n assembly {\\n remainder := mulmod(x, y, SCALE)\\n roundUpUnit := gt(remainder, 499999999999999999)\\n }\\n\\n if (prod1 == 0) {\\n unchecked {\\n result = (prod0 / SCALE) + roundUpUnit;\\n return result;\\n }\\n }\\n\\n assembly {\\n result := add(\\n mul(\\n or(\\n div(sub(prod0, remainder), SCALE_LPOTD),\\n mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, SCALE_LPOTD), SCALE_LPOTD), 1))\\n ),\\n SCALE_INVERSE\\n ),\\n roundUpUnit\\n )\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev An extension of \\\"mulDiv\\\" for signed numbers. Works by computing the signs and the absolute values separately.\\n ///\\n /// Requirements:\\n /// - None of the inputs can be type(int256).min.\\n /// - The result must fit within int256.\\n ///\\n /// @param x The multiplicand as an int256.\\n /// @param y The multiplier as an int256.\\n /// @param denominator The divisor as an int256.\\n /// @return result The result as an int256.\\n function mulDivSigned(\\n int256 x,\\n int256 y,\\n int256 denominator\\n ) internal pure returns (int256 result) {\\n if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {\\n revert PRBMath__MulDivSignedInputTooSmall();\\n }\\n\\n // Get hold of the absolute values of x, y and the denominator.\\n uint256 ax;\\n uint256 ay;\\n uint256 ad;\\n unchecked {\\n ax = x < 0 ? uint256(-x) : uint256(x);\\n ay = y < 0 ? uint256(-y) : uint256(y);\\n ad = denominator < 0 ? uint256(-denominator) : uint256(denominator);\\n }\\n\\n // Compute the absolute value of (x*y)\\u00f7denominator. The result must fit within int256.\\n uint256 rAbs = mulDiv(ax, ay, ad);\\n if (rAbs > uint256(type(int256).max)) {\\n revert PRBMath__MulDivSignedOverflow(rAbs);\\n }\\n\\n // Get the signs of x, y and the denominator.\\n uint256 sx;\\n uint256 sy;\\n uint256 sd;\\n assembly {\\n sx := sgt(x, sub(0, 1))\\n sy := sgt(y, sub(0, 1))\\n sd := sgt(denominator, sub(0, 1))\\n }\\n\\n // XOR over sx, sy and sd. This is checking whether there are one or three negative signs in the inputs.\\n // If yes, the result should be negative.\\n result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs);\\n }\\n\\n /// @notice Calculates the square root of x, rounding down.\\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The uint256 number for which to calculate the square root.\\n /// @return result The result as an uint256.\\n function sqrt(uint256 x) internal pure returns (uint256 result) {\\n if (x == 0) {\\n return 0;\\n }\\n\\n // Set the initial guess to the closest power of two that is higher than x.\\n uint256 xAux = uint256(x);\\n result = 1;\\n if (xAux >= 0x100000000000000000000000000000000) {\\n xAux >>= 128;\\n result <<= 64;\\n }\\n if (xAux >= 0x10000000000000000) {\\n xAux >>= 64;\\n result <<= 32;\\n }\\n if (xAux >= 0x100000000) {\\n xAux >>= 32;\\n result <<= 16;\\n }\\n if (xAux >= 0x10000) {\\n xAux >>= 16;\\n result <<= 8;\\n }\\n if (xAux >= 0x100) {\\n xAux >>= 8;\\n result <<= 4;\\n }\\n if (xAux >= 0x10) {\\n xAux >>= 4;\\n result <<= 2;\\n }\\n if (xAux >= 0x8) {\\n result <<= 1;\\n }\\n\\n // The operations can never overflow because the result is max 2^127 when it enters this block.\\n unchecked {\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1; // Seven iterations should be enough\\n uint256 roundedDownResult = x / result;\\n return result >= roundedDownResult ? roundedDownResult : result;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x62cbabae4910e168e99b9c2c3e3b5c9c7ad5e7abd961dcc63b7ea3d83d8ea87e\",\"license\":\"Unlicense\"}},\"version\":1}", + "metadata": "{\"compiler\":{\"version\":\"0.8.16+commit.07a7930e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_baseWeightCurrency\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBOperatorStore\",\"name\":\"_operatorStore\",\"type\":\"address\"},{\"internalType\":\"contract IJBProjects\",\"name\":\"_projects\",\"type\":\"address\"},{\"internalType\":\"contract IJBDirectory\",\"name\":\"_directory\",\"type\":\"address\"},{\"internalType\":\"contract IJBSplitsStore\",\"name\":\"_splitsStore\",\"type\":\"address\"},{\"internalType\":\"contract IJBPrices\",\"name\":\"_prices\",\"type\":\"address\"},{\"internalType\":\"contract IJBSingleTokenPaymentTerminalStore\",\"name\":\"_store\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"FEE_TOO_HIGH\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INADEQUATE_DISTRIBUTION_AMOUNT\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INADEQUATE_RECLAIM_AMOUNT\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INADEQUATE_TOKEN_COUNT\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NO_MSG_VALUE_ALLOWED\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PAY_TO_ZERO_ADDRESS\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"prod1\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"denominator\",\"type\":\"uint256\"}],\"name\":\"PRBMath__MulDivOverflow\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PROJECT_TERMINAL_MISMATCH\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"REDEEM_TO_ZERO_ADDRESS\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TERMINAL_IN_SPLIT_ZERO_ADDRESS\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TERMINAL_TOKENS_INCOMPATIBLE\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UNAUTHORIZED\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"refundedFees\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AddToBalance\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IJBPayDelegate\",\"name\":\"delegate\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"currentFundingCycleConfiguration\",\"type\":\"uint256\"},{\"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\"},{\"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\":\"forwardedAmount\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"projectTokenCount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"preferClaimedTokens\",\"type\":\"bool\"},{\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"struct JBDidPayData\",\"name\":\"data\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"delegatedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"DelegateDidPay\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IJBRedemptionDelegate\",\"name\":\"delegate\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"currentFundingCycleConfiguration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"projectTokenCount\",\"type\":\"uint256\"},{\"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\":\"reclaimedAmount\",\"type\":\"tuple\"},{\"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\":\"forwardedAmount\",\"type\":\"tuple\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"struct JBDidRedeemData\",\"name\":\"data\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"delegatedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"DelegateDidRedeem\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleConfiguration\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleNumber\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"distributedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"beneficiaryDistributionAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"DistributePayouts\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"domain\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"group\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"preferClaimed\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"preferAddToBalance\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"percent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"lockedUntil\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBSplitAllocator\",\"name\":\"allocator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"struct JBSplit\",\"name\":\"split\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"netAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"DistributeToPayoutSplit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"feeProjectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"reason\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"FeeReverted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"feeDiscount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"HoldFee\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"contract IJBPaymentTerminal\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Migrate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleConfiguration\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleNumber\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"beneficiaryTokenCount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"Pay\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"preferClaimed\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"preferAddToBalance\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"percent\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"internalType\":\"address payable\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"lockedUntil\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBSplitAllocator\",\"name\":\"allocator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"struct JBSplit\",\"name\":\"split\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"reason\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"PayoutReverted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"wasHeld\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"ProcessFee\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleConfiguration\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleNumber\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenCount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"reclaimedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"RedeemTokens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"refundedFees\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"leftoverAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"RefundHeldFees\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"fee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"SetFee\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IJBFeeGauge\",\"name\":\"feeGauge\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"SetFeeGauge\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"addrs\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"flag\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"SetFeelessAddress\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleConfiguration\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"fundingCycleNumber\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"projectId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"distributedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"netDistributedamount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"UseAllowance\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"}],\"name\":\"acceptsToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"addToBalanceOf\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_shouldRefundHeldFees\",\"type\":\"bool\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"addToBalanceOf\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"baseWeightCurrency\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currency\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"currencyForToken\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"}],\"name\":\"currentEthOverflowOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"name\":\"decimalsForToken\",\"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\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_currency\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_minReturnedTokens\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"distributePayoutsOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"netLeftoverDistributionAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"feeGauge\",\"outputs\":[{\"internalType\":\"contract IJBFeeGauge\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"}],\"name\":\"heldFeesOf\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"fee\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"feeDiscount\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"internalType\":\"struct JBFee[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isFeelessAddress\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBPaymentTerminal\",\"name\":\"_to\",\"type\":\"address\"}],\"name\":\"migrate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"operatorStore\",\"outputs\":[{\"internalType\":\"contract IJBOperatorStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_minReturnedTokens\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"_preferClaimedTokens\",\"type\":\"bool\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"pay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"payoutSplitsGroup\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"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\"}],\"name\":\"processFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"projects\",\"outputs\":[{\"internalType\":\"contract IJBProjects\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_holder\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_tokenCount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_minReturnedTokens\",\"type\":\"uint256\"},{\"internalType\":\"address payable\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"redeemTokensOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"reclaimAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_fee\",\"type\":\"uint256\"}],\"name\":\"setFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IJBFeeGauge\",\"name\":\"_feeGauge\",\"type\":\"address\"}],\"name\":\"setFeeGauge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"_flag\",\"type\":\"bool\"}],\"name\":\"setFeelessAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"splitsStore\",\"outputs\":[{\"internalType\":\"contract IJBSplitsStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"store\",\"outputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminalStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_currency\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_minReturnedTokens\",\"type\":\"uint256\"},{\"internalType\":\"address payable\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"useAllowanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"netDistributedAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Inherits from - JBPayoutRedemptionPaymentTerminal3_1: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\",\"kind\":\"dev\",\"methods\":{\"acceptsToken(address,uint256)\":{\"params\":{\"_projectId\":\"The project ID to check for token acceptance.\",\"_token\":\"The token to check if this terminal accepts or not.\"},\"returns\":{\"_0\":\"The flag.\"}},\"addToBalanceOf(uint256,uint256,address,bool,string,bytes)\":{\"params\":{\"_amount\":\"The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\",\"_memo\":\"A memo to pass along to the emitted event.\",\"_metadata\":\"Extra data to pass along to the emitted event.\",\"_projectId\":\"The ID of the project to which the funds received belong.\",\"_shouldRefundHeldFees\":\"A flag indicating if held fees should be refunded based on the amount being added.\",\"_token\":\"The token being paid. This terminal ignores this property since it only manages one currency. \"}},\"addToBalanceOf(uint256,uint256,address,string,bytes)\":{\"params\":{\"_amount\":\"The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\",\"_memo\":\"A memo to pass along to the emitted event.\",\"_metadata\":\"Extra data to pass along to the emitted event.\",\"_projectId\":\"The ID of the project to which the funds received belong.\",\"_token\":\"The token being paid. This terminal ignores this property since it only manages one currency. \"}},\"constructor\":{\"params\":{\"_baseWeightCurrency\":\"The currency to base token issuance on.\",\"_directory\":\"A contract storing directories of terminals and controllers for each project.\",\"_operatorStore\":\"A contract storing operator assignments.\",\"_owner\":\"The address that will own this contract.\",\"_prices\":\"A contract that exposes price feeds.\",\"_projects\":\"A contract which mints ERC-721's that represent project ownership and transfers.\",\"_splitsStore\":\"A contract that stores splits for each project.\",\"_store\":\"A contract that stores the terminal's data.\"}},\"currencyForToken(address)\":{\"params\":{\"_token\":\"The token to check for the currency of.\"},\"returns\":{\"_0\":\"The currency index.\"}},\"currentEthOverflowOf(uint256)\":{\"details\":\"The current overflow is represented as a fixed point number with 18 decimals.\",\"params\":{\"_projectId\":\"The ID of the project to get overflow for.\"},\"returns\":{\"_0\":\"The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\"}},\"decimalsForToken(address)\":{\"params\":{\"_token\":\"The token to check for the decimals of.\"},\"returns\":{\"_0\":\"The number of decimals for the token.\"}},\"distributePayoutsOf(uint256,uint256,uint256,address,uint256,bytes)\":{\"details\":\"Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\",\"params\":{\"_amount\":\"The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\",\"_currency\":\"The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\",\"_metadata\":\"Bytes to send along to the emitted event, if provided.\",\"_minReturnedTokens\":\"The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\",\"_projectId\":\"The ID of the project having its payouts distributed.\",\"_token\":\"The token being distributed. This terminal ignores this property since it only manages one token. \"},\"returns\":{\"netLeftoverDistributionAmount\":\"The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\"}},\"heldFeesOf(uint256)\":{\"params\":{\"_projectId\":\"The ID of the project for which fees are being held.\"},\"returns\":{\"_0\":\"An array of fees that are being held.\"}},\"migrate(uint256,address)\":{\"details\":\"Only a project's owner or a designated operator can migrate it.\",\"params\":{\"_projectId\":\"The ID of the project being migrated.\",\"_to\":\"The terminal contract that will gain the project's funds.\"},\"returns\":{\"balance\":\"The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pay(uint256,uint256,address,address,uint256,bool,string,bytes)\":{\"params\":{\"_amount\":\"The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\",\"_beneficiary\":\"The address to mint tokens for and pass along to the funding cycle's data source and delegate.\",\"_memo\":\"A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\",\"_metadata\":\"Bytes to send along to the data source, delegate, and emitted event, if provided.\",\"_minReturnedTokens\":\"The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\",\"_preferClaimedTokens\":\"A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\",\"_projectId\":\"The ID of the project being paid.\",\"_token\":\"The token being paid. This terminal ignores this property since it only manages one token. \"},\"returns\":{\"_0\":\"The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\"}},\"processFees(uint256)\":{\"details\":\"Only a project owner, an operator, or the contract's owner can process held fees.\",\"params\":{\"_projectId\":\"The ID of the project whos held fees should be processed.\"}},\"redeemTokensOf(address,uint256,uint256,address,uint256,address,string,bytes)\":{\"details\":\"Only a token holder or a designated operator can redeem its tokens.\",\"params\":{\"_beneficiary\":\"The address to send the terminal tokens to.\",\"_holder\":\"The account to redeem tokens for.\",\"_memo\":\"A memo to pass along to the emitted event.\",\"_metadata\":\"Bytes to send along to the data source, delegate, and emitted event, if provided.\",\"_minReturnedTokens\":\"The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\",\"_projectId\":\"The ID of the project to which the tokens being redeemed belong.\",\"_token\":\"The token being reclaimed. This terminal ignores this property since it only manages one token. \",\"_tokenCount\":\"The number of project tokens to redeem, as a fixed point number with 18 decimals.\"},\"returns\":{\"reclaimAmount\":\"The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"setFee(uint256)\":{\"details\":\"Only the owner of this contract can change the fee.\",\"params\":{\"_fee\":\"The new fee, out of MAX_FEE.\"}},\"setFeeGauge(address)\":{\"details\":\"Only the owner of this contract can change the fee gauge.\",\"params\":{\"_feeGauge\":\"The new fee gauge.\"}},\"setFeelessAddress(address,bool)\":{\"details\":\"Only the owner of this contract can set addresses as feeless.\",\"params\":{\"_address\":\"The address that can be paid towards while still bypassing fees.\",\"_flag\":\"A flag indicating whether the terminal should be feeless or not.\"}},\"supportsInterface(bytes4)\":{\"details\":\" See {IERC165-supportsInterface}.\",\"params\":{\"_interfaceId\":\"The ID of the interface to check for adherance to.\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"useAllowanceOf(uint256,uint256,uint256,address,uint256,address,string,bytes)\":{\"details\":\"Only a project's owner or a designated operator can use its allowance.Incurs the protocol fee.\",\"params\":{\"_amount\":\"The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\",\"_beneficiary\":\"The address to send the funds to.\",\"_currency\":\"The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\",\"_memo\":\"A memo to pass along to the emitted event.\",\"_metadata\":\"Bytes to send along to the emitted event, if provided.\",\"_minReturnedTokens\":\"The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\",\"_projectId\":\"The ID of the project to use the allowance of.\",\"_token\":\"The token being distributed. This terminal ignores this property since it only manages one token. \"},\"returns\":{\"netDistributedAmount\":\"The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\"}}},\"version\":1},\"userdoc\":{\"errors\":{\"PRBMath__MulDivOverflow(uint256,uint256)\":[{\"notice\":\"Emitted when the result overflows uint256.\"}]},\"kind\":\"user\",\"methods\":{\"acceptsToken(address,uint256)\":{\"notice\":\"A flag indicating if this terminal accepts the specified token.\"},\"addToBalanceOf(uint256,uint256,address,bool,string,bytes)\":{\"notice\":\"Receives funds belonging to the specified project.\"},\"addToBalanceOf(uint256,uint256,address,string,bytes)\":{\"notice\":\"Receives funds belonging to the specified project.\"},\"baseWeightCurrency()\":{\"notice\":\"The currency to base token issuance on.\"},\"currency()\":{\"notice\":\"The currency to use when resolving price feeds for this terminal.\"},\"currencyForToken(address)\":{\"notice\":\"The currency that should be used for the specified token.\"},\"currentEthOverflowOf(uint256)\":{\"notice\":\"Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\"},\"decimals()\":{\"notice\":\"The number of decimals the token fixed point amounts are expected to have.\"},\"decimalsForToken(address)\":{\"notice\":\"The decimals that should be used in fixed number accounting for the specified token.\"},\"directory()\":{\"notice\":\"The directory of terminals and controllers for projects.\"},\"distributePayoutsOf(uint256,uint256,uint256,address,uint256,bytes)\":{\"notice\":\"Distributes payouts for a project with the distribution limit of its current funding cycle.\"},\"fee()\":{\"notice\":\"The platform fee percent.\"},\"feeGauge()\":{\"notice\":\"The data source that returns a discount to apply to a project's fee.\"},\"heldFeesOf(uint256)\":{\"notice\":\"The fees that are currently being held to be processed later for each project.\"},\"isFeelessAddress(address)\":{\"notice\":\"Addresses that can be paid towards from this terminal without incurring a fee.\"},\"migrate(uint256,address)\":{\"notice\":\"Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\"},\"operatorStore()\":{\"notice\":\" A contract storing operator assignments.\"},\"pay(uint256,uint256,address,address,uint256,bool,string,bytes)\":{\"notice\":\"Contribute tokens to a project.\"},\"payoutSplitsGroup()\":{\"notice\":\"The group that payout splits coming from this terminal are identified by.\"},\"prices()\":{\"notice\":\"The contract that exposes price feeds.\"},\"processFees(uint256)\":{\"notice\":\"Process any fees that are being held for the project.\"},\"projects()\":{\"notice\":\"Mints ERC-721's that represent project ownership and transfers.\"},\"redeemTokensOf(address,uint256,uint256,address,uint256,address,string,bytes)\":{\"notice\":\"Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\"},\"setFee(uint256)\":{\"notice\":\"Allows the fee to be updated.\"},\"setFeeGauge(address)\":{\"notice\":\"Allows the fee gauge to be updated.\"},\"setFeelessAddress(address,bool)\":{\"notice\":\"Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\"},\"splitsStore()\":{\"notice\":\"The contract that stores splits for each project.\"},\"store()\":{\"notice\":\"The contract that stores and manages the terminal's data.\"},\"supportsInterface(bytes4)\":{\"notice\":\"Indicates if this contract adheres to the specified interface.\"},\"token()\":{\"notice\":\"The token that this terminal accepts.\"},\"useAllowanceOf(uint256,uint256,uint256,address,uint256,address,string,bytes)\":{\"notice\":\"Allows a project to send funds from its overflow up to the preconfigured allowance.\"}},\"notice\":\"Manages all inflows and outflows of ETH funds into the protocol ecosystem.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/JBETHPaymentTerminal3_1.sol\":\"JBETHPaymentTerminal3_1\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0x24e0364e503a9bbde94c715d26573a76f14cd2a202d45f96f52134ab806b67b9\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool _approved) external;\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x516a22876c1fab47f49b1bc22b4614491cd05338af8bd2e7b382da090a079990\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3777e696b62134e6177440dbe6e6601c0c156a443f57167194b67e75527439de\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes calldata) {\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC165} interface.\\n *\\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\\n * for the additional interface id that will be supported. For example:\\n *\\n * ```solidity\\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\\n * }\\n * ```\\n *\\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\\n */\\nabstract contract ERC165 is IERC165 {\\n /**\\n * @dev See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\\n return interfaceId == type(IERC165).interfaceId;\\n }\\n}\\n\",\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/ERC165Checker.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165Checker.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC165.sol\\\";\\n\\n/**\\n * @dev Library used to query support of an interface declared via {IERC165}.\\n *\\n * Note that these functions return the actual result of the query: they do not\\n * `revert` if an interface is not supported. It is up to the caller to decide\\n * what to do in these cases.\\n */\\nlibrary ERC165Checker {\\n // As per the EIP-165 spec, no interface should ever match 0xffffffff\\n bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;\\n\\n /**\\n * @dev Returns true if `account` supports the {IERC165} interface,\\n */\\n function supportsERC165(address account) internal view returns (bool) {\\n // Any contract that implements ERC165 must explicitly indicate support of\\n // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid\\n return\\n _supportsERC165Interface(account, type(IERC165).interfaceId) &&\\n !_supportsERC165Interface(account, _INTERFACE_ID_INVALID);\\n }\\n\\n /**\\n * @dev Returns true if `account` supports the interface defined by\\n * `interfaceId`. Support for {IERC165} itself is queried automatically.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {\\n // query support of both ERC165 as per the spec and support of _interfaceId\\n return supportsERC165(account) && _supportsERC165Interface(account, interfaceId);\\n }\\n\\n /**\\n * @dev Returns a boolean array where each value corresponds to the\\n * interfaces passed in and whether they're supported or not. This allows\\n * you to batch check interfaces for a contract where your expectation\\n * is that some interfaces may not be supported.\\n *\\n * See {IERC165-supportsInterface}.\\n *\\n * _Available since v3.4._\\n */\\n function getSupportedInterfaces(address account, bytes4[] memory interfaceIds)\\n internal\\n view\\n returns (bool[] memory)\\n {\\n // an array of booleans corresponding to interfaceIds and whether they're supported or not\\n bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);\\n\\n // query support of ERC165 itself\\n if (supportsERC165(account)) {\\n // query support of each interface in interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n interfaceIdsSupported[i] = _supportsERC165Interface(account, interfaceIds[i]);\\n }\\n }\\n\\n return interfaceIdsSupported;\\n }\\n\\n /**\\n * @dev Returns true if `account` supports all the interfaces defined in\\n * `interfaceIds`. Support for {IERC165} itself is queried automatically.\\n *\\n * Batch-querying can lead to gas savings by skipping repeated checks for\\n * {IERC165} support.\\n *\\n * See {IERC165-supportsInterface}.\\n */\\n function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {\\n // query support of ERC165 itself\\n if (!supportsERC165(account)) {\\n return false;\\n }\\n\\n // query support of each interface in _interfaceIds\\n for (uint256 i = 0; i < interfaceIds.length; i++) {\\n if (!_supportsERC165Interface(account, interfaceIds[i])) {\\n return false;\\n }\\n }\\n\\n // all interfaces supported\\n return true;\\n }\\n\\n /**\\n * @notice Query if a contract implements an interface, does not check ERC165 support\\n * @param account The address of the contract to query for support of an interface\\n * @param interfaceId The interface identifier, as specified in ERC-165\\n * @return true if the contract at account indicates support of the interface with\\n * identifier interfaceId, false otherwise\\n * @dev Assumes that account contains a contract that supports ERC165, otherwise\\n * the behavior of this method is undefined. This precondition can be checked\\n * with {supportsERC165}.\\n * Interface identification is specified in ERC-165.\\n */\\n function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) {\\n bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);\\n (bool success, bytes memory result) = account.staticcall{gas: 30000}(encodedParams);\\n if (result.length < 32) return false;\\n return success && abi.decode(result, (bool));\\n }\\n}\\n\",\"keccak256\":\"0xf7291d7213336b00ee7edbf7cd5034778dd7b0bda2a7489e664f1e5cacc6c24e\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"@paulrberg/contracts/math/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\nimport \\\"prb-math/contracts/PRBMath.sol\\\";\\n\",\"keccak256\":\"0x42821345981bc0434a90ba2268a2f5278dfe9e38166981d72fc7f3b776a29495\",\"license\":\"Unlicense\"},\"contracts/JBETHPaymentTerminal3_1.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport '@openzeppelin/contracts/utils/Address.sol';\\nimport './abstract/JBPayoutRedemptionPaymentTerminal3_1.sol';\\nimport './libraries/JBSplitsGroups.sol';\\n\\n/**\\n @notice\\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\\n\\n @dev\\n Inherits from -\\n JBPayoutRedemptionPaymentTerminal3_1: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\\n*/\\ncontract JBETHPaymentTerminal3_1 is JBPayoutRedemptionPaymentTerminal3_1 {\\n //*********************************************************************//\\n // -------------------------- internal views ------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Checks the balance of tokens in this contract.\\n\\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\\n */\\n function _balance() internal view override returns (uint256) {\\n return address(this).balance;\\n }\\n\\n //*********************************************************************//\\n // -------------------------- constructor ---------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @param _baseWeightCurrency The currency to base token issuance on.\\n @param _operatorStore A contract storing operator assignments.\\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\\n @param _directory A contract storing directories of terminals and controllers for each project.\\n @param _splitsStore A contract that stores splits for each project.\\n @param _prices A contract that exposes price feeds.\\n @param _store A contract that stores the terminal's data.\\n @param _owner The address that will own this contract.\\n */\\n constructor(\\n uint256 _baseWeightCurrency,\\n IJBOperatorStore _operatorStore,\\n IJBProjects _projects,\\n IJBDirectory _directory,\\n IJBSplitsStore _splitsStore,\\n IJBPrices _prices,\\n IJBSingleTokenPaymentTerminalStore _store,\\n address _owner\\n )\\n JBPayoutRedemptionPaymentTerminal3_1(\\n JBTokens.GAS_TOKEN,\\n 18, // 18 decimals.\\n JBCurrencies.GAS_CURRENCY,\\n _baseWeightCurrency,\\n JBSplitsGroups.ETH_PAYOUT,\\n _operatorStore,\\n _projects,\\n _directory,\\n _splitsStore,\\n _prices,\\n _store,\\n _owner\\n )\\n // solhint-disable-next-line no-empty-blocks\\n {\\n\\n }\\n\\n //*********************************************************************//\\n // ---------------------- internal transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Transfers tokens.\\n\\n @param _from The address from which the transfer should originate.\\n @param _to The address to which the transfer should go.\\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\\n */\\n function _transferFrom(\\n address _from,\\n address payable _to,\\n uint256 _amount\\n ) internal override {\\n _from; // Prevents unused var compiler and natspec complaints.\\n\\n Address.sendValue(_to, _amount);\\n }\\n}\\n\",\"keccak256\":\"0x51cd7cb442d31c0cede341af67b5ed069d467a72cb812dad5c0763f51960bbe5\",\"license\":\"MIT\"},\"contracts/abstract/JBOperatable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport './../interfaces/IJBOperatable.sol';\\n\\n/** \\n @notice\\n Modifiers to allow access to functions based on the message sender's operator status.\\n\\n @dev\\n Adheres to -\\n IJBOperatable: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n*/\\nabstract contract JBOperatable is IJBOperatable {\\n //*********************************************************************//\\n // --------------------------- custom errors -------------------------- //\\n //*********************************************************************//\\n error UNAUTHORIZED();\\n\\n //*********************************************************************//\\n // ---------------------------- modifiers ---------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Only allows the speficied account or an operator of the account to proceed. \\n\\n @param _account The account to check for.\\n @param _domain The domain namespace to look for an operator within. \\n @param _permissionIndex The index of the permission to check for. \\n */\\n modifier requirePermission(\\n address _account,\\n uint256 _domain,\\n uint256 _permissionIndex\\n ) {\\n _requirePermission(_account, _domain, _permissionIndex);\\n _;\\n }\\n\\n /** \\n @notice\\n Only allows the speficied account, an operator of the account to proceed, or a truthy override flag. \\n\\n @param _account The account to check for.\\n @param _domain The domain namespace to look for an operator within. \\n @param _permissionIndex The index of the permission to check for. \\n @param _override A condition to force allowance for.\\n */\\n modifier requirePermissionAllowingOverride(\\n address _account,\\n uint256 _domain,\\n uint256 _permissionIndex,\\n bool _override\\n ) {\\n _requirePermissionAllowingOverride(_account, _domain, _permissionIndex, _override);\\n _;\\n }\\n\\n //*********************************************************************//\\n // ---------------- public immutable stored properties --------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n A contract storing operator assignments.\\n */\\n IJBOperatorStore public immutable override operatorStore;\\n\\n //*********************************************************************//\\n // -------------------------- constructor ---------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @param _operatorStore A contract storing operator assignments.\\n */\\n constructor(IJBOperatorStore _operatorStore) {\\n operatorStore = _operatorStore;\\n }\\n\\n //*********************************************************************//\\n // -------------------------- internal views ------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Require the message sender is either the account or has the specified permission.\\n\\n @param _account The account to allow.\\n @param _domain The domain namespace within which the permission index will be checked.\\n @param _permissionIndex The permission index that an operator must have within the specified domain to be allowed.\\n */\\n function _requirePermission(\\n address _account,\\n uint256 _domain,\\n uint256 _permissionIndex\\n ) internal view {\\n if (\\n msg.sender != _account &&\\n !operatorStore.hasPermission(msg.sender, _account, _domain, _permissionIndex) &&\\n !operatorStore.hasPermission(msg.sender, _account, 0, _permissionIndex)\\n ) revert UNAUTHORIZED();\\n }\\n\\n /** \\n @notice\\n Require the message sender is either the account, has the specified permission, or the override condition is true.\\n\\n @param _account The account to allow.\\n @param _domain The domain namespace within which the permission index will be checked.\\n @param _domain The permission index that an operator must have within the specified domain to be allowed.\\n @param _override The override condition to allow.\\n */\\n function _requirePermissionAllowingOverride(\\n address _account,\\n uint256 _domain,\\n uint256 _permissionIndex,\\n bool _override\\n ) internal view {\\n if (\\n !_override &&\\n msg.sender != _account &&\\n !operatorStore.hasPermission(msg.sender, _account, _domain, _permissionIndex) &&\\n !operatorStore.hasPermission(msg.sender, _account, 0, _permissionIndex)\\n ) revert UNAUTHORIZED();\\n }\\n}\\n\",\"keccak256\":\"0x9e62cac5c464eb973f881cf6c373b95aab31d2ddbeb048ee7ad82b5c9ab28add\",\"license\":\"MIT\"},\"contracts/abstract/JBPayoutRedemptionPaymentTerminal3_1.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport '@openzeppelin/contracts/access/Ownable.sol';\\nimport '@openzeppelin/contracts/utils/introspection/ERC165Checker.sol';\\nimport '@paulrberg/contracts/math/PRBMath.sol';\\nimport './../interfaces/IJBController.sol';\\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal3_1.sol';\\nimport './../libraries/JBConstants.sol';\\nimport './../libraries/JBCurrencies.sol';\\nimport './../libraries/JBFixedPointNumber.sol';\\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\\nimport './../libraries/JBOperations.sol';\\nimport './../libraries/JBTokens.sol';\\nimport './../structs/JBPayDelegateAllocation.sol';\\nimport './../structs/JBTokenAmount.sol';\\nimport './JBOperatable.sol';\\nimport './JBSingleTokenPaymentTerminal.sol';\\n\\n/**\\n @notice\\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\\n\\n @dev\\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\\n\\n @dev\\n Adheres to -\\n IJBPayoutRedemptionPaymentTerminal3_1: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n\\n @dev\\n Inherits from -\\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\\n*/\\nabstract contract JBPayoutRedemptionPaymentTerminal3_1 is\\n JBSingleTokenPaymentTerminal,\\n JBOperatable,\\n Ownable,\\n IJBPayoutRedemptionPaymentTerminal3_1\\n{\\n // A library that parses the packed funding cycle metadata into a friendlier format.\\n using JBFundingCycleMetadataResolver for JBFundingCycle;\\n\\n //*********************************************************************//\\n // --------------------------- custom errors ------------------------- //\\n //*********************************************************************//\\n error FEE_TOO_HIGH();\\n error INADEQUATE_DISTRIBUTION_AMOUNT();\\n error INADEQUATE_RECLAIM_AMOUNT();\\n error INADEQUATE_TOKEN_COUNT();\\n error NO_MSG_VALUE_ALLOWED();\\n error PAY_TO_ZERO_ADDRESS();\\n error PROJECT_TERMINAL_MISMATCH();\\n error REDEEM_TO_ZERO_ADDRESS();\\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\\n error TERMINAL_TOKENS_INCOMPATIBLE();\\n\\n //*********************************************************************//\\n // ---------------------------- modifiers ---------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice \\n A modifier that verifies this terminal is a terminal of provided project ID.\\n */\\n modifier isTerminalOf(uint256 _projectId) {\\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\\n _;\\n }\\n\\n //*********************************************************************//\\n // --------------------- internal stored constants ------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Maximum fee that can be set for a funding cycle configuration.\\n\\n @dev\\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\\n */\\n uint256 internal constant _FEE_CAP = 50_000_000;\\n\\n /**\\n @notice\\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\\n */\\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\\n\\n //*********************************************************************//\\n // --------------------- internal stored properties ------------------ //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Fees that are being held to be processed later.\\n\\n _projectId The ID of the project for which fees are being held.\\n */\\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\\n\\n //*********************************************************************//\\n // ---------------- public immutable stored properties --------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Mints ERC-721's that represent project ownership and transfers.\\n */\\n IJBProjects public immutable override projects;\\n\\n /**\\n @notice\\n The directory of terminals and controllers for projects.\\n */\\n IJBDirectory public immutable override directory;\\n\\n /**\\n @notice\\n The contract that stores splits for each project.\\n */\\n IJBSplitsStore public immutable override splitsStore;\\n\\n /**\\n @notice\\n The contract that exposes price feeds.\\n */\\n IJBPrices public immutable override prices;\\n\\n /**\\n @notice\\n The contract that stores and manages the terminal's data.\\n */\\n IJBSingleTokenPaymentTerminalStore public immutable override store;\\n\\n /**\\n @notice\\n The currency to base token issuance on.\\n\\n @dev\\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\\n */\\n uint256 public immutable override baseWeightCurrency;\\n\\n /**\\n @notice\\n The group that payout splits coming from this terminal are identified by.\\n */\\n uint256 public immutable override payoutSplitsGroup;\\n\\n //*********************************************************************//\\n // --------------------- public stored properties -------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The platform fee percent.\\n\\n @dev\\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\\n */\\n uint256 public override fee = 25_000_000; // 2.5%\\n\\n /**\\n @notice\\n The data source that returns a discount to apply to a project's fee.\\n */\\n IJBFeeGauge public override feeGauge;\\n\\n /**\\n @notice\\n Addresses that can be paid towards from this terminal without incurring a fee.\\n\\n @dev\\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\\n\\n _address The address that can be paid toward.\\n */\\n mapping(address => bool) public override isFeelessAddress;\\n\\n //*********************************************************************//\\n // ------------------------- external views -------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\\n\\n @dev\\n The current overflow is represented as a fixed point number with 18 decimals.\\n\\n @param _projectId The ID of the project to get overflow for.\\n\\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\\n */\\n function currentEthOverflowOf(uint256 _projectId)\\n external\\n view\\n virtual\\n override\\n returns (uint256)\\n {\\n // Get this terminal's current overflow.\\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\\n\\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\\n uint256 _adjustedOverflow = (decimals == 18)\\n ? _overflow\\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\\n\\n // Return the amount converted to ETH.\\n return\\n (currency == JBCurrencies.GAS_CURRENCY)\\n ? _adjustedOverflow\\n : PRBMath.mulDiv(\\n _adjustedOverflow,\\n 10**decimals,\\n prices.priceFor(currency, JBCurrencies.GAS_CURRENCY, decimals)\\n );\\n }\\n\\n /**\\n @notice\\n The fees that are currently being held to be processed later for each project.\\n\\n @param _projectId The ID of the project for which fees are being held.\\n\\n @return An array of fees that are being held.\\n */\\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\\n return _heldFeesOf[_projectId];\\n }\\n\\n //*********************************************************************//\\n // -------------------------- public views --------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Indicates if this contract adheres to the specified interface.\\n\\n @dev \\n See {IERC165-supportsInterface}.\\n\\n @param _interfaceId The ID of the interface to check for adherance to.\\n */\\n function supportsInterface(bytes4 _interfaceId)\\n public\\n view\\n virtual\\n override(JBSingleTokenPaymentTerminal, IERC165)\\n returns (bool)\\n {\\n return\\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal3_1).interfaceId ||\\n _interfaceId == type(IJBPayoutTerminal3_1).interfaceId ||\\n _interfaceId == type(IJBAllowanceTerminal3_1).interfaceId ||\\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\\n _interfaceId == type(IJBOperatable).interfaceId ||\\n super.supportsInterface(_interfaceId);\\n }\\n\\n //*********************************************************************//\\n // -------------------------- internal views ------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Checks the balance of tokens in this contract.\\n\\n @return The contract's balance.\\n */\\n function _balance() internal view virtual returns (uint256);\\n\\n //*********************************************************************//\\n // -------------------------- constructor ---------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @param _token The token that this terminal manages.\\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\\n @param _currency The currency that this terminal's token adheres to for price feeds.\\n @param _baseWeightCurrency The currency to base token issuance on.\\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\\n @param _operatorStore A contract storing operator assignments.\\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\\n @param _directory A contract storing directories of terminals and controllers for each project.\\n @param _splitsStore A contract that stores splits for each project.\\n @param _prices A contract that exposes price feeds.\\n @param _store A contract that stores the terminal's data.\\n @param _owner The address that will own this contract.\\n */\\n constructor(\\n // payable constructor save the gas used to check msg.value==0\\n address _token,\\n uint256 _decimals,\\n uint256 _currency,\\n uint256 _baseWeightCurrency,\\n uint256 _payoutSplitsGroup,\\n IJBOperatorStore _operatorStore,\\n IJBProjects _projects,\\n IJBDirectory _directory,\\n IJBSplitsStore _splitsStore,\\n IJBPrices _prices,\\n IJBSingleTokenPaymentTerminalStore _store,\\n address _owner\\n )\\n payable\\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\\n JBOperatable(_operatorStore)\\n {\\n baseWeightCurrency = _baseWeightCurrency;\\n payoutSplitsGroup = _payoutSplitsGroup;\\n projects = _projects;\\n directory = _directory;\\n splitsStore = _splitsStore;\\n prices = _prices;\\n store = _store;\\n\\n transferOwnership(_owner);\\n }\\n\\n //*********************************************************************//\\n // ---------------------- external transactions ---------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Contribute tokens to a project.\\n\\n @param _projectId The ID of the project being paid.\\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\\n\\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\\n */\\n function pay(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n // ETH shouldn't be sent if this terminal's token isn't ETH.\\n if (token != JBTokens.GAS_TOKEN) {\\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\\n\\n // Get a reference to the balance before receiving tokens.\\n uint256 _balanceBefore = _balance();\\n\\n // Transfer tokens to this terminal from the msg sender.\\n _transferFrom(msg.sender, payable(address(this)), _amount);\\n\\n // The amount should reflect the change in balance.\\n _amount = _balance() - _balanceBefore;\\n }\\n // If this terminal's token is ETH, override _amount with msg.value.\\n else _amount = msg.value;\\n\\n return\\n _pay(\\n _amount,\\n msg.sender,\\n _projectId,\\n _beneficiary,\\n _minReturnedTokens,\\n _preferClaimedTokens,\\n _memo,\\n _metadata\\n );\\n }\\n\\n /**\\n @notice\\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\\n\\n @dev\\n Only a token holder or a designated operator can redeem its tokens.\\n\\n @param _holder The account to redeem tokens for.\\n @param _projectId The ID of the project to which the tokens being redeemed belong.\\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\\n @param _beneficiary The address to send the terminal tokens to.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\\n\\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\\n */\\n function redeemTokensOf(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n address _token,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string memory _memo,\\n bytes memory _metadata\\n )\\n external\\n virtual\\n override\\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\\n returns (uint256 reclaimAmount)\\n {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n return\\n _redeemTokensOf(\\n _holder,\\n _projectId,\\n _tokenCount,\\n _minReturnedTokens,\\n _beneficiary,\\n _memo,\\n _metadata\\n );\\n }\\n\\n /**\\n @notice\\n Distributes payouts for a project with the distribution limit of its current funding cycle.\\n\\n @dev\\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\\n\\n @dev\\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\\n\\n @dev\\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\\n\\n @param _projectId The ID of the project having its payouts distributed.\\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\\n @param _metadata Bytes to send along to the emitted event, if provided.\\n\\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\\n */\\n function distributePayoutsOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n address _token,\\n uint256 _minReturnedTokens,\\n bytes calldata _metadata\\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _metadata);\\n }\\n\\n /**\\n @notice\\n Allows a project to send funds from its overflow up to the preconfigured allowance.\\n\\n @dev\\n Only a project's owner or a designated operator can use its allowance.\\n\\n @dev\\n Incurs the protocol fee.\\n\\n @param _projectId The ID of the project to use the allowance of.\\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\\n @param _beneficiary The address to send the funds to.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Bytes to send along to the emitted event, if provided.\\n\\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\\n */\\n function useAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n address _token,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string memory _memo,\\n bytes calldata _metadata\\n )\\n external\\n virtual\\n override\\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\\n returns (uint256 netDistributedAmount)\\n {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n return\\n _useAllowanceOf(\\n _projectId,\\n _amount,\\n _currency,\\n _minReturnedTokens,\\n _beneficiary,\\n _memo,\\n _metadata\\n );\\n }\\n\\n /**\\n @notice\\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\\n\\n @dev\\n Only a project's owner or a designated operator can migrate it.\\n\\n @param _projectId The ID of the project being migrated.\\n @param _to The terminal contract that will gain the project's funds.\\n\\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\\n */\\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\\n external\\n virtual\\n override\\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\\n returns (uint256 balance)\\n {\\n // The terminal being migrated to must accept the same token as this terminal.\\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\\n\\n // Record the migration in the store.\\n balance = store.recordMigration(_projectId);\\n\\n // Transfer the balance if needed.\\n if (balance > 0) {\\n // Trigger any inherited pre-transfer logic.\\n _beforeTransferTo(address(_to), balance);\\n\\n // If this terminal's token is ETH, send it in msg.value.\\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? balance : 0;\\n\\n // Withdraw the balance to transfer to the new terminal;\\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\\n }\\n\\n emit Migrate(_projectId, _to, balance, msg.sender);\\n }\\n\\n /**\\n @notice\\n Receives funds belonging to the specified project.\\n\\n @param _projectId The ID of the project to which the funds received belong.\\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Extra data to pass along to the emitted event.\\n */\\n function addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable virtual override isTerminalOf(_projectId) {\\n // Do not refund held fees by default.\\n addToBalanceOf(_projectId, _amount, _token, false, _memo, _metadata);\\n }\\n\\n /**\\n @notice\\n Process any fees that are being held for the project.\\n\\n @dev\\n Only a project owner, an operator, or the contract's owner can process held fees.\\n\\n @param _projectId The ID of the project whos held fees should be processed.\\n */\\n function processFees(uint256 _projectId)\\n external\\n virtual\\n override\\n requirePermissionAllowingOverride(\\n projects.ownerOf(_projectId),\\n _projectId,\\n JBOperations.PROCESS_FEES,\\n msg.sender == owner()\\n )\\n {\\n // Get a reference to the project's held fees.\\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\\n\\n // Delete the held fees.\\n delete _heldFeesOf[_projectId];\\n\\n // Push array length in stack\\n uint256 _heldFeeLength = _heldFees.length;\\n\\n // Process each fee.\\n for (uint256 _i; _i < _heldFeeLength; ) {\\n // Get the fee amount.\\n uint256 _amount = _feeAmount(\\n _heldFees[_i].amount,\\n _heldFees[_i].fee,\\n _heldFees[_i].feeDiscount\\n );\\n\\n // Process the fee.\\n _processFee(_amount, _heldFees[_i].beneficiary, _projectId);\\n\\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n\\n /**\\n @notice\\n Allows the fee to be updated.\\n\\n @dev\\n Only the owner of this contract can change the fee.\\n\\n @param _fee The new fee, out of MAX_FEE.\\n */\\n function setFee(uint256 _fee) external virtual override onlyOwner {\\n // The provided fee must be within the max.\\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\\n\\n // Store the new fee.\\n fee = _fee;\\n\\n emit SetFee(_fee, msg.sender);\\n }\\n\\n /**\\n @notice\\n Allows the fee gauge to be updated.\\n\\n @dev\\n Only the owner of this contract can change the fee gauge.\\n\\n @param _feeGauge The new fee gauge.\\n */\\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\\n // Store the new fee gauge.\\n feeGauge = _feeGauge;\\n\\n emit SetFeeGauge(_feeGauge, msg.sender);\\n }\\n\\n /**\\n @notice\\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\\n\\n @dev\\n Only the owner of this contract can set addresses as feeless.\\n\\n @param _address The address that can be paid towards while still bypassing fees.\\n @param _flag A flag indicating whether the terminal should be feeless or not.\\n */\\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\\n // Set the flag value.\\n isFeelessAddress[_address] = _flag;\\n\\n emit SetFeelessAddress(_address, _flag, msg.sender);\\n }\\n\\n //*********************************************************************//\\n // ----------------------- public transactions ----------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Receives funds belonging to the specified project.\\n\\n @param _projectId The ID of the project to which the funds received belong.\\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Extra data to pass along to the emitted event.\\n */\\n function addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n bool _shouldRefundHeldFees,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) public payable virtual override isTerminalOf(_projectId) {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\\n if (token != JBTokens.GAS_TOKEN) {\\n // Amount must be greater than 0.\\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\\n\\n // Get a reference to the balance before receiving tokens.\\n uint256 _balanceBefore = _balance();\\n\\n // Transfer tokens to this terminal from the msg sender.\\n _transferFrom(msg.sender, payable(address(this)), _amount);\\n\\n // The amount should reflect the change in balance.\\n _amount = _balance() - _balanceBefore;\\n }\\n // If the terminal's token is ETH, override `_amount` with msg.value.\\n else _amount = msg.value;\\n\\n // Add to balance.\\n _addToBalanceOf(_projectId, _amount, _shouldRefundHeldFees, _memo, _metadata);\\n }\\n\\n //*********************************************************************//\\n // ---------------------- internal transactions ---------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n Transfers tokens.\\n\\n @param _from The address from which the transfer should originate.\\n @param _to The address to which the transfer should go.\\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\\n */\\n function _transferFrom(\\n address _from,\\n address payable _to,\\n uint256 _amount\\n ) internal virtual {\\n _from; // Prevents unused var compiler and natspec complaints.\\n _to; // Prevents unused var compiler and natspec complaints.\\n _amount; // Prevents unused var compiler and natspec complaints.\\n }\\n\\n /** \\n @notice\\n Logic to be triggered before transferring tokens from this terminal.\\n\\n @param _to The address to which the transfer is going.\\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\\n */\\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\\n _to; // Prevents unused var compiler and natspec complaints.\\n _amount; // Prevents unused var compiler and natspec complaints.\\n }\\n\\n /** \\n @notice\\n Logic to be triggered if a transfer should be undone\\n\\n @param _to The address to which the transfer went.\\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\\n */\\n function _cancelTransferTo(address _to, uint256 _amount) internal virtual {\\n _to; // Prevents unused var compiler and natspec complaints.\\n _amount; // Prevents unused var compiler and natspec complaints.\\n }\\n\\n /**\\n @notice\\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\\n\\n @dev\\n Only a token holder or a designated operator can redeem its tokens.\\n\\n @param _holder The account to redeem tokens for.\\n @param _projectId The ID of the project to which the tokens being redeemed belong.\\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\\n @param _beneficiary The address to send the terminal tokens to.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\\n\\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\\n */\\n function _redeemTokensOf(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string memory _memo,\\n bytes memory _metadata\\n ) internal returns (uint256 reclaimAmount) {\\n // Can't send reclaimed funds to the zero address.\\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\\n\\n // Define variables that will be needed outside the scoped section below.\\n // Keep a reference to the funding cycle during which the redemption is being made.\\n JBFundingCycle memory _fundingCycle;\\n\\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\\n {\\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\\n\\n // Record the redemption.\\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\\n _holder,\\n _projectId,\\n _tokenCount,\\n _memo,\\n _metadata\\n );\\n\\n // The amount being reclaimed must be at least as much as was expected.\\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\\n\\n // Burn the project tokens.\\n if (_tokenCount > 0)\\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\\n _holder,\\n _projectId,\\n _tokenCount,\\n '',\\n false\\n );\\n\\n // If delegate allocations were specified by the data source, fulfill them.\\n if (_delegateAllocations.length != 0) {\\n // Keep a reference to the token amount being forwarded to the delegate.\\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\\n\\n JBDidRedeemData memory _data = JBDidRedeemData(\\n _holder,\\n _projectId,\\n _fundingCycle.configuration,\\n _tokenCount,\\n JBTokenAmount(token, reclaimAmount, decimals, currency),\\n _forwardedAmount,\\n _beneficiary,\\n _memo,\\n _metadata\\n );\\n\\n uint256 _numDelegates = _delegateAllocations.length;\\n\\n for (uint256 _i; _i < _numDelegates; ) {\\n // Get a reference to the delegate being iterated on.\\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\\n\\n // Trigger any inherited pre-transfer logic.\\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\\n\\n // Keep track of the msg.value to use in the delegate call\\n uint256 _payableValue;\\n\\n // If this terminal's token is ETH, send it in msg.value.\\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\\n\\n // Pass the correct token forwardedAmount to the delegate\\n _data.forwardedAmount.value = _delegateAllocation.amount;\\n\\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\\n\\n emit DelegateDidRedeem(\\n _delegateAllocation.delegate,\\n _data,\\n _delegateAllocation.amount,\\n msg.sender\\n );\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n }\\n\\n // Send the reclaimed funds to the beneficiary.\\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\\n\\n emit RedeemTokens(\\n _fundingCycle.configuration,\\n _fundingCycle.number,\\n _projectId,\\n _holder,\\n _beneficiary,\\n _tokenCount,\\n reclaimAmount,\\n _memo,\\n _metadata,\\n msg.sender\\n );\\n }\\n\\n /**\\n @notice\\n Distributes payouts for a project with the distribution limit of its current funding cycle.\\n\\n @dev\\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\\n\\n @dev\\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\\n\\n @dev\\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\\n\\n @param _projectId The ID of the project having its payouts distributed.\\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\\n @param _metadata Bytes to send along to the emitted event, if provided.\\n\\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\\n */\\n function _distributePayoutsOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n uint256 _minReturnedTokens,\\n bytes calldata _metadata\\n ) internal returns (uint256 netLeftoverDistributionAmount) {\\n // Record the distribution.\\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\\n _projectId,\\n _amount,\\n _currency\\n );\\n\\n // The amount being distributed must be at least as much as was expected.\\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\\n\\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\\n // and receive any extra distributable funds not allocated to payout splits.\\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\\n\\n // Define variables that will be needed outside the scoped section below.\\n // Keep a reference to the fee amount that was paid.\\n uint256 _fee;\\n\\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\\n {\\n // Get the amount of discount that should be applied to any fees taken.\\n // If the fee is zero, set the discount to 100% for convenience.\\n uint256 _feeDiscount = fee == 0\\n ? JBConstants.MAX_FEE_DISCOUNT\\n : _currentFeeDiscount(_projectId);\\n\\n // The amount distributed that is eligible for incurring fees.\\n uint256 _feeEligibleDistributionAmount;\\n\\n // The amount leftover after distributing to the splits.\\n uint256 _leftoverDistributionAmount;\\n\\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\\n _projectId,\\n _fundingCycle.configuration,\\n payoutSplitsGroup,\\n _distributedAmount,\\n _feeDiscount\\n );\\n\\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\\n unchecked {\\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\\n }\\n }\\n\\n // Take the fee.\\n _fee = _feeEligibleDistributionAmount != 0\\n ? _takeFeeFrom(\\n _projectId,\\n _fundingCycle,\\n _feeEligibleDistributionAmount,\\n _projectOwner,\\n _feeDiscount\\n )\\n : 0;\\n\\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\\n if (_leftoverDistributionAmount != 0) {\\n // Subtract the fee from the net leftover amount.\\n netLeftoverDistributionAmount =\\n _leftoverDistributionAmount -\\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\\n\\n // Transfer the amount to the project owner.\\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\\n }\\n }\\n\\n emit DistributePayouts(\\n _fundingCycle.configuration,\\n _fundingCycle.number,\\n _projectId,\\n _projectOwner,\\n _amount,\\n _distributedAmount,\\n _fee,\\n netLeftoverDistributionAmount,\\n _metadata,\\n msg.sender\\n );\\n }\\n\\n /**\\n @notice\\n Allows a project to send funds from its overflow up to the preconfigured allowance.\\n\\n @dev\\n Only a project's owner or a designated operator can use its allowance.\\n\\n @dev\\n Incurs the protocol fee.\\n\\n @param _projectId The ID of the project to use the allowance of.\\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\\n @param _beneficiary The address to send the funds to.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Bytes to send along to the emitted event, if provided.\\n\\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\\n */\\n function _useAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string memory _memo,\\n bytes calldata _metadata\\n ) internal returns (uint256 netDistributedAmount) {\\n // Record the use of the allowance.\\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\\n _projectId,\\n _amount,\\n _currency\\n );\\n\\n // The amount being withdrawn must be at least as much as was expected.\\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\\n\\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\\n {\\n // Keep a reference to the fee amount that was paid.\\n uint256 _fee;\\n\\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\\n address _projectOwner = projects.ownerOf(_projectId);\\n\\n // Get the amount of discount that should be applied to any fees taken.\\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\\n ? JBConstants.MAX_FEE_DISCOUNT\\n : _currentFeeDiscount(_projectId);\\n\\n // Take a fee from the `_distributedAmount`, if needed.\\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\\n ? 0\\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\\n\\n unchecked {\\n // The net amount is the withdrawn amount without the fee.\\n netDistributedAmount = _distributedAmount - _fee;\\n }\\n\\n // Transfer any remaining balance to the beneficiary.\\n if (netDistributedAmount > 0)\\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\\n }\\n\\n emit UseAllowance(\\n _fundingCycle.configuration,\\n _fundingCycle.number,\\n _projectId,\\n _beneficiary,\\n _amount,\\n _distributedAmount,\\n netDistributedAmount,\\n _memo,\\n _metadata,\\n msg.sender\\n );\\n }\\n\\n /**\\n @notice\\n Pays out splits for a project's funding cycle configuration.\\n\\n @param _projectId The ID of the project for which payout splits are being distributed.\\n @param _domain The domain of the splits to distribute the payout between.\\n @param _group The group of the splits to distribute the payout between.\\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\\n\\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\\n */\\n function _distributeToPayoutSplitsOf(\\n uint256 _projectId,\\n uint256 _domain,\\n uint256 _group,\\n uint256 _amount,\\n uint256 _feeDiscount\\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\\n // Set the leftover amount to the initial amount.\\n leftoverAmount = _amount;\\n // The total percentage available to split\\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\\n\\n // Get a reference to the project's payout splits.\\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\\n\\n // Transfer between all splits.\\n for (uint256 _i; _i < _splits.length; ) {\\n // Get a reference to the split being iterated on.\\n JBSplit memory _split = _splits[_i];\\n\\n // The amount to send towards the split.\\n uint256 _payoutAmount = _split.percent == leftoverPercentage\\n ? leftoverAmount\\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\\n\\n // Decrement the leftover percentage.\\n leftoverPercentage -= _split.percent;\\n\\n // The payout amount substracting any applicable incurred fees.\\n uint256 _netPayoutAmount = _distributeToPayoutSplit(\\n _split,\\n _projectId,\\n _group,\\n _payoutAmount,\\n _feeDiscount\\n );\\n\\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\\n if (_netPayoutAmount != 0 && _netPayoutAmount != _payoutAmount)\\n feeEligibleDistributionAmount += _payoutAmount;\\n\\n if (_payoutAmount > 0) {\\n // Subtract from the amount to be sent to the beneficiary.\\n unchecked {\\n leftoverAmount = leftoverAmount - _payoutAmount;\\n }\\n }\\n\\n emit DistributeToPayoutSplit(\\n _projectId,\\n _domain,\\n _group,\\n _split,\\n _payoutAmount,\\n _netPayoutAmount,\\n msg.sender\\n );\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n\\n /**\\n @notice\\n Pays out a split for a project's funding cycle configuration.\\n \\n @param _split The split to distribute payouts to.\\n @param _amount The total amount being distributed to the split, as a fixed point number with the same number of decimals as this terminal.\\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\\n\\n @return netPayoutAmount The amount sent to the split after subtracting fees.\\n */\\n function _distributeToPayoutSplit(\\n JBSplit memory _split,\\n uint256 _projectId,\\n uint256 _group,\\n uint256 _amount,\\n uint256 _feeDiscount\\n ) internal returns (uint256 netPayoutAmount) {\\n // If there's an allocator set, transfer to its `allocate` function.\\n if (_split.allocator != IJBSplitAllocator(address(0))) {\\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\\n if (\\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_split.allocator)]\\n )\\n netPayoutAmount = _amount;\\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\\n else {\\n unchecked {\\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\\n }\\n }\\n\\n // Trigger any inherited pre-transfer logic.\\n _beforeTransferTo(address(_split.allocator), netPayoutAmount);\\n\\n // Create the data to send to the allocator.\\n JBSplitAllocationData memory _data = JBSplitAllocationData(\\n token,\\n netPayoutAmount,\\n decimals,\\n _projectId,\\n _group,\\n _split\\n );\\n\\n // Trigger the allocator's `allocate` function.\\n uint256 _error;\\n bytes memory _reason;\\n\\n if (\\n ERC165Checker.supportsInterface(\\n address(_split.allocator),\\n type(IJBSplitAllocator).interfaceId\\n )\\n )\\n // If this terminal's token is ETH, send it in msg.value.\\n try _split.allocator.allocate{value: token == JBTokens.GAS_TOKEN ? netPayoutAmount : 0}(_data) {\\n\\n } catch (bytes memory reason) {\\n _reason = reason;\\n _error = 1;\\n }\\n else _error = 2;\\n\\n\\n if (_error != 0) {\\n // Trigger any inhereted post-transfer cancelation logic.\\n _cancelTransferTo(address(_split.allocator), netPayoutAmount);\\n\\n // Set the net payout amount to 0 to signal the reversion.\\n netPayoutAmount = 0;\\n\\n // Add undistributed amount back to project's balance.\\n store.recordAddedBalanceFor(_projectId, _amount);\\n\\n emit PayoutReverted(_projectId, _split, _amount, _error == 1 ? _reason : abi.encode(\\\"IERC165 fail\\\"), msg.sender);\\n }\\n\\n // Otherwise, if a project is specified, make a payment to it.\\n } else if (_split.projectId != 0) {\\n // Get a reference to the Juicebox terminal being used.\\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\\n\\n // The project must have a terminal to send funds to.\\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\\n\\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\\n if (\\n _terminal == this ||\\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\\n isFeelessAddress[address(_terminal)]\\n )\\n netPayoutAmount = _amount;\\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\\n else {\\n unchecked {\\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\\n }\\n }\\n\\n // Trigger any inherited pre-transfer logic.\\n _beforeTransferTo(address(_terminal), netPayoutAmount);\\n\\n // Send the projectId in the metadata.\\n bytes memory _projectMetadata = new bytes(32);\\n _projectMetadata = bytes(abi.encodePacked(_projectId));\\n\\n // Add to balance if prefered.\\n if (_split.preferAddToBalance)\\n try\\n _terminal.addToBalanceOf{value: token == JBTokens.GAS_TOKEN ? netPayoutAmount : 0}(\\n _split.projectId,\\n netPayoutAmount,\\n token,\\n '',\\n _projectMetadata\\n )\\n {} catch (bytes memory reason) {\\n // Trigger any inhereted post-transfer cancelation logic.\\n _cancelTransferTo(address(_terminal), netPayoutAmount);\\n\\n // Set the net payout amount to 0 to signal the reversion.\\n netPayoutAmount = 0;\\n\\n // Add undistributed amount back to project's balance.\\n store.recordAddedBalanceFor(_projectId, _amount);\\n\\n emit PayoutReverted(_projectId, _split, _amount, reason, msg.sender);\\n }\\n else\\n try\\n _terminal.pay{value: token == JBTokens.GAS_TOKEN ? netPayoutAmount : 0}(\\n _split.projectId,\\n netPayoutAmount,\\n token,\\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\\n 0,\\n _split.preferClaimed,\\n '',\\n _projectMetadata\\n )\\n {} catch (bytes memory reason) {\\n // Trigger any inhereted post-transfer cancelation logic.\\n _cancelTransferTo(address(_terminal), netPayoutAmount);\\n\\n // Set the net payout amount to 0 to signal the reversion.\\n netPayoutAmount = 0;\\n\\n // Add undistributed amount back to project's balance.\\n store.recordAddedBalanceFor(_projectId, _amount);\\n\\n emit PayoutReverted(_projectId, _split, _amount, reason, msg.sender);\\n }\\n } else {\\n // Keep a reference to the beneficiary.\\n address payable _beneficiary = _split.beneficiary != address(0)\\n ? _split.beneficiary\\n : payable(msg.sender);\\n\\n // If there's a full discount, this distribution is not eligible for a fee.\\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\\n netPayoutAmount = _amount;\\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\\n else {\\n unchecked {\\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\\n }\\n }\\n\\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\\n _transferFrom(address(this), _beneficiary, netPayoutAmount);\\n }\\n }\\n\\n /**\\n @notice\\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\\n\\n @param _projectId The ID of the project having fees taken from.\\n @param _fundingCycle The funding cycle during which the fee is being taken.\\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\\n @param _beneficiary The address to mint the platforms tokens for.\\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\\n\\n @return feeAmount The amount of the fee taken.\\n */\\n function _takeFeeFrom(\\n uint256 _projectId,\\n JBFundingCycle memory _fundingCycle,\\n uint256 _amount,\\n address _beneficiary,\\n uint256 _feeDiscount\\n ) internal returns (uint256 feeAmount) {\\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\\n\\n if (_fundingCycle.shouldHoldFees()) {\\n // Store the held fee.\\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\\n\\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\\n } else {\\n // Process the fee.\\n _processFee(feeAmount, _beneficiary, _projectId); // Take the fee.\\n\\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\\n }\\n }\\n\\n /**\\n @notice\\n Process a fee of the specified amount.\\n\\n @param _amount The fee amount, as a floating point number with 18 decimals.\\n @param _beneficiary The address to mint the platform's tokens for.\\n @param _from The project ID the fee is being paid from.\\n */\\n function _processFee(\\n uint256 _amount,\\n address _beneficiary,\\n uint256 _from\\n ) internal {\\n // Get the terminal for the protocol project.\\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\\n\\n // If this terminal's token is ETH, send it in msg.value.\\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _amount : 0;\\n\\n // Send the projectId in the metadata.\\n bytes memory _projectMetadata = new bytes(32);\\n _projectMetadata = bytes(abi.encodePacked(_from));\\n\\n // Trigger any inherited pre-transfer logic if funds will be transferred.\\n if (address(_terminal) != address(this)) _beforeTransferTo(address(_terminal), _amount);\\n\\n try\\n // Send the fee.\\n _terminal.pay{value: _payableValue}(\\n _FEE_BENEFICIARY_PROJECT_ID,\\n _amount,\\n token,\\n _beneficiary,\\n 0,\\n false,\\n '',\\n _projectMetadata\\n )\\n {} catch (bytes memory reason) {\\n // Trigger any inhereted post-transfer cancelation logic if the pre-transfer logic was triggered.\\n if (address(_terminal) != address(this)) _cancelTransferTo(address(_terminal), _amount);\\n\\n // Add fee amount back to project's balance.\\n store.recordAddedBalanceFor(_from, _amount);\\n\\n emit FeeReverted(_from, _FEE_BENEFICIARY_PROJECT_ID, _amount, reason, msg.sender);\\n }\\n }\\n\\n /**\\n @notice\\n Contribute tokens to a project.\\n\\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\\n @param _payer The address making the payment.\\n @param _projectId The ID of the project being paid.\\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\\n\\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\\n */\\n function _pay(\\n uint256 _amount,\\n address _payer,\\n uint256 _projectId,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string memory _memo,\\n bytes memory _metadata\\n ) internal returns (uint256 beneficiaryTokenCount) {\\n // Cant send tokens to the zero address.\\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\\n\\n // Define variables that will be needed outside the scoped section below.\\n // Keep a reference to the funding cycle during which the payment is being made.\\n JBFundingCycle memory _fundingCycle;\\n\\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\\n {\\n JBPayDelegateAllocation[] memory _delegateAllocations;\\n uint256 _tokenCount;\\n\\n // Bundle the amount info into a JBTokenAmount struct.\\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\\n\\n // Record the payment.\\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\\n _payer,\\n _bundledAmount,\\n _projectId,\\n baseWeightCurrency,\\n _beneficiary,\\n _memo,\\n _metadata\\n );\\n\\n // Mint the tokens if needed.\\n if (_tokenCount > 0)\\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\\n _projectId,\\n _tokenCount,\\n _beneficiary,\\n '',\\n _preferClaimedTokens,\\n true\\n );\\n\\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\\n\\n // If delegate allocations were specified by the data source, fulfill them.\\n if (_delegateAllocations.length != 0) {\\n // Keep a reference to the token amount being forwarded to the delegate.\\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\\n\\n JBDidPayData memory _data = JBDidPayData(\\n _payer,\\n _projectId,\\n _fundingCycle.configuration,\\n _bundledAmount,\\n _forwardedAmount,\\n beneficiaryTokenCount,\\n _beneficiary,\\n _preferClaimedTokens,\\n _memo,\\n _metadata\\n );\\n\\n // Get a reference to the number of delegates to allocate to.\\n uint256 _numDelegates = _delegateAllocations.length;\\n\\n for (uint256 _i; _i < _numDelegates; ) {\\n // Get a reference to the delegate being iterated on.\\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\\n\\n // Trigger any inherited pre-transfer logic.\\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\\n\\n // Keep track of the msg.value to use in the delegate call\\n uint256 _payableValue;\\n\\n // If this terminal's token is ETH, send it in msg.value.\\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\\n\\n // Pass the correct token forwardedAmount to the delegate\\n _data.forwardedAmount.value = _delegateAllocation.amount;\\n\\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\\n\\n emit DelegateDidPay(\\n _delegateAllocation.delegate,\\n _data,\\n _delegateAllocation.amount,\\n msg.sender\\n );\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n }\\n\\n emit Pay(\\n _fundingCycle.configuration,\\n _fundingCycle.number,\\n _projectId,\\n _payer,\\n _beneficiary,\\n _amount,\\n beneficiaryTokenCount,\\n _memo,\\n _metadata,\\n msg.sender\\n );\\n }\\n\\n /**\\n @notice\\n Receives funds belonging to the specified project.\\n\\n @param _projectId The ID of the project to which the funds received belong.\\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Extra data to pass along to the emitted event.\\n */\\n function _addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n bool _shouldRefundHeldFees,\\n string memory _memo,\\n bytes memory _metadata\\n ) internal {\\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\\n\\n // Record the added funds with any refunded fees.\\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\\n\\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\\n }\\n\\n /**\\n @notice\\n Refund fees based on the specified amount.\\n\\n @param _projectId The project for which fees are being refunded.\\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\\n\\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\\n */\\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\\n internal\\n returns (uint256 refundedFees)\\n {\\n // Get a reference to the project's held fees.\\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\\n\\n // Delete the current held fees.\\n delete _heldFeesOf[_projectId];\\n\\n // Get a reference to the leftover amount once all fees have been settled.\\n uint256 leftoverAmount = _amount;\\n\\n // Push length in stack\\n uint256 _heldFeesLength = _heldFees.length;\\n\\n // Process each fee.\\n for (uint256 _i; _i < _heldFeesLength; ) {\\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\\n else if (leftoverAmount >= _heldFees[_i].amount) {\\n unchecked {\\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\\n refundedFees += _feeAmount(\\n _heldFees[_i].amount,\\n _heldFees[_i].fee,\\n _heldFees[_i].feeDiscount\\n );\\n }\\n } else {\\n unchecked {\\n _heldFeesOf[_projectId].push(\\n JBFee(\\n _heldFees[_i].amount - leftoverAmount,\\n _heldFees[_i].fee,\\n _heldFees[_i].feeDiscount,\\n _heldFees[_i].beneficiary\\n )\\n );\\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\\n }\\n leftoverAmount = 0;\\n }\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n\\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\\n }\\n\\n /** \\n @notice \\n Returns the fee amount based on the provided amount for the specified project.\\n\\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\\n @param _fee The percentage of the fee, out of MAX_FEE. \\n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\\n\\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\\n */\\n function _feeAmount(\\n uint256 _amount,\\n uint256 _fee,\\n uint256 _feeDiscount\\n ) internal pure returns (uint256) {\\n // Calculate the discounted fee.\\n uint256 _discountedFee = _fee -\\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\\n\\n // The amount of tokens from the `_amount` to pay as a fee.\\n return\\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\\n }\\n\\n /** \\n @notice\\n Get the fee discount from the fee gauge for the specified project.\\n\\n @param _projectId The ID of the project to get a fee discount for.\\n \\n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\\n */\\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\\n if (\\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\\n IJBPaymentTerminal(address(0))\\n ) return JBConstants.MAX_FEE_DISCOUNT;\\n\\n // Get the fee discount.\\n if (feeGauge != IJBFeeGauge(address(0)))\\n // If the guage reverts, keep the discount at 0.\\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\\n // If the fee discount is greater than the max, we ignore the return value\\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\\n } catch {\\n return 0;\\n }\\n\\n return 0;\\n }\\n}\\n\",\"keccak256\":\"0x1af3116bfcffd711bd25c79f41f389a1a163716420d22869c072e83e4be60c68\",\"license\":\"MIT\"},\"contracts/abstract/JBSingleTokenPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\\nimport './../interfaces/IJBSingleTokenPaymentTerminal.sol';\\n\\n/**\\n @notice\\n Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\\n\\n @dev\\n Adheres to -\\n IJBSingleTokenPaymentTerminals: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n\\n @dev\\n Inherits from -\\n ERC165: Introspection on interface adherance. \\n*/\\nabstract contract JBSingleTokenPaymentTerminal is ERC165, IJBSingleTokenPaymentTerminal {\\n //*********************************************************************//\\n // ---------------- public immutable stored properties --------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The token that this terminal accepts.\\n */\\n address public immutable override token;\\n\\n /**\\n @notice\\n The number of decimals the token fixed point amounts are expected to have.\\n */\\n uint256 public immutable override decimals;\\n\\n /**\\n @notice\\n The currency to use when resolving price feeds for this terminal.\\n */\\n uint256 public immutable override currency;\\n\\n //*********************************************************************//\\n // ------------------------- external views -------------------------- //\\n //*********************************************************************//\\n\\n /** \\n @notice\\n A flag indicating if this terminal accepts the specified token.\\n\\n @param _token The token to check if this terminal accepts or not.\\n @param _projectId The project ID to check for token acceptance.\\n\\n @return The flag.\\n */\\n function acceptsToken(address _token, uint256 _projectId) external view override returns (bool) {\\n _projectId; // Prevents unused var compiler and natspec complaints.\\n\\n return _token == token;\\n }\\n\\n /** \\n @notice\\n The decimals that should be used in fixed number accounting for the specified token.\\n\\n @param _token The token to check for the decimals of.\\n\\n @return The number of decimals for the token.\\n */\\n function decimalsForToken(address _token) external view override returns (uint256) {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n return decimals;\\n }\\n\\n /** \\n @notice\\n The currency that should be used for the specified token.\\n\\n @param _token The token to check for the currency of.\\n\\n @return The currency index.\\n */\\n function currencyForToken(address _token) external view override returns (uint256) {\\n _token; // Prevents unused var compiler and natspec complaints.\\n\\n return currency;\\n }\\n\\n //*********************************************************************//\\n // -------------------------- public views --------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Indicates if this contract adheres to the specified interface.\\n\\n @dev \\n See {IERC165-supportsInterface}.\\n\\n @param _interfaceId The ID of the interface to check for adherance to.\\n */\\n function supportsInterface(bytes4 _interfaceId)\\n public\\n view\\n virtual\\n override(ERC165, IERC165)\\n returns (bool)\\n {\\n return\\n _interfaceId == type(IJBPaymentTerminal).interfaceId ||\\n _interfaceId == type(IJBSingleTokenPaymentTerminal).interfaceId ||\\n super.supportsInterface(_interfaceId);\\n }\\n\\n //*********************************************************************//\\n // -------------------------- constructor ---------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @param _token The token that this terminal manages.\\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\\n @param _currency The currency that this terminal's token adheres to for price feeds.\\n */\\n constructor(\\n address _token,\\n uint256 _decimals,\\n uint256 _currency\\n ) {\\n token = _token;\\n decimals = _decimals;\\n currency = _currency;\\n }\\n}\\n\",\"keccak256\":\"0xdc82ad3e01b918d3d21ffea8c9f30950d81e225137c851599d028dcd22125f89\",\"license\":\"MIT\"},\"contracts/enums/JBBallotState.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nenum JBBallotState {\\n Active,\\n Approved,\\n Failed\\n}\\n\",\"keccak256\":\"0x891fcac63470398b3a11239da7feba6b07d640809fcefd2404303b823d7378f8\",\"license\":\"MIT\"},\"contracts/interfaces/IJBAllowanceTerminal3_1.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBAllowanceTerminal3_1 {\\n function useAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n address _token,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external returns (uint256 netDistributedAmount);\\n}\\n\",\"keccak256\":\"0x4e1ef83fc258e44f7880005b7944e3b4799d87129b2300236d93269a00adb4ee\",\"license\":\"MIT\"},\"contracts/interfaces/IJBController.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBFundAccessConstraints.sol';\\nimport './../structs/JBFundingCycleData.sol';\\nimport './../structs/JBFundingCycleMetadata.sol';\\nimport './../structs/JBGroupedSplits.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBMigratable.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBSplitsStore.sol';\\nimport './IJBTokenStore.sol';\\n\\ninterface IJBController is IERC165 {\\n event LaunchProject(uint256 configuration, uint256 projectId, string memo, address caller);\\n\\n event LaunchFundingCycles(uint256 configuration, uint256 projectId, string memo, address caller);\\n\\n event ReconfigureFundingCycles(\\n uint256 configuration,\\n uint256 projectId,\\n string memo,\\n address caller\\n );\\n\\n event SetFundAccessConstraints(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n JBFundAccessConstraints constraints,\\n address caller\\n );\\n\\n event DistributeReservedTokens(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address beneficiary,\\n uint256 tokenCount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n address caller\\n );\\n\\n event DistributeToReservedTokenSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n uint256 tokenCount,\\n address caller\\n );\\n\\n event MintTokens(\\n address indexed beneficiary,\\n uint256 indexed projectId,\\n uint256 tokenCount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n uint256 reservedRate,\\n address caller\\n );\\n\\n event BurnTokens(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 tokenCount,\\n string memo,\\n address caller\\n );\\n\\n event Migrate(uint256 indexed projectId, IJBMigratable to, address caller);\\n\\n event PrepMigration(uint256 indexed projectId, address from, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function tokenStore() external view returns (IJBTokenStore);\\n\\n function splitsStore() external view returns (IJBSplitsStore);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function reservedTokenBalanceOf(uint256 _projectId, uint256 _reservedRate)\\n external\\n view\\n returns (uint256);\\n\\n function distributionLimitOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n IJBPaymentTerminal _terminal,\\n address _token\\n ) external view returns (uint256 distributionLimit, uint256 distributionLimitCurrency);\\n\\n function overflowAllowanceOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n IJBPaymentTerminal _terminal,\\n address _token\\n ) external view returns (uint256 overflowAllowance, uint256 overflowAllowanceCurrency);\\n\\n function totalOutstandingTokensOf(uint256 _projectId, uint256 _reservedRate)\\n external\\n view\\n returns (uint256);\\n\\n function getFundingCycleOf(uint256 _projectId, uint256 _configuration)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function latestConfiguredFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (\\n JBFundingCycle memory,\\n JBFundingCycleMetadata memory metadata,\\n JBBallotState\\n );\\n\\n function currentFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function queuedFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function launchProjectFor(\\n address _owner,\\n JBProjectMetadata calldata _projectMetadata,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n IJBPaymentTerminal[] memory _terminals,\\n string calldata _memo\\n ) external returns (uint256 projectId);\\n\\n function launchFundingCyclesFor(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n IJBPaymentTerminal[] memory _terminals,\\n string calldata _memo\\n ) external returns (uint256 configuration);\\n\\n function reconfigureFundingCyclesOf(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n string calldata _memo\\n ) external returns (uint256);\\n\\n function mintTokensOf(\\n uint256 _projectId,\\n uint256 _tokenCount,\\n address _beneficiary,\\n string calldata _memo,\\n bool _preferClaimedTokens,\\n bool _useReservedRate\\n ) external returns (uint256 beneficiaryTokenCount);\\n\\n function burnTokensOf(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n string calldata _memo,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function distributeReservedTokensOf(uint256 _projectId, string memory _memo)\\n external\\n returns (uint256);\\n\\n function migrate(uint256 _projectId, IJBMigratable _to) external;\\n}\\n\",\"keccak256\":\"0xb1ee4b41f2a06f28f69c74cb729b8964f2e75f3c545a68f85bd9082b5575bc85\",\"license\":\"MIT\"},\"contracts/interfaces/IJBDirectory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBProjects.sol';\\n\\ninterface IJBDirectory {\\n event SetController(uint256 indexed projectId, address indexed controller, address caller);\\n\\n event AddTerminal(uint256 indexed projectId, IJBPaymentTerminal indexed terminal, address caller);\\n\\n event SetTerminals(uint256 indexed projectId, IJBPaymentTerminal[] terminals, address caller);\\n\\n event SetPrimaryTerminal(\\n uint256 indexed projectId,\\n address indexed token,\\n IJBPaymentTerminal indexed terminal,\\n address caller\\n );\\n\\n event SetIsAllowedToSetFirstController(address indexed addr, bool indexed flag, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function controllerOf(uint256 _projectId) external view returns (address);\\n\\n function isAllowedToSetFirstController(address _address) external view returns (bool);\\n\\n function terminalsOf(uint256 _projectId) external view returns (IJBPaymentTerminal[] memory);\\n\\n function isTerminalOf(uint256 _projectId, IJBPaymentTerminal _terminal)\\n external\\n view\\n returns (bool);\\n\\n function primaryTerminalOf(uint256 _projectId, address _token)\\n external\\n view\\n returns (IJBPaymentTerminal);\\n\\n function setControllerOf(uint256 _projectId, address _controller) external;\\n\\n function setTerminalsOf(uint256 _projectId, IJBPaymentTerminal[] calldata _terminals) external;\\n\\n function setPrimaryTerminalOf(\\n uint256 _projectId,\\n address _token,\\n IJBPaymentTerminal _terminal\\n ) external;\\n\\n function setIsAllowedToSetFirstController(address _address, bool _flag) external;\\n}\\n\",\"keccak256\":\"0x715321646db00514d1355ed43c40cd3f01e94959552fd07797b315d9c49cdb1d\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFeeGauge.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBFeeGauge {\\n function currentDiscountFor(uint256 _projectId) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x8e19959617191320fe1210760860e668a57319258c0c74fcfabac829ae0222c0\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFeeHoldingTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBFeeHoldingTerminal {\\n function addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n bool _shouldRefundHeldFees,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable;\\n}\\n\",\"keccak256\":\"0x8c9edae0768a737097835b8b9ef4a60f000de122a867c90f20cfc653287541a4\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleBallot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../enums/JBBallotState.sol';\\n\\ninterface IJBFundingCycleBallot is IERC165 {\\n function duration() external view returns (uint256);\\n\\n function stateOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n uint256 _start\\n ) external view returns (JBBallotState);\\n}\\n\",\"keccak256\":\"0x49553a56209237846bc400cf27f260824a6bd06fd8094a7eb5abb9de75779598\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../enums/JBBallotState.sol';\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBFundingCycleData.sol';\\n\\ninterface IJBFundingCycleStore {\\n event Configure(\\n uint256 indexed configuration,\\n uint256 indexed projectId,\\n JBFundingCycleData data,\\n uint256 metadata,\\n uint256 mustStartAtOrAfter,\\n address caller\\n );\\n\\n event Init(uint256 indexed configuration, uint256 indexed projectId, uint256 indexed basedOn);\\n\\n function latestConfigurationOf(uint256 _projectId) external view returns (uint256);\\n\\n function get(uint256 _projectId, uint256 _configuration)\\n external\\n view\\n returns (JBFundingCycle memory);\\n\\n function latestConfiguredOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBBallotState ballotState);\\n\\n function queuedOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentBallotStateOf(uint256 _projectId) external view returns (JBBallotState);\\n\\n function configureFor(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n uint256 _metadata,\\n uint256 _mustStartAtOrAfter\\n ) external returns (JBFundingCycle memory fundingCycle);\\n}\\n\",\"keccak256\":\"0xaead823851433be0c2ddc8f8086813e6cd647de3a1bc0f7570a5d6b38c378b5a\",\"license\":\"MIT\"},\"contracts/interfaces/IJBMigratable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBMigratable {\\n function prepForMigrationOf(uint256 _projectId, address _from) external;\\n}\\n\",\"keccak256\":\"0xc81053e4b4754fc510aa04fecd3ab1460f01e3e27761e7a8c94f631a978ae127\",\"license\":\"MIT\"},\"contracts/interfaces/IJBOperatable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBOperatorStore.sol';\\n\\ninterface IJBOperatable {\\n function operatorStore() external view returns (IJBOperatorStore);\\n}\\n\",\"keccak256\":\"0x09a55a91c6ce3625379334271d236cfa47bf36522a91568b406bf06f7239407e\",\"license\":\"MIT\"},\"contracts/interfaces/IJBOperatorStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBOperatorData.sol';\\n\\ninterface IJBOperatorStore {\\n event SetOperator(\\n address indexed operator,\\n address indexed account,\\n uint256 indexed domain,\\n uint256[] permissionIndexes,\\n uint256 packed\\n );\\n\\n function permissionsOf(\\n address _operator,\\n address _account,\\n uint256 _domain\\n ) external view returns (uint256);\\n\\n function hasPermission(\\n address _operator,\\n address _account,\\n uint256 _domain,\\n uint256 _permissionIndex\\n ) external view returns (bool);\\n\\n function hasPermissions(\\n address _operator,\\n address _account,\\n uint256 _domain,\\n uint256[] calldata _permissionIndexes\\n ) external view returns (bool);\\n\\n function setOperator(JBOperatorData calldata _operatorData) external;\\n\\n function setOperators(JBOperatorData[] calldata _operatorData) external;\\n}\\n\",\"keccak256\":\"0x17f4929812a356984795fafed8cb2be816a025c9a0771d85595ac0b5ff3cffc5\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPayDelegate.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBDidPayData.sol';\\n\\n/**\\n @title\\n Pay delegate\\n\\n @notice\\n Delegate called after JBTerminal.pay(..) logic completion (if passed by the funding cycle datasource)\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n*/\\ninterface IJBPayDelegate is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.pay(..), after the execution of its logic\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control\\n \\n @param _data the data passed by the terminal, as a JBDidPayData struct:\\n address payer;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n JBTokenAmount amount;\\n JBTokenAmount forwardedAmount;\\n uint256 projectTokenCount;\\n address beneficiary;\\n bool preferClaimedTokens;\\n string memo;\\n bytes metadata;\\n */\\n function didPay(JBDidPayData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0xa797de18b69eceba117e1f0b3810cf3cc2d2791417d580a5bdc510d1b868ab26\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\n\\ninterface IJBPaymentTerminal is IERC165 {\\n function acceptsToken(address _token, uint256 _projectId) external view returns (bool);\\n\\n function currencyForToken(address _token) external view returns (uint256);\\n\\n function decimalsForToken(address _token) external view returns (uint256);\\n\\n // Return value must be a fixed point number with 18 decimals.\\n function currentEthOverflowOf(uint256 _projectId) external view returns (uint256);\\n\\n function pay(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable returns (uint256 beneficiaryTokenCount);\\n\\n function addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable;\\n}\\n\",\"keccak256\":\"0xb7826f5ed609359ce322c09e83236c47ba385df1c3cad3607e56fd0a2e00eee2\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPayoutRedemptionPaymentTerminal3_1.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBFee.sol';\\nimport './IJBAllowanceTerminal3_1.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFeeGauge.sol';\\nimport './IJBFeeHoldingTerminal.sol';\\nimport './IJBPayDelegate.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBPayoutTerminal3_1.sol';\\nimport './IJBPrices.sol';\\nimport './IJBProjects.sol';\\nimport './IJBRedemptionDelegate.sol';\\nimport './IJBRedemptionTerminal.sol';\\nimport './IJBSingleTokenPaymentTerminalStore.sol';\\nimport './IJBSplitsStore.sol';\\n\\ninterface IJBPayoutRedemptionPaymentTerminal3_1 is\\n IJBPaymentTerminal,\\n IJBPayoutTerminal3_1,\\n IJBAllowanceTerminal3_1,\\n IJBRedemptionTerminal,\\n IJBFeeHoldingTerminal\\n{\\n event AddToBalance(\\n uint256 indexed projectId,\\n uint256 amount,\\n uint256 refundedFees,\\n string memo,\\n bytes metadata,\\n address caller\\n );\\n\\n event Migrate(\\n uint256 indexed projectId,\\n IJBPaymentTerminal indexed to,\\n uint256 amount,\\n address caller\\n );\\n\\n event DistributePayouts(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address beneficiary,\\n uint256 amount,\\n uint256 distributedAmount,\\n uint256 fee,\\n uint256 beneficiaryDistributionAmount,\\n bytes metadata,\\n address caller\\n );\\n\\n event UseAllowance(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address beneficiary,\\n uint256 amount,\\n uint256 distributedAmount,\\n uint256 netDistributedamount,\\n string memo,\\n bytes metadata,\\n address caller\\n );\\n\\n event HoldFee(\\n uint256 indexed projectId,\\n uint256 indexed amount,\\n uint256 indexed fee,\\n uint256 feeDiscount,\\n address beneficiary,\\n address caller\\n );\\n\\n event ProcessFee(\\n uint256 indexed projectId,\\n uint256 indexed amount,\\n bool indexed wasHeld,\\n address beneficiary,\\n address caller\\n );\\n\\n event RefundHeldFees(\\n uint256 indexed projectId,\\n uint256 indexed amount,\\n uint256 indexed refundedFees,\\n uint256 leftoverAmount,\\n address caller\\n );\\n\\n event Pay(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address payer,\\n address beneficiary,\\n uint256 amount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n bytes metadata,\\n address caller\\n );\\n\\n event DelegateDidPay(\\n IJBPayDelegate indexed delegate,\\n JBDidPayData data,\\n uint256 delegatedAmount,\\n address caller\\n );\\n\\n event RedeemTokens(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address holder,\\n address beneficiary,\\n uint256 tokenCount,\\n uint256 reclaimedAmount,\\n string memo,\\n bytes metadata,\\n address caller\\n );\\n\\n event DelegateDidRedeem(\\n IJBRedemptionDelegate indexed delegate,\\n JBDidRedeemData data,\\n uint256 delegatedAmount,\\n address caller\\n );\\n\\n event DistributeToPayoutSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n uint256 amount,\\n uint256 netAmount,\\n address caller\\n );\\n\\n event SetFee(uint256 fee, address caller);\\n\\n event SetFeeGauge(IJBFeeGauge indexed feeGauge, address caller);\\n\\n event SetFeelessAddress(address indexed addrs, bool indexed flag, address caller);\\n\\n event PayoutReverted(uint256 indexed projectId, JBSplit split, uint256 amount, bytes reason, address caller);\\n\\n event FeeReverted(\\n uint256 indexed projectId,\\n uint256 indexed feeProjectId,\\n uint256 amount,\\n bytes reason,\\n address caller\\n );\\n\\n function projects() external view returns (IJBProjects);\\n\\n function splitsStore() external view returns (IJBSplitsStore);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function prices() external view returns (IJBPrices);\\n\\n function store() external view returns (IJBSingleTokenPaymentTerminalStore);\\n\\n function baseWeightCurrency() external view returns (uint256);\\n\\n function payoutSplitsGroup() external view returns (uint256);\\n\\n function heldFeesOf(uint256 _projectId) external view returns (JBFee[] memory);\\n\\n function fee() external view returns (uint256);\\n\\n function feeGauge() external view returns (IJBFeeGauge);\\n\\n function isFeelessAddress(address _contract) external view returns (bool);\\n\\n function migrate(uint256 _projectId, IJBPaymentTerminal _to) external returns (uint256 balance);\\n\\n function processFees(uint256 _projectId) external;\\n\\n function setFee(uint256 _fee) external;\\n\\n function setFeeGauge(IJBFeeGauge _feeGauge) external;\\n\\n function setFeelessAddress(address _contract, bool _flag) external;\\n}\\n\",\"keccak256\":\"0xe823526fd535dc962784820cac32e6fdd56f2a5020dbf9883979b9ddfcc093fa\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPayoutTerminal3_1.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBPayoutTerminal3_1 {\\n function distributePayoutsOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency,\\n address _token,\\n uint256 _minReturnedTokens,\\n bytes calldata _metadata\\n ) external returns (uint256 netLeftoverDistributionAmount);\\n}\\n\",\"keccak256\":\"0x415707a4902f90945ecee641e96dd88c733b1d159c35c1184e665ca3509ffe49\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPriceFeed.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBPriceFeed {\\n function currentPrice(uint256 _targetDecimals) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x57c71282fec1b34b00cf991ffed2e36031c393e35bfa7ca5d723eb6572fb7122\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPrices.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBPriceFeed.sol';\\n\\ninterface IJBPrices {\\n event AddFeed(uint256 indexed currency, uint256 indexed base, IJBPriceFeed feed);\\n\\n function feedFor(uint256 _currency, uint256 _base) external view returns (IJBPriceFeed);\\n\\n function priceFor(\\n uint256 _currency,\\n uint256 _base,\\n uint256 _decimals\\n ) external view returns (uint256);\\n\\n function addFeedFor(\\n uint256 _currency,\\n uint256 _base,\\n IJBPriceFeed _priceFeed\\n ) external;\\n}\\n\",\"keccak256\":\"0x82a175b1f4b95b506c98406576cd59cbe04615e3df24f9cf3587b61b8ee323b1\",\"license\":\"MIT\"},\"contracts/interfaces/IJBProjects.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBTokenUriResolver.sol';\\n\\ninterface IJBProjects is IERC721 {\\n event Create(\\n uint256 indexed projectId,\\n address indexed owner,\\n JBProjectMetadata metadata,\\n address caller\\n );\\n\\n event SetMetadata(uint256 indexed projectId, JBProjectMetadata metadata, address caller);\\n\\n event SetTokenUriResolver(IJBTokenUriResolver indexed resolver, address caller);\\n\\n function count() external view returns (uint256);\\n\\n function metadataContentOf(uint256 _projectId, uint256 _domain)\\n external\\n view\\n returns (string memory);\\n\\n function tokenUriResolver() external view returns (IJBTokenUriResolver);\\n\\n function createFor(address _owner, JBProjectMetadata calldata _metadata)\\n external\\n returns (uint256 projectId);\\n\\n function setMetadataOf(uint256 _projectId, JBProjectMetadata calldata _metadata) external;\\n\\n function setTokenUriResolver(IJBTokenUriResolver _newResolver) external;\\n}\\n\",\"keccak256\":\"0x7cfc021d0bd7e73b1ba8f4845d7d35e3419d6a14d3d25ca3a8010e7f91062fe4\",\"license\":\"MIT\"},\"contracts/interfaces/IJBRedemptionDelegate.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBDidRedeemData.sol';\\n\\n/**\\n @title\\n Redemption delegate\\n\\n @notice\\n Delegate called after JBTerminal.redeemTokensOf(..) logic completion (if passed by the funding cycle datasource)\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n*/\\ninterface IJBRedemptionDelegate is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.redeemTokensOf(..), after the execution of its logic\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control\\n \\n @param _data the data passed by the terminal, as a JBDidRedeemData struct:\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 projectTokenCount;\\n JBTokenAmount reclaimedAmount;\\n JBTokenAmount forwardedAmount;\\n address payable beneficiary;\\n string memo;\\n bytes metadata;\\n */\\n function didRedeem(JBDidRedeemData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0x172d2c0be65e72e54f71ae521907067f0fa30e8ca05c4f88826903208aa437e2\",\"license\":\"MIT\"},\"contracts/interfaces/IJBRedemptionTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBRedemptionTerminal {\\n function redeemTokensOf(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n address _token,\\n uint256 _minReturnedTokens,\\n address payable _beneficiary,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external returns (uint256 reclaimAmount);\\n}\\n\",\"keccak256\":\"0xe26a6a03468401b802ae5328b39a266f53b9331a1c077fcbf7719d10ba74ff44\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSingleTokenPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBPaymentTerminal.sol';\\n\\ninterface IJBSingleTokenPaymentTerminal is IJBPaymentTerminal {\\n function token() external view returns (address);\\n\\n function currency() external view returns (uint256);\\n\\n function decimals() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xf6e78323caa9af7bbf024f44b2032a83fed0394e0b3a242a6346e73c85b2e46f\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSingleTokenPaymentTerminalStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBPayDelegateAllocation.sol';\\nimport './../structs/JBRedemptionDelegateAllocation.sol';\\nimport './../structs/JBTokenAmount.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBPrices.sol';\\nimport './IJBSingleTokenPaymentTerminal.sol';\\n\\ninterface IJBSingleTokenPaymentTerminalStore {\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function prices() external view returns (IJBPrices);\\n\\n function balanceOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\\n external\\n view\\n returns (uint256);\\n\\n function usedDistributionLimitOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _fundingCycleNumber\\n ) external view returns (uint256);\\n\\n function usedOverflowAllowanceOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _fundingCycleConfiguration\\n ) external view returns (uint256);\\n\\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\\n external\\n view\\n returns (uint256);\\n\\n function currentTotalOverflowOf(\\n uint256 _projectId,\\n uint256 _decimals,\\n uint256 _currency\\n ) external view returns (uint256);\\n\\n function currentReclaimableOverflowOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n bool _useTotalOverflow\\n ) external view returns (uint256);\\n\\n function currentReclaimableOverflowOf(\\n uint256 _projectId,\\n uint256 _tokenCount,\\n uint256 _totalSupply,\\n uint256 _overflow\\n ) external view returns (uint256);\\n\\n function recordPaymentFrom(\\n address _payer,\\n JBTokenAmount memory _amount,\\n uint256 _projectId,\\n uint256 _baseWeightCurrency,\\n address _beneficiary,\\n string calldata _memo,\\n bytes calldata _metadata\\n )\\n external\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 tokenCount,\\n JBPayDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n );\\n\\n function recordRedemptionFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n string calldata _memo,\\n bytes calldata _metadata\\n )\\n external\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 reclaimAmount,\\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n );\\n\\n function recordDistributionFor(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n ) external returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount);\\n\\n function recordUsedAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n ) external returns (JBFundingCycle memory fundingCycle, uint256 withdrawnAmount);\\n\\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external;\\n\\n function recordMigration(uint256 _projectId) external returns (uint256 balance);\\n}\\n\",\"keccak256\":\"0xd78929c9371fd7895b829ef5e4ad4b3786523c3580ac3f6f5f25d2b5941c0dd3\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSplitAllocator.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport '../structs/JBSplitAllocationData.sol';\\n\\n/**\\n @title\\n Split allocator\\n\\n @notice\\n Provide a way to process a single split with extra logic\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n\\n @dev\\n The contract address should be set as an allocator in the adequate split\\n*/\\ninterface IJBSplitAllocator is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.distributePayoutOf(..), during the processing of the split including it\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control. The token and/or eth are optimistically transfered\\n to the allocator for its logic.\\n \\n @param _data the data passed by the terminal, as a JBSplitAllocationData struct:\\n address token;\\n uint256 amount;\\n uint256 decimals;\\n uint256 projectId;\\n uint256 group;\\n JBSplit split;\\n */\\n function allocate(JBSplitAllocationData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0x5efb6f51fc161f42ff58989386ad99028e4039a0ba897d66f358c3dfcf686105\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSplitsStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBGroupedSplits.sol';\\nimport './../structs/JBSplit.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBProjects.sol';\\n\\ninterface IJBSplitsStore {\\n event SetSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n address caller\\n );\\n\\n function projects() external view returns (IJBProjects);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function splitsOf(\\n uint256 _projectId,\\n uint256 _domain,\\n uint256 _group\\n ) external view returns (JBSplit[] memory);\\n\\n function set(\\n uint256 _projectId,\\n uint256 _domain,\\n JBGroupedSplits[] memory _groupedSplits\\n ) external;\\n}\\n\",\"keccak256\":\"0x66dab3dd394e318b850401ca92c2963b906cc0ad5562fa5d4f6f850175d1c77a\",\"license\":\"MIT\"},\"contracts/interfaces/IJBToken.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBToken {\\n function projectId() external view returns (uint256);\\n\\n function decimals() external view returns (uint8);\\n\\n function totalSupply(uint256 _projectId) external view returns (uint256);\\n\\n function balanceOf(address _account, uint256 _projectId) external view returns (uint256);\\n\\n function mint(\\n uint256 _projectId,\\n address _account,\\n uint256 _amount\\n ) external;\\n\\n function burn(\\n uint256 _projectId,\\n address _account,\\n uint256 _amount\\n ) external;\\n\\n function approve(\\n uint256,\\n address _spender,\\n uint256 _amount\\n ) external;\\n\\n function transfer(\\n uint256 _projectId,\\n address _to,\\n uint256 _amount\\n ) external;\\n\\n function transferFrom(\\n uint256 _projectId,\\n address _from,\\n address _to,\\n uint256 _amount\\n ) external;\\n}\\n\",\"keccak256\":\"0xe8969210417736c85d71101bf1c0bd8ebbf9d1e62a93e758148bd5709a6c7097\",\"license\":\"MIT\"},\"contracts/interfaces/IJBTokenStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBProjects.sol';\\nimport './IJBToken.sol';\\n\\ninterface IJBTokenStore {\\n event Issue(\\n uint256 indexed projectId,\\n IJBToken indexed token,\\n string name,\\n string symbol,\\n address caller\\n );\\n\\n event Mint(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 amount,\\n bool tokensWereClaimed,\\n bool preferClaimedTokens,\\n address caller\\n );\\n\\n event Burn(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 amount,\\n uint256 initialUnclaimedBalance,\\n uint256 initialClaimedBalance,\\n bool preferClaimedTokens,\\n address caller\\n );\\n\\n event Claim(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 initialUnclaimedBalance,\\n uint256 amount,\\n address caller\\n );\\n\\n event Set(uint256 indexed projectId, IJBToken indexed newToken, address caller);\\n\\n event Transfer(\\n address indexed holder,\\n uint256 indexed projectId,\\n address indexed recipient,\\n uint256 amount,\\n address caller\\n );\\n\\n function tokenOf(uint256 _projectId) external view returns (IJBToken);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function unclaimedBalanceOf(address _holder, uint256 _projectId) external view returns (uint256);\\n\\n function unclaimedTotalSupplyOf(uint256 _projectId) external view returns (uint256);\\n\\n function totalSupplyOf(uint256 _projectId) external view returns (uint256);\\n\\n function balanceOf(address _holder, uint256 _projectId) external view returns (uint256 _result);\\n\\n function issueFor(\\n uint256 _projectId,\\n string calldata _name,\\n string calldata _symbol\\n ) external returns (IJBToken token);\\n\\n function setFor(uint256 _projectId, IJBToken _token) external;\\n\\n function burnFrom(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function mintFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function claimFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount\\n ) external;\\n\\n function transferFrom(\\n address _holder,\\n uint256 _projectId,\\n address _recipient,\\n uint256 _amount\\n ) external;\\n}\\n\",\"keccak256\":\"0x98459e3af050d41dfeffdc97f1c93330207ba450f8ff3613224b49a89eeca9c6\",\"license\":\"MIT\"},\"contracts/interfaces/IJBTokenUriResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBTokenUriResolver {\\n function getUri(uint256 _projectId) external view returns (string memory tokenUri);\\n}\\n\",\"keccak256\":\"0xd267fd8ca7c21c2c71794acdb9a98314c33a35fc559e0bf0897a6686d196d174\",\"license\":\"MIT\"},\"contracts/libraries/JBConstants.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/**\\n @notice\\n Global constants used across Juicebox contracts.\\n*/\\nlibrary JBConstants {\\n uint256 public constant MAX_RESERVED_RATE = 10_000;\\n uint256 public constant MAX_REDEMPTION_RATE = 10_000;\\n uint256 public constant MAX_DISCOUNT_RATE = 1_000_000_000;\\n uint256 public constant SPLITS_TOTAL_PERCENT = 1_000_000_000;\\n uint256 public constant MAX_FEE = 1_000_000_000;\\n uint256 public constant MAX_FEE_DISCOUNT = 1_000_000_000;\\n}\\n\",\"keccak256\":\"0x34362846a1cd428a8bdedf4ab6857e11402f345cb87b994b2e7fb6d2474b808d\",\"license\":\"MIT\"},\"contracts/libraries/JBCurrencies.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBCurrencies {\\n uint256 public constant ETH = 1;\\n uint256 public constant USD = 2;\\n}\\n\",\"keccak256\":\"0x7e417ff25c173608ee4fe6d9fc3dcd5e1458c78c889af12bac47b1189a436076\",\"license\":\"MIT\"},\"contracts/libraries/JBFixedPointNumber.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nlibrary JBFixedPointNumber {\\n function adjustDecimals(\\n uint256 _value,\\n uint256 _decimals,\\n uint256 _targetDecimals\\n ) internal pure returns (uint256) {\\n // If decimals need adjusting, multiply or divide the price by the decimal adjuster to get the normalized result.\\n if (_targetDecimals == _decimals) return _value;\\n else if (_targetDecimals > _decimals) return _value * 10**(_targetDecimals - _decimals);\\n else return _value / 10**(_decimals - _targetDecimals);\\n }\\n}\\n\",\"keccak256\":\"0x18efac48269f3a3bd7e9a1c770776f950e0afa86769e6f8b128002c3b8c6742c\",\"license\":\"MIT\"},\"contracts/libraries/JBFundingCycleMetadataResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBFundingCycleMetadata.sol';\\nimport './../structs/JBGlobalFundingCycleMetadata.sol';\\nimport './JBConstants.sol';\\nimport './JBGlobalFundingCycleMetadataResolver.sol';\\n\\nlibrary JBFundingCycleMetadataResolver {\\n function global(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (JBGlobalFundingCycleMetadata memory)\\n {\\n return JBGlobalFundingCycleMetadataResolver.expandMetadata(uint8(_fundingCycle.metadata >> 8));\\n }\\n\\n function reservedRate(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n return uint256(uint16(_fundingCycle.metadata >> 24));\\n }\\n\\n function redemptionRate(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n // Redemption rate is a number 0-10000. It's inverse was stored so the most common case of 100% results in no storage needs.\\n return JBConstants.MAX_REDEMPTION_RATE - uint256(uint16(_fundingCycle.metadata >> 40));\\n }\\n\\n function ballotRedemptionRate(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (uint256)\\n {\\n // Redemption rate is a number 0-10000. It's inverse was stored so the most common case of 100% results in no storage needs.\\n return JBConstants.MAX_REDEMPTION_RATE - uint256(uint16(_fundingCycle.metadata >> 56));\\n }\\n\\n function payPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 72) & 1) == 1;\\n }\\n\\n function distributionsPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 73) & 1) == 1;\\n }\\n\\n function redeemPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 74) & 1) == 1;\\n }\\n\\n function burnPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 75) & 1) == 1;\\n }\\n\\n function mintingAllowed(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 76) & 1) == 1;\\n }\\n\\n function terminalMigrationAllowed(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 77) & 1) == 1;\\n }\\n\\n function controllerMigrationAllowed(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 78) & 1) == 1;\\n }\\n\\n function shouldHoldFees(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 79) & 1) == 1;\\n }\\n\\n function preferClaimedTokenOverride(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 80) & 1) == 1;\\n }\\n\\n function useTotalOverflowForRedemptions(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 81) & 1) == 1;\\n }\\n\\n function useDataSourceForPay(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return (_fundingCycle.metadata >> 82) & 1 == 1;\\n }\\n\\n function useDataSourceForRedeem(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return (_fundingCycle.metadata >> 83) & 1 == 1;\\n }\\n\\n function dataSource(JBFundingCycle memory _fundingCycle) internal pure returns (address) {\\n return address(uint160(_fundingCycle.metadata >> 84));\\n }\\n\\n function metadata(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n return uint256(uint8(_fundingCycle.metadata >> 244));\\n }\\n\\n /**\\n @notice\\n Pack the funding cycle metadata.\\n\\n @param _metadata The metadata to validate and pack.\\n\\n @return packed The packed uint256 of all metadata params. The first 8 bits specify the version.\\n */\\n function packFundingCycleMetadata(JBFundingCycleMetadata memory _metadata)\\n internal\\n pure\\n returns (uint256 packed)\\n {\\n // version 1 in the bits 0-7 (8 bits).\\n packed = 1;\\n // global metadta in bits 8-23 (16 bits).\\n packed |=\\n JBGlobalFundingCycleMetadataResolver.packFundingCycleGlobalMetadata(_metadata.global) <<\\n 8;\\n // reserved rate in bits 24-39 (16 bits).\\n packed |= _metadata.reservedRate << 24;\\n // redemption rate in bits 40-55 (16 bits).\\n // redemption rate is a number 0-10000. Store the reverse so the most common case of 100% results in no storage needs.\\n packed |= (JBConstants.MAX_REDEMPTION_RATE - _metadata.redemptionRate) << 40;\\n // ballot redemption rate rate in bits 56-71 (16 bits).\\n // ballot redemption rate is a number 0-10000. Store the reverse so the most common case of 100% results in no storage needs.\\n packed |= (JBConstants.MAX_REDEMPTION_RATE - _metadata.ballotRedemptionRate) << 56;\\n // pause pay in bit 72.\\n if (_metadata.pausePay) packed |= 1 << 72;\\n // pause tap in bit 73.\\n if (_metadata.pauseDistributions) packed |= 1 << 73;\\n // pause redeem in bit 74.\\n if (_metadata.pauseRedeem) packed |= 1 << 74;\\n // pause burn in bit 75.\\n if (_metadata.pauseBurn) packed |= 1 << 75;\\n // allow minting in bit 76.\\n if (_metadata.allowMinting) packed |= 1 << 76;\\n // allow terminal migration in bit 77.\\n if (_metadata.allowTerminalMigration) packed |= 1 << 77;\\n // allow controller migration in bit 78.\\n if (_metadata.allowControllerMigration) packed |= 1 << 78;\\n // hold fees in bit 79.\\n if (_metadata.holdFees) packed |= 1 << 79;\\n // prefer claimed token override in bit 80.\\n if (_metadata.preferClaimedTokenOverride) packed |= 1 << 80;\\n // useTotalOverflowForRedemptions in bit 81.\\n if (_metadata.useTotalOverflowForRedemptions) packed |= 1 << 81;\\n // use pay data source in bit 82.\\n if (_metadata.useDataSourceForPay) packed |= 1 << 82;\\n // use redeem data source in bit 83.\\n if (_metadata.useDataSourceForRedeem) packed |= 1 << 83;\\n // data source address in bits 84-243.\\n packed |= uint256(uint160(address(_metadata.dataSource))) << 84;\\n // metadata in bits 244-252 (8 bits).\\n packed |= _metadata.metadata << 244;\\n }\\n\\n /**\\n @notice\\n Expand the funding cycle metadata.\\n\\n @param _fundingCycle The funding cycle having its metadata expanded.\\n\\n @return metadata The metadata object.\\n */\\n function expandMetadata(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (JBFundingCycleMetadata memory)\\n {\\n return\\n JBFundingCycleMetadata(\\n global(_fundingCycle),\\n reservedRate(_fundingCycle),\\n redemptionRate(_fundingCycle),\\n ballotRedemptionRate(_fundingCycle),\\n payPaused(_fundingCycle),\\n distributionsPaused(_fundingCycle),\\n redeemPaused(_fundingCycle),\\n burnPaused(_fundingCycle),\\n mintingAllowed(_fundingCycle),\\n terminalMigrationAllowed(_fundingCycle),\\n controllerMigrationAllowed(_fundingCycle),\\n shouldHoldFees(_fundingCycle),\\n preferClaimedTokenOverride(_fundingCycle),\\n useTotalOverflowForRedemptions(_fundingCycle),\\n useDataSourceForPay(_fundingCycle),\\n useDataSourceForRedeem(_fundingCycle),\\n dataSource(_fundingCycle),\\n metadata(_fundingCycle)\\n );\\n }\\n}\\n\",\"keccak256\":\"0x3d045c38593102cfb6ac67f3ddf2232e1ff5518d6d021423ae2681387599fbd3\",\"license\":\"MIT\"},\"contracts/libraries/JBGlobalFundingCycleMetadataResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport './../structs/JBFundingCycleMetadata.sol';\\n\\nlibrary JBGlobalFundingCycleMetadataResolver {\\n function setTerminalsAllowed(uint8 _data) internal pure returns (bool) {\\n return (_data & 1) == 1;\\n }\\n\\n function setControllerAllowed(uint8 _data) internal pure returns (bool) {\\n return ((_data >> 1) & 1) == 1;\\n }\\n\\n function transfersPaused(uint8 _data) internal pure returns (bool) {\\n return ((_data >> 2) & 1) == 1;\\n }\\n\\n /**\\n @notice\\n Pack the global funding cycle metadata.\\n\\n @param _metadata The metadata to validate and pack.\\n\\n @return packed The packed uint256 of all global metadata params. The first 8 bits specify the version.\\n */\\n function packFundingCycleGlobalMetadata(JBGlobalFundingCycleMetadata memory _metadata)\\n internal\\n pure\\n returns (uint256 packed)\\n {\\n // allow set terminals in bit 0.\\n if (_metadata.allowSetTerminals) packed |= 1;\\n // allow set controller in bit 1.\\n if (_metadata.allowSetController) packed |= 1 << 1;\\n // pause transfers in bit 2.\\n if (_metadata.pauseTransfers) packed |= 1 << 2;\\n }\\n\\n /**\\n @notice\\n Expand the global funding cycle metadata.\\n\\n @param _packedMetadata The packed metadata to expand.\\n\\n @return metadata The global metadata object.\\n */\\n function expandMetadata(uint8 _packedMetadata)\\n internal\\n pure\\n returns (JBGlobalFundingCycleMetadata memory metadata)\\n {\\n return\\n JBGlobalFundingCycleMetadata(\\n setTerminalsAllowed(_packedMetadata),\\n setControllerAllowed(_packedMetadata),\\n transfersPaused(_packedMetadata)\\n );\\n }\\n}\\n\",\"keccak256\":\"0x0d998f938026edeb755987a79421267cf860801161b5f171206a200b60f1061f\",\"license\":\"MIT\"},\"contracts/libraries/JBOperations.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBOperations {\\n uint256 public constant RECONFIGURE = 1;\\n uint256 public constant REDEEM = 2;\\n uint256 public constant MIGRATE_CONTROLLER = 3;\\n uint256 public constant MIGRATE_TERMINAL = 4;\\n uint256 public constant PROCESS_FEES = 5;\\n uint256 public constant SET_METADATA = 6;\\n uint256 public constant ISSUE = 7;\\n uint256 public constant SET_TOKEN = 8;\\n uint256 public constant MINT = 9;\\n uint256 public constant BURN = 10;\\n uint256 public constant CLAIM = 11;\\n uint256 public constant TRANSFER = 12;\\n uint256 public constant REQUIRE_CLAIM = 13; // unused in v3\\n uint256 public constant SET_CONTROLLER = 14;\\n uint256 public constant SET_TERMINALS = 15;\\n uint256 public constant SET_PRIMARY_TERMINAL = 16;\\n uint256 public constant USE_ALLOWANCE = 17;\\n uint256 public constant SET_SPLITS = 18;\\n}\\n\",\"keccak256\":\"0x7f8e501e6890297f4015b1c27cebdb44fadbf21204bea1f3162f5388c060f690\",\"license\":\"MIT\"},\"contracts/libraries/JBSplitsGroups.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBSplitsGroups {\\n uint256 public constant ETH_PAYOUT = 1;\\n uint256 public constant RESERVED_TOKENS = 2;\\n}\\n\",\"keccak256\":\"0x4183db6087bd8db645fc3a0d3d8afb0d6356e003650793f63c301ebbbae47269\",\"license\":\"MIT\"},\"contracts/libraries/JBTokens.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBTokens {\\n /** \\n @notice \\n The ETH token address in Juicebox is represented by 0x000000000000000000000000000000000000EEEe.\\n */\\n address public constant ETH = address(0x000000000000000000000000000000000000EEEe);\\n}\\n\",\"keccak256\":\"0xecf82992f7b827766aa55f16872517a646521eef414d8cc9786617ea377e5463\",\"license\":\"MIT\"},\"contracts/structs/JBDidPayData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member payer The address from which the payment originated.\\n @member projectId The ID of the project for which the payment was made.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the payment is being made.\\n @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.\\n @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.\\n @member projectTokenCount The number of project tokens minted for the beneficiary.\\n @member beneficiary The address to which the tokens were minted.\\n @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.\\n @member memo The memo that is being emitted alongside the payment.\\n @member metadata Extra data to send to the delegate.\\n*/\\nstruct JBDidPayData {\\n address payer;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n JBTokenAmount amount;\\n JBTokenAmount forwardedAmount;\\n uint256 projectTokenCount;\\n address beneficiary;\\n bool preferClaimedTokens;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0xf3c664309b37790f16047ae97b0459889ae0242dfcde7fc8902c8d10c7f8e6b6\",\"license\":\"MIT\"},\"contracts/structs/JBDidRedeemData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member holder The holder of the tokens being redeemed.\\n @member projectId The ID of the project with which the redeemed tokens are associated.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the redemption is being made.\\n @member projectTokenCount The number of project tokens being redeemed.\\n @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.\\n @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.\\n @member beneficiary The address to which the reclaimed amount will be sent.\\n @member memo The memo that is being emitted alongside the redemption.\\n @member metadata Extra data to send to the delegate.\\n*/\\nstruct JBDidRedeemData {\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 projectTokenCount;\\n JBTokenAmount reclaimedAmount;\\n JBTokenAmount forwardedAmount;\\n address payable beneficiary;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0xe2c401f39723a7ce915b8bef328744c66daaf57460843964b941456c2258a412\",\"license\":\"MIT\"},\"contracts/structs/JBFee.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member amount The total amount the fee was taken from, as a fixed point number with the same number of decimals as the terminal in which this struct was created.\\n @member fee The percent of the fee, out of MAX_FEE.\\n @member feeDiscount The discount of the fee.\\n @member beneficiary The address that will receive the tokens that are minted as a result of the fee payment.\\n*/\\nstruct JBFee {\\n uint256 amount;\\n uint32 fee;\\n uint32 feeDiscount;\\n address beneficiary;\\n}\\n\",\"keccak256\":\"0xf4759ff41fe7f1db0fd1ccc7b2a326b239389fd8d69df9b9ed5e1d5926f6fe38\",\"license\":\"MIT\"},\"contracts/structs/JBFundAccessConstraints.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBPaymentTerminal.sol';\\n\\n/** \\n @member terminal The terminal within which the distribution limit and the overflow allowance applies.\\n @member token The token for which the fund access constraints apply.\\n @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.\\n @member distributionLimitCurrency The currency of the distribution limit.\\n @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.\\n @member overflowAllowanceCurrency The currency of the overflow allowance.\\n*/\\nstruct JBFundAccessConstraints {\\n IJBPaymentTerminal terminal;\\n address token;\\n uint256 distributionLimit;\\n uint256 distributionLimitCurrency;\\n uint256 overflowAllowance;\\n uint256 overflowAllowanceCurrency;\\n}\\n\",\"keccak256\":\"0x85ebaa57b788cbdedc7a3d0eec4892eda5d79db7c1a6103797f10d0d989775b2\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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.\\n @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.\\n @member basedOn The `configuration` of the funding cycle that was active when this cycle was created.\\n @member start The timestamp marking the moment from which the funding cycle is considered active. It is a unix timestamp measured in seconds.\\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n @member metadata Extra data that can be associated with a funding cycle.\\n*/\\nstruct JBFundingCycle {\\n uint256 number;\\n uint256 configuration;\\n uint256 basedOn;\\n uint256 start;\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n uint256 metadata;\\n}\\n\",\"keccak256\":\"0xcdd3ac9b6fa67e62ada88d09b73bc35ade1cd77d43db712289266a788928b4c2\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycleData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n*/\\nstruct JBFundingCycleData {\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n}\\n\",\"keccak256\":\"0x2aa6368bf4dfc5797e8b02a978293de0c777fae2658de2c825a103587240f3b0\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycleMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBGlobalFundingCycleMetadata.sol';\\n\\n/** \\n @member global Data used globally in non-migratable ecosystem contracts.\\n @member reservedRate The reserved rate of the funding cycle. This number is a percentage calculated out of `JBConstants.MAX_RESERVED_RATE`.\\n @member redemptionRate The redemption rate of the funding cycle. This number is a percentage calculated out of `JBConstants.MAX_REDEMPTION_RATE`.\\n @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`.\\n @member pausePay A flag indicating if the pay functionality should be paused during the funding cycle.\\n @member pauseDistributions A flag indicating if the distribute functionality should be paused during the funding cycle.\\n @member pauseRedeem A flag indicating if the redeem functionality should be paused during the funding cycle.\\n @member pauseBurn A flag indicating if the burn functionality should be paused during the funding cycle.\\n @member allowMinting A flag indicating if minting tokens should be allowed during this funding cycle.\\n @member allowTerminalMigration A flag indicating if migrating terminals should be allowed during this funding cycle.\\n @member allowControllerMigration A flag indicating if migrating controllers should be allowed during this funding cycle.\\n @member holdFees A flag indicating if fees should be held during this funding cycle.\\n @member preferClaimedTokenOverride A flag indicating if claimed tokens should always be prefered to unclaimed tokens when minting.\\n @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.\\n @member useDataSourceForPay A flag indicating if the data source should be used for pay transactions during this funding cycle.\\n @member useDataSourceForRedeem A flag indicating if the data source should be used for redeem transactions during this funding cycle.\\n @member dataSource The data source to use during this funding cycle.\\n @member metadata Metadata of the metadata, up to uint8 in size.\\n*/\\nstruct JBFundingCycleMetadata {\\n JBGlobalFundingCycleMetadata global;\\n uint256 reservedRate;\\n uint256 redemptionRate;\\n uint256 ballotRedemptionRate;\\n bool pausePay;\\n bool pauseDistributions;\\n bool pauseRedeem;\\n bool pauseBurn;\\n bool allowMinting;\\n bool allowTerminalMigration;\\n bool allowControllerMigration;\\n bool holdFees;\\n bool preferClaimedTokenOverride;\\n bool useTotalOverflowForRedemptions;\\n bool useDataSourceForPay;\\n bool useDataSourceForRedeem;\\n address dataSource;\\n uint256 metadata;\\n}\\n\",\"keccak256\":\"0x783604440cac8d176332eab28166f188ee5c230378c08cfc95fea4f7187dc77d\",\"license\":\"MIT\"},\"contracts/structs/JBGlobalFundingCycleMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member allowSetTerminals A flag indicating if setting terminals should be allowed during this funding cycle.\\n @member allowSetController A flag indicating if setting a new controller should be allowed during this funding cycle.\\n @member pauseTransfers A flag indicating if the project token transfer functionality should be paused during the funding cycle.\\n*/\\nstruct JBGlobalFundingCycleMetadata {\\n bool allowSetTerminals;\\n bool allowSetController;\\n bool pauseTransfers;\\n}\\n\",\"keccak256\":\"0x05d85530305fec6d6eca54cdbc2cd9110cbda0146598032b0203aa4b622944ff\",\"license\":\"MIT\"},\"contracts/structs/JBGroupedSplits.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBSplit.sol';\\n\\n/** \\n @member group The group indentifier.\\n @member splits The splits to associate with the group.\\n*/\\nstruct JBGroupedSplits {\\n uint256 group;\\n JBSplit[] splits;\\n}\\n\",\"keccak256\":\"0x80be1b220da4ac04851ea540ebb94c1ec2b0442ec5bd1e88fdf78a56becd8b5a\",\"license\":\"MIT\"},\"contracts/structs/JBOperatorData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member operator The address of the operator.\\n @member domain The domain within which the operator is being given permissions. A domain of 0 is a wildcard domain, which gives an operator access to all domains.\\n @member permissionIndexes The indexes of the permissions the operator is being given.\\n*/\\nstruct JBOperatorData {\\n address operator;\\n uint256 domain;\\n uint256[] permissionIndexes;\\n}\\n\",\"keccak256\":\"0x3b85be7b69515976ee10770776283911666aceca820b0cf4e201ea4dbffeb6f0\",\"license\":\"MIT\"},\"contracts/structs/JBPayDelegateAllocation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '../interfaces/IJBPayDelegate.sol';\\n\\n/** \\n @member delegate A delegate contract to use for subsequent calls.\\n @member amount The amount to send to the delegate.\\n*/\\nstruct JBPayDelegateAllocation {\\n IJBPayDelegate delegate;\\n uint256 amount;\\n}\\n\",\"keccak256\":\"0xb4e558dc62231d89e9b48998012577d22c3e52b58e23401f22d9096827f6ea0c\",\"license\":\"MIT\"},\"contracts/structs/JBProjectMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member content The metadata content.\\n @member domain The domain within which the metadata applies.\\n*/\\nstruct JBProjectMetadata {\\n string content;\\n uint256 domain;\\n}\\n\",\"keccak256\":\"0x90ad7b1014c0a9f945fe7a2efde9d5de41e40574fa27969070b1d2ff52033ea0\",\"license\":\"MIT\"},\"contracts/structs/JBRedemptionDelegateAllocation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '../interfaces/IJBRedemptionDelegate.sol';\\n\\n/** \\n @member delegate A delegate contract to use for subsequent calls.\\n @member amount The amount to send to the delegate.\\n*/\\nstruct JBRedemptionDelegateAllocation {\\n IJBRedemptionDelegate delegate;\\n uint256 amount;\\n}\\n\",\"keccak256\":\"0x10c29d33dd0d875a0d4692a2b9a9355c2ebf433cc06a9a60253d4366b60d4d31\",\"license\":\"MIT\"},\"contracts/structs/JBSplit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBSplitAllocator.sol';\\n\\n/** \\n @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.\\n @member preferAddToBalance A flag indicating if a distribution to a project should prefer triggering it's addToBalance function instead of its pay function.\\n @member percent The percent of the whole group that this split occupies. This number is out of `JBConstants.SPLITS_TOTAL_PERCENT`.\\n @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.\\n @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.\\n @member lockedUntil Specifies if the split should be unchangeable until the specified time, with the exception of extending the locked period.\\n @member allocator If an allocator is specified, funds will be sent to the allocator contract along with all properties of this split.\\n*/\\nstruct JBSplit {\\n bool preferClaimed;\\n bool preferAddToBalance;\\n uint256 percent;\\n uint256 projectId;\\n address payable beneficiary;\\n uint256 lockedUntil;\\n IJBSplitAllocator allocator;\\n}\\n\",\"keccak256\":\"0xc80a16606da8abf76d0f73abc38aee041e24f29342c1939018f70c286e89f105\",\"license\":\"MIT\"},\"contracts/structs/JBSplitAllocationData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBSplit.sol';\\n\\n/** \\n @member token The token being sent to the split allocator.\\n @member amount The amount being sent to the split allocator, as a fixed point number.\\n @member decimals The number of decimals in the amount.\\n @member projectId The project to which the split belongs.\\n @member group The group to which the split belongs.\\n @member split The split that caused the allocation.\\n*/\\nstruct JBSplitAllocationData {\\n address token;\\n uint256 amount;\\n uint256 decimals;\\n uint256 projectId;\\n uint256 group;\\n JBSplit split;\\n}\\n\",\"keccak256\":\"0x39f5c41bd31d36774744698ac94484b6cab62d7038df2f29d947668959782e63\",\"license\":\"MIT\"},\"contracts/structs/JBTokenAmount.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/* \\n @member token The token the payment was made in.\\n @member value The amount of tokens that was paid, as a fixed point number.\\n @member decimals The number of decimals included in the value fixed point number.\\n @member currency The expected currency of the value.\\n**/\\nstruct JBTokenAmount {\\n address token;\\n uint256 value;\\n uint256 decimals;\\n uint256 currency;\\n}\\n\",\"keccak256\":\"0x4a778e779ba257ba5638c5469e07a4d21b55a3128d56db5a0fdfacb1f3301c51\",\"license\":\"MIT\"},\"prb-math/contracts/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivFixedPointOverflow(uint256 prod1);\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivOverflow(uint256 prod1, uint256 denominator);\\n\\n/// @notice Emitted when one of the inputs is type(int256).min.\\nerror PRBMath__MulDivSignedInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows int256.\\nerror PRBMath__MulDivSignedOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is MIN_SD59x18.\\nerror PRBMathSD59x18__AbsInputTooSmall();\\n\\n/// @notice Emitted when ceiling a number overflows SD59x18.\\nerror PRBMathSD59x18__CeilOverflow(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__DivInputTooSmall();\\n\\n/// @notice Emitted when one of the intermediary unsigned results overflows SD59x18.\\nerror PRBMathSD59x18__DivOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathSD59x18__ExpInputTooBig(int256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathSD59x18__Exp2InputTooBig(int256 x);\\n\\n/// @notice Emitted when flooring a number underflows SD59x18.\\nerror PRBMathSD59x18__FloorUnderflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format overflows SD59x18.\\nerror PRBMathSD59x18__FromIntOverflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format underflows SD59x18.\\nerror PRBMathSD59x18__FromIntUnderflow(int256 x);\\n\\n/// @notice Emitted when the product of the inputs is negative.\\nerror PRBMathSD59x18__GmNegativeProduct(int256 x, int256 y);\\n\\n/// @notice Emitted when multiplying the inputs overflows SD59x18.\\nerror PRBMathSD59x18__GmOverflow(int256 x, int256 y);\\n\\n/// @notice Emitted when the input is less than or equal to zero.\\nerror PRBMathSD59x18__LogInputTooSmall(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__MulInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__MulOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__PowuOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is negative.\\nerror PRBMathSD59x18__SqrtNegativeInput(int256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows SD59x18.\\nerror PRBMathSD59x18__SqrtOverflow(int256 x);\\n\\n/// @notice Emitted when addition overflows UD60x18.\\nerror PRBMathUD60x18__AddOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when ceiling a number overflows UD60x18.\\nerror PRBMathUD60x18__CeilOverflow(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathUD60x18__ExpInputTooBig(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathUD60x18__Exp2InputTooBig(uint256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format format overflows UD60x18.\\nerror PRBMathUD60x18__FromUintOverflow(uint256 x);\\n\\n/// @notice Emitted when multiplying the inputs overflows UD60x18.\\nerror PRBMathUD60x18__GmOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when the input is less than 1.\\nerror PRBMathUD60x18__LogInputTooSmall(uint256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows UD60x18.\\nerror PRBMathUD60x18__SqrtOverflow(uint256 x);\\n\\n/// @notice Emitted when subtraction underflows UD60x18.\\nerror PRBMathUD60x18__SubUnderflow(uint256 x, uint256 y);\\n\\n/// @dev Common mathematical functions used in both PRBMathSD59x18 and PRBMathUD60x18. Note that this shared library\\n/// does not always assume the signed 59.18-decimal fixed-point or the unsigned 60.18-decimal fixed-point\\n/// representation. When it does not, it is explicitly mentioned in the NatSpec documentation.\\nlibrary PRBMath {\\n /// STRUCTS ///\\n\\n struct SD59x18 {\\n int256 value;\\n }\\n\\n struct UD60x18 {\\n uint256 value;\\n }\\n\\n /// STORAGE ///\\n\\n /// @dev How many trailing decimals can be represented.\\n uint256 internal constant SCALE = 1e18;\\n\\n /// @dev Largest power of two divisor of SCALE.\\n uint256 internal constant SCALE_LPOTD = 262144;\\n\\n /// @dev SCALE inverted mod 2^256.\\n uint256 internal constant SCALE_INVERSE =\\n 78156646155174841979727994598816262306175212592076161876661_508869554232690281;\\n\\n /// FUNCTIONS ///\\n\\n /// @notice Calculates the binary exponent of x using the binary fraction method.\\n /// @dev Has to use 192.64-bit fixed-point numbers.\\n /// See https://ethereum.stackexchange.com/a/96594/24693.\\n /// @param x The exponent as an unsigned 192.64-bit fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp2(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n // Start from 0.5 in the 192.64-bit fixed-point format.\\n result = 0x800000000000000000000000000000000000000000000000;\\n\\n // Multiply the result by root(2, 2^-i) when the bit at position i is 1. None of the intermediary results overflows\\n // because the initial result is 2^191 and all magic factors are less than 2^65.\\n if (x & 0x8000000000000000 > 0) {\\n result = (result * 0x16A09E667F3BCC909) >> 64;\\n }\\n if (x & 0x4000000000000000 > 0) {\\n result = (result * 0x1306FE0A31B7152DF) >> 64;\\n }\\n if (x & 0x2000000000000000 > 0) {\\n result = (result * 0x1172B83C7D517ADCE) >> 64;\\n }\\n if (x & 0x1000000000000000 > 0) {\\n result = (result * 0x10B5586CF9890F62A) >> 64;\\n }\\n if (x & 0x800000000000000 > 0) {\\n result = (result * 0x1059B0D31585743AE) >> 64;\\n }\\n if (x & 0x400000000000000 > 0) {\\n result = (result * 0x102C9A3E778060EE7) >> 64;\\n }\\n if (x & 0x200000000000000 > 0) {\\n result = (result * 0x10163DA9FB33356D8) >> 64;\\n }\\n if (x & 0x100000000000000 > 0) {\\n result = (result * 0x100B1AFA5ABCBED61) >> 64;\\n }\\n if (x & 0x80000000000000 > 0) {\\n result = (result * 0x10058C86DA1C09EA2) >> 64;\\n }\\n if (x & 0x40000000000000 > 0) {\\n result = (result * 0x1002C605E2E8CEC50) >> 64;\\n }\\n if (x & 0x20000000000000 > 0) {\\n result = (result * 0x100162F3904051FA1) >> 64;\\n }\\n if (x & 0x10000000000000 > 0) {\\n result = (result * 0x1000B175EFFDC76BA) >> 64;\\n }\\n if (x & 0x8000000000000 > 0) {\\n result = (result * 0x100058BA01FB9F96D) >> 64;\\n }\\n if (x & 0x4000000000000 > 0) {\\n result = (result * 0x10002C5CC37DA9492) >> 64;\\n }\\n if (x & 0x2000000000000 > 0) {\\n result = (result * 0x1000162E525EE0547) >> 64;\\n }\\n if (x & 0x1000000000000 > 0) {\\n result = (result * 0x10000B17255775C04) >> 64;\\n }\\n if (x & 0x800000000000 > 0) {\\n result = (result * 0x1000058B91B5BC9AE) >> 64;\\n }\\n if (x & 0x400000000000 > 0) {\\n result = (result * 0x100002C5C89D5EC6D) >> 64;\\n }\\n if (x & 0x200000000000 > 0) {\\n result = (result * 0x10000162E43F4F831) >> 64;\\n }\\n if (x & 0x100000000000 > 0) {\\n result = (result * 0x100000B1721BCFC9A) >> 64;\\n }\\n if (x & 0x80000000000 > 0) {\\n result = (result * 0x10000058B90CF1E6E) >> 64;\\n }\\n if (x & 0x40000000000 > 0) {\\n result = (result * 0x1000002C5C863B73F) >> 64;\\n }\\n if (x & 0x20000000000 > 0) {\\n result = (result * 0x100000162E430E5A2) >> 64;\\n }\\n if (x & 0x10000000000 > 0) {\\n result = (result * 0x1000000B172183551) >> 64;\\n }\\n if (x & 0x8000000000 > 0) {\\n result = (result * 0x100000058B90C0B49) >> 64;\\n }\\n if (x & 0x4000000000 > 0) {\\n result = (result * 0x10000002C5C8601CC) >> 64;\\n }\\n if (x & 0x2000000000 > 0) {\\n result = (result * 0x1000000162E42FFF0) >> 64;\\n }\\n if (x & 0x1000000000 > 0) {\\n result = (result * 0x10000000B17217FBB) >> 64;\\n }\\n if (x & 0x800000000 > 0) {\\n result = (result * 0x1000000058B90BFCE) >> 64;\\n }\\n if (x & 0x400000000 > 0) {\\n result = (result * 0x100000002C5C85FE3) >> 64;\\n }\\n if (x & 0x200000000 > 0) {\\n result = (result * 0x10000000162E42FF1) >> 64;\\n }\\n if (x & 0x100000000 > 0) {\\n result = (result * 0x100000000B17217F8) >> 64;\\n }\\n if (x & 0x80000000 > 0) {\\n result = (result * 0x10000000058B90BFC) >> 64;\\n }\\n if (x & 0x40000000 > 0) {\\n result = (result * 0x1000000002C5C85FE) >> 64;\\n }\\n if (x & 0x20000000 > 0) {\\n result = (result * 0x100000000162E42FF) >> 64;\\n }\\n if (x & 0x10000000 > 0) {\\n result = (result * 0x1000000000B17217F) >> 64;\\n }\\n if (x & 0x8000000 > 0) {\\n result = (result * 0x100000000058B90C0) >> 64;\\n }\\n if (x & 0x4000000 > 0) {\\n result = (result * 0x10000000002C5C860) >> 64;\\n }\\n if (x & 0x2000000 > 0) {\\n result = (result * 0x1000000000162E430) >> 64;\\n }\\n if (x & 0x1000000 > 0) {\\n result = (result * 0x10000000000B17218) >> 64;\\n }\\n if (x & 0x800000 > 0) {\\n result = (result * 0x1000000000058B90C) >> 64;\\n }\\n if (x & 0x400000 > 0) {\\n result = (result * 0x100000000002C5C86) >> 64;\\n }\\n if (x & 0x200000 > 0) {\\n result = (result * 0x10000000000162E43) >> 64;\\n }\\n if (x & 0x100000 > 0) {\\n result = (result * 0x100000000000B1721) >> 64;\\n }\\n if (x & 0x80000 > 0) {\\n result = (result * 0x10000000000058B91) >> 64;\\n }\\n if (x & 0x40000 > 0) {\\n result = (result * 0x1000000000002C5C8) >> 64;\\n }\\n if (x & 0x20000 > 0) {\\n result = (result * 0x100000000000162E4) >> 64;\\n }\\n if (x & 0x10000 > 0) {\\n result = (result * 0x1000000000000B172) >> 64;\\n }\\n if (x & 0x8000 > 0) {\\n result = (result * 0x100000000000058B9) >> 64;\\n }\\n if (x & 0x4000 > 0) {\\n result = (result * 0x10000000000002C5D) >> 64;\\n }\\n if (x & 0x2000 > 0) {\\n result = (result * 0x1000000000000162E) >> 64;\\n }\\n if (x & 0x1000 > 0) {\\n result = (result * 0x10000000000000B17) >> 64;\\n }\\n if (x & 0x800 > 0) {\\n result = (result * 0x1000000000000058C) >> 64;\\n }\\n if (x & 0x400 > 0) {\\n result = (result * 0x100000000000002C6) >> 64;\\n }\\n if (x & 0x200 > 0) {\\n result = (result * 0x10000000000000163) >> 64;\\n }\\n if (x & 0x100 > 0) {\\n result = (result * 0x100000000000000B1) >> 64;\\n }\\n if (x & 0x80 > 0) {\\n result = (result * 0x10000000000000059) >> 64;\\n }\\n if (x & 0x40 > 0) {\\n result = (result * 0x1000000000000002C) >> 64;\\n }\\n if (x & 0x20 > 0) {\\n result = (result * 0x10000000000000016) >> 64;\\n }\\n if (x & 0x10 > 0) {\\n result = (result * 0x1000000000000000B) >> 64;\\n }\\n if (x & 0x8 > 0) {\\n result = (result * 0x10000000000000006) >> 64;\\n }\\n if (x & 0x4 > 0) {\\n result = (result * 0x10000000000000003) >> 64;\\n }\\n if (x & 0x2 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n if (x & 0x1 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n\\n // We're doing two things at the same time:\\n //\\n // 1. Multiply the result by 2^n + 1, where \\\"2^n\\\" is the integer part and the one is added to account for\\n // the fact that we initially set the result to 0.5. This is accomplished by subtracting from 191\\n // rather than 192.\\n // 2. Convert the result to the unsigned 60.18-decimal fixed-point format.\\n //\\n // This works because 2^(191-ip) = 2^ip / 2^191, where \\\"ip\\\" is the integer part \\\"2^n\\\".\\n result *= SCALE;\\n result >>= (191 - (x >> 64));\\n }\\n }\\n\\n /// @notice Finds the zero-based index of the first one in the binary representation of x.\\n /// @dev See the note on msb in the \\\"Find First Set\\\" Wikipedia article https://en.wikipedia.org/wiki/Find_first_set\\n /// @param x The uint256 number for which to find the index of the most significant bit.\\n /// @return msb The index of the most significant bit as an uint256.\\n function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\\n if (x >= 2**128) {\\n x >>= 128;\\n msb += 128;\\n }\\n if (x >= 2**64) {\\n x >>= 64;\\n msb += 64;\\n }\\n if (x >= 2**32) {\\n x >>= 32;\\n msb += 32;\\n }\\n if (x >= 2**16) {\\n x >>= 16;\\n msb += 16;\\n }\\n if (x >= 2**8) {\\n x >>= 8;\\n msb += 8;\\n }\\n if (x >= 2**4) {\\n x >>= 4;\\n msb += 4;\\n }\\n if (x >= 2**2) {\\n x >>= 2;\\n msb += 2;\\n }\\n if (x >= 2**1) {\\n // No need to shift x any more.\\n msb += 1;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.\\n ///\\n /// Requirements:\\n /// - The denominator cannot be zero.\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The multiplicand as an uint256.\\n /// @param y The multiplier as an uint256.\\n /// @param denominator The divisor as an uint256.\\n /// @return result The result as an uint256.\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n unchecked {\\n result = prod0 / denominator;\\n }\\n return result;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n if (prod1 >= denominator) {\\n revert PRBMath__MulDivOverflow(prod1, denominator);\\n }\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n unchecked {\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 lpotdod = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by lpotdod.\\n denominator := div(denominator, lpotdod)\\n\\n // Divide [prod1 prod0] by lpotdod.\\n prod0 := div(prod0, lpotdod)\\n\\n // Flip lpotdod such that it is 2^256 / lpotdod. If lpotdod is zero, then it becomes one.\\n lpotdod := add(div(sub(0, lpotdod), lpotdod), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * lpotdod;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f71e18) with full precision.\\n ///\\n /// @dev Variant of \\\"mulDiv\\\" with constant folding, i.e. in which the denominator is always 1e18. Before returning the\\n /// final result, we add 1 if (x * y) % SCALE >= HALF_SCALE. Without this, 6.6e-19 would be truncated to 0 instead of\\n /// being rounded to 1e-18. See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717.\\n ///\\n /// Requirements:\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - The body is purposely left uncommented; see the NatSpec comments in \\\"PRBMath.mulDiv\\\" to understand how this works.\\n /// - It is assumed that the result can never be type(uint256).max when x and y solve the following two equations:\\n /// 1. x * y = type(uint256).max * SCALE\\n /// 2. (x * y) % SCALE >= SCALE / 2\\n ///\\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function mulDivFixedPoint(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n uint256 prod0;\\n uint256 prod1;\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n if (prod1 >= SCALE) {\\n revert PRBMath__MulDivFixedPointOverflow(prod1);\\n }\\n\\n uint256 remainder;\\n uint256 roundUpUnit;\\n assembly {\\n remainder := mulmod(x, y, SCALE)\\n roundUpUnit := gt(remainder, 499999999999999999)\\n }\\n\\n if (prod1 == 0) {\\n unchecked {\\n result = (prod0 / SCALE) + roundUpUnit;\\n return result;\\n }\\n }\\n\\n assembly {\\n result := add(\\n mul(\\n or(\\n div(sub(prod0, remainder), SCALE_LPOTD),\\n mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, SCALE_LPOTD), SCALE_LPOTD), 1))\\n ),\\n SCALE_INVERSE\\n ),\\n roundUpUnit\\n )\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev An extension of \\\"mulDiv\\\" for signed numbers. Works by computing the signs and the absolute values separately.\\n ///\\n /// Requirements:\\n /// - None of the inputs can be type(int256).min.\\n /// - The result must fit within int256.\\n ///\\n /// @param x The multiplicand as an int256.\\n /// @param y The multiplier as an int256.\\n /// @param denominator The divisor as an int256.\\n /// @return result The result as an int256.\\n function mulDivSigned(\\n int256 x,\\n int256 y,\\n int256 denominator\\n ) internal pure returns (int256 result) {\\n if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {\\n revert PRBMath__MulDivSignedInputTooSmall();\\n }\\n\\n // Get hold of the absolute values of x, y and the denominator.\\n uint256 ax;\\n uint256 ay;\\n uint256 ad;\\n unchecked {\\n ax = x < 0 ? uint256(-x) : uint256(x);\\n ay = y < 0 ? uint256(-y) : uint256(y);\\n ad = denominator < 0 ? uint256(-denominator) : uint256(denominator);\\n }\\n\\n // Compute the absolute value of (x*y)\\u00f7denominator. The result must fit within int256.\\n uint256 rAbs = mulDiv(ax, ay, ad);\\n if (rAbs > uint256(type(int256).max)) {\\n revert PRBMath__MulDivSignedOverflow(rAbs);\\n }\\n\\n // Get the signs of x, y and the denominator.\\n uint256 sx;\\n uint256 sy;\\n uint256 sd;\\n assembly {\\n sx := sgt(x, sub(0, 1))\\n sy := sgt(y, sub(0, 1))\\n sd := sgt(denominator, sub(0, 1))\\n }\\n\\n // XOR over sx, sy and sd. This is checking whether there are one or three negative signs in the inputs.\\n // If yes, the result should be negative.\\n result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs);\\n }\\n\\n /// @notice Calculates the square root of x, rounding down.\\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The uint256 number for which to calculate the square root.\\n /// @return result The result as an uint256.\\n function sqrt(uint256 x) internal pure returns (uint256 result) {\\n if (x == 0) {\\n return 0;\\n }\\n\\n // Set the initial guess to the closest power of two that is higher than x.\\n uint256 xAux = uint256(x);\\n result = 1;\\n if (xAux >= 0x100000000000000000000000000000000) {\\n xAux >>= 128;\\n result <<= 64;\\n }\\n if (xAux >= 0x10000000000000000) {\\n xAux >>= 64;\\n result <<= 32;\\n }\\n if (xAux >= 0x100000000) {\\n xAux >>= 32;\\n result <<= 16;\\n }\\n if (xAux >= 0x10000) {\\n xAux >>= 16;\\n result <<= 8;\\n }\\n if (xAux >= 0x100) {\\n xAux >>= 8;\\n result <<= 4;\\n }\\n if (xAux >= 0x10) {\\n xAux >>= 4;\\n result <<= 2;\\n }\\n if (xAux >= 0x8) {\\n result <<= 1;\\n }\\n\\n // The operations can never overflow because the result is max 2^127 when it enters this block.\\n unchecked {\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1; // Seven iterations should be enough\\n uint256 roundedDownResult = x / result;\\n return result >= roundedDownResult ? roundedDownResult : result;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x62cbabae4910e168e99b9c2c3e3b5c9c7ad5e7abd961dcc63b7ea3d83d8ea87e\",\"license\":\"Unlicense\"}},\"version\":1}", "bytecode": "0x6101e060405263017d78406002553480156200001a57600080fd5b5060405162005c9538038062005c958339810160408190526200003d916200020a565b61eeee6080819052601260a0819052600160c08190526001600160a01b038a1660e0528a818b8b8b8b8b8b8b6200007433620000cf565b6101a08990526101c08890526001600160a01b0380871661010052858116610120528481166101405283811661016052821661018052620000b5816200011f565b5050505050505050505050505050505050505050620002bf565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000546001600160a01b031633146200017f5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064015b60405180910390fd5b6001600160a01b038116620001e65760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840162000176565b620001f181620000cf565b50565b6001600160a01b0381168114620001f157600080fd5b600080600080600080600080610100898b0312156200022857600080fd5b8851975060208901516200023c81620001f4565b60408a01519097506200024f81620001f4565b60608a01519096506200026281620001f4565b60808a01519095506200027581620001f4565b60a08a01519094506200028881620001f4565b60c08a01519093506200029b81620001f4565b60e08a0151909250620002ae81620001f4565b809150509295985092959890939650565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c05161575e62000537600039600081816103cf01526120f301526000818161030701526119980152600081816104f701528181610c20015281816113da0152818161196601528181611fa101528181612605015281816126ea01528181612a3101528181612b4a01528181613bbf0152613f76015260008181610656015261155f0152600081816102bb01526132e001526000818161060f015281816108590152818161092d0152818161160401528181611a490152818161242901528181612c150152818161318e0152613ce00152600081816104a501528181610adb01528181610fc80152818161130f0152818161204d01526127a001526000818161056b01528181611e3501528181611ed10152818161225b01526122f70152600081816102660152818161070e015281816114aa0152818161150c0152818161194001528181611bea01528181612d7b0152612e3a01526000818161033b015281816105db0152818161144b01528181611477015281816114d7015281816115390152818161191a01528181611bc401528181612d5501528181612e140152613a5c0152600081816106cc01528181610762015281816109b701528181610b7301528181610ca101528181610d1401528181611696015281816118e501528181611b8f01528181611caa015281816123fe0152818161249c0152818161254801528181612d1f01528181612ddf01528181612ebc0152818161316101528181613a2701528181613ad101528181613d0d01528181613e7901528181613eb7015281816140400152614084015261575e6000f3fe6080604052600436106101f95760003560e01c80638da5cb5b1161010d578063c715967a116100a0578063df21a7dd1161006f578063df21a7dd146106ae578063e5a6b10f146106fc578063f2fde38b14610730578063fc0c546a14610750578063fe663f0f1461078457600080fd5b8063c715967a14610631578063d3419bf314610644578063d6dacc5314610678578063ddca3f431461069857600080fd5b8063ad007d63116100dc578063ad007d6314610559578063b631b5001461058d578063b7bad1b1146105bd578063c41c2f24146105fd57600080fd5b80638da5cb5b146104c7578063975057e7146104e5578063a02f801c14610519578063a32e1e961461053957600080fd5b80634a4305c011610190578063715018a61161015f578063715018a6146104115780637258002c1461042657806389701db5146104465780638af56094146104665780638b79543c1461049357600080fd5b80634a4305c01461037d578063637913ac1461039d57806366248b86146103bd57806369fe0e2d146103f157600080fd5b80632bdfe004116101cc5780632bdfe004146102a95780632d1a5903146102f5578063313ce56714610329578063405b84fa1461035d57600080fd5b806301ffc9a7146101fe5780630cf8e858146102335780631982d679146102485780631ebc263f14610296575b600080fd5b34801561020a57600080fd5b5061021e61021936600461438e565b6107a4565b60405190151581526020015b60405180910390f35b610246610241366004614415565b61083b565b005b34801561025457600080fd5b506102886102633660046144aa565b507f000000000000000000000000000000000000000000000000000000000000000090565b60405190815260200161022a565b6102886102a43660046144d5565b610904565b3480156102b557600080fd5b506102dd7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161022a565b34801561030157600080fd5b506102887f000000000000000000000000000000000000000000000000000000000000000081565b34801561033557600080fd5b506102887f000000000000000000000000000000000000000000000000000000000000000081565b34801561036957600080fd5b5061028861037836600461459c565b610ac2565b34801561038957600080fd5b506102886103983660046145cc565b610dbe565b3480156103a957600080fd5b506102466103b83660046144aa565b610dda565b3480156103c957600080fd5b506102887f000000000000000000000000000000000000000000000000000000000000000081565b3480156103fd57600080fd5b5061024661040c366004614635565b610e61565b34801561041d57600080fd5b50610246610ef0565b34801561043257600080fd5b5061024661044136600461464e565b610f26565b34801561045257600080fd5b50610246610461366004614635565b610fb2565b34801561047257600080fd5b50610486610481366004614635565b611249565b60405161022a919061467c565b34801561049f57600080fd5b506102dd7f000000000000000000000000000000000000000000000000000000000000000081565b3480156104d357600080fd5b506000546001600160a01b03166102dd565b3480156104f157600080fd5b506102dd7f000000000000000000000000000000000000000000000000000000000000000081565b34801561052557600080fd5b50610288610534366004614822565b6112f6565b34801561054557600080fd5b50610288610554366004614635565b6113b1565b34801561056557600080fd5b506102dd7f000000000000000000000000000000000000000000000000000000000000000081565b34801561059957600080fd5b5061021e6105a83660046144aa565b60046020526000908152604090205460ff1681565b3480156105c957600080fd5b506102886105d83660046144aa565b507f000000000000000000000000000000000000000000000000000000000000000090565b34801561060957600080fd5b506102dd7f000000000000000000000000000000000000000000000000000000000000000081565b61024661063f3660046148da565b6115e6565b34801561065057600080fd5b506102dd7f000000000000000000000000000000000000000000000000000000000000000081565b34801561068457600080fd5b506003546102dd906001600160a01b031681565b3480156106a457600080fd5b5061028860025481565b3480156106ba57600080fd5b5061021e6106c9366004614981565b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161490565b34801561070857600080fd5b506102887f000000000000000000000000000000000000000000000000000000000000000081565b34801561073c57600080fd5b5061024661074b3660046144aa565b611788565b34801561075c57600080fd5b506102dd7f000000000000000000000000000000000000000000000000000000000000000081565b34801561079057600080fd5b5061028861079f3660046149ad565b611823565b60006001600160e01b0319821663edb527eb60e01b14806107d557506001600160e01b031982166301290c1760e61b145b806107f057506001600160e01b0319821663280be00760e21b145b8061080b57506001600160e01b0319821663fe663f0f60e01b145b8061082657506001600160e01b0319821663ad007d6360e01b145b80610835575061083582611843565b92915050565b604051636e49181f60e01b81526004810188905230602482015287907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636e49181f90604401602060405180830381865afa1580156108a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108cc9190614a65565b6108e957604051631b1d5a5960e31b815260040160405180910390fd5b6108fa8888886000898989896115e6565b5050505050505050565b604051636e49181f60e01b8152600481018b90523060248201526000908b906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636e49181f90604401602060405180830381865afa158015610974573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109989190614a65565b6109b557604051631b1d5a5960e31b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661eeee14610a24573415610a0657604051635e7e9adf60e11b815260040160405180910390fd5b47610a1233308e611893565b610a1c8147614a98565b9b5050610a28565b349a505b610ab28b338e8c8c8c8c8c8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506118a292505050565b9c9b505050505050505050505050565b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610b2a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b4e9190614aab565b836004610b5c838383611e0a565b60405163df21a7dd60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301526024820188905286169063df21a7dd90604401602060405180830381865afa158015610bc9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bed9190614a65565b610c0a5760405163581010ed60e01b815260040160405180910390fd5b604051636bb6a5ad60e01b8152600481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636bb6a5ad906024016020604051808303816000875af1158015610c71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c959190614ac8565b93508315610d705760007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661eeee14610cd8576000610cda565b845b6040805160208101825260008152905163019f1d0b60e31b81529192506001600160a01b03881691630cf8e858918491610d3c918c918b917f000000000000000000000000000000000000000000000000000000000000000091600401614b31565b6000604051808303818588803b158015610d5557600080fd5b505af1158015610d69573d6000803e3d6000fd5b5050505050505b604080518581523360208201526001600160a01b0387169188917fa7519e5f94697b7f53e97c5eb46a0c730a296ab686ab8fd333835c5f735784eb910160405180910390a350505092915050565b6000610dce888888878787611f6e565b98975050505050505050565b6000546001600160a01b03163314610e0d5760405162461bcd60e51b8152600401610e0490614b6c565b60405180910390fd5b600380546001600160a01b0319166001600160a01b0383169081179091556040513381527f0a9a80fe9716605b3e52abb3d792d6a4e7816d6afc02a5a4ef023081feaf9f609060200160405180910390a250565b6000546001600160a01b03163314610e8b5760405162461bcd60e51b8152600401610e0490614b6c565b6302faf080811115610eb0576040516345fbd9c160e01b815260040160405180910390fd5b6002819055604080518281523360208201527fd7414e590e1cb532989ab2a34c8f4c2c17f7ab6f006efeeaef2e87cd5008c202910160405180910390a150565b6000546001600160a01b03163314610f1a5760405162461bcd60e51b8152600401610e0490614b6c565b610f2460006121d6565b565b6000546001600160a01b03163314610f505760405162461bcd60e51b8152600401610e0490614b6c565b6001600160a01b038216600081815260046020908152604091829020805460ff191685151590811790915591513381529192917fa2653e25a502c023a5830d0de847ef6f458387865b1f4f575d7594f9f2c0d71e910160405180910390a35050565b6040516331a9108f60e11b8152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015611017573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061103b9190614aab565b8160056110506000546001600160a01b031690565b6001600160a01b0316336001600160a01b03161461107084848484612226565b600085815260016020908152604080832080548251818502810185019093528083529192909190849084015b8282101561110957600084815260209081902060408051608081018252600286029092018054835260019081015463ffffffff8082168587015264010000000082041692840192909252600160401b9091046001600160a01b03166060830152908352909201910161109c565b50505060008881526001602052604081209293506111289291506142ed565b805160005b818110156108fa5760006111a584838151811061114c5761114c614ba1565b60200260200101516000015185848151811061116a5761116a614ba1565b60200260200101516020015163ffffffff1686858151811061118e5761118e614ba1565b60200260200101516040015163ffffffff1661239a565b90506111cf818584815181106111bd576111bd614ba1565b6020026020010151606001518b6123e0565b60011515818a7fcf0c92a2c6d7c42f488326b0cb900104b99984b6b218db81cd29371364a3525187868151811061120857611208614ba1565b602002602001015160600151336040516112389291906001600160a01b0392831681529116602082015260400190565b60405180910390a45060010161112d565b606060016000838152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b828210156112eb57600084815260209081902060408051608081018252600286029092018054835260019081015463ffffffff8082168587015264010000000082041692840192909252600160401b9091046001600160a01b03166060830152908352909201910161127e565b505050509050919050565b6040516331a9108f60e11b8152600481018a90526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa15801561135e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113829190614aab565b8a6011611390838383611e0a565b6113a08d8d8d8c8c8c8c8c6126b7565b9d9c50505050505050505050505050565b60405163035240c760e61b81523060048201526024810182905260009081906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063d49031c090604401602060405180830381865afa158015611421573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114459190614ac8565b905060007f00000000000000000000000000000000000000000000000000000000000000006012146114a25761149d827f000000000000000000000000000000000000000000000000000000000000000060126128e3565b6114a4565b815b905060017f0000000000000000000000000000000000000000000000000000000000000000146115dc576115d7816114fd7f0000000000000000000000000000000000000000000000000000000000000000600a614c9b565b604051635268657960e11b81527f00000000000000000000000000000000000000000000000000000000000000006004820152600160248201527f000000000000000000000000000000000000000000000000000000000000000060448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a4d0caf290606401602060405180830381865afa1580156115ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115d29190614ac8565b612940565b6115de565b805b949350505050565b604051636e49181f60e01b81526004810189905230602482015288907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636e49181f90604401602060405180830381865afa158015611653573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116779190614a65565b61169457604051631b1d5a5960e31b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661eeee146117035734156116e557604051635e7e9adf60e11b815260040160405180910390fd5b476116f133308b611893565b6116fb8147614a98565b985050611707565b3497505b61177d89898888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8c018190048102820181019092528a815292508a9150899081908401838280828437600092019190915250612a0d92505050565b505050505050505050565b6000546001600160a01b031633146117b25760405162461bcd60e51b8152600401610e0490614b6c565b6001600160a01b0381166118175760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610e04565b611820816121d6565b50565b600088886002611834838383611e0a565b610ab28c8c8c8b8b8b8b612aff565b60006001600160e01b0319821663301cdc3960e21b148061187457506001600160e01b0319821663144b000160e11b145b8061083557506301ffc9a760e01b6001600160e01b0319831614610835565b61189d828261302a565b505050565b60006001600160a01b0386166118cb5760405163a762251360e01b815260040160405180910390fd5b6118d361430e565b606060008060405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020018e81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000000000000000000000000000000000000000000081525090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632fa1b3918d838e7f00000000000000000000000000000000000000000000000000000000000000008f8d8d6040518863ffffffff1660e01b81526004016119dc9796959493929190614cd3565b6000604051808303816000875af11580156119fb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611a239190810190614e37565b995091955090935091508115611b5857604051632eec7b5560e11b8152600481018c90527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635dd8f6aa90602401602060405180830381865afa158015611a98573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abc9190614aab565b604051638ae9c07b60e01b8152600481018d9052602481018490526001600160a01b038c8116604483015260c06064830152600060c48301528a15156084830152600160a48301529190911690638ae9c07b9060e4016020604051808303816000875af1158015611b31573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b559190614ac8565b94505b88851015611b7957604051633dca309360e11b815260040160405180910390fd5b825115611dac57600060405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020018f81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f0000000000000000000000000000000000000000000000000000000000000000815250905060006040518061014001604052808f6001600160a01b031681526020018e8152602001876020015181526020018481526020018381526020018881526020018d6001600160a01b031681526020018b151581526020018a815260200189815250905060008551905060005b81811015611da7576000878281518110611c9557611c95614ba1565b60209081029190910101519050600061eeed197f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031601611cde575060208101515b602080830151608087015190910152815160405163da9ee8b760e01b81526001600160a01b039091169063da9ee8b7908390611d1e908990600401614fee565b6000604051808303818588803b158015611d3757600080fd5b505af1158015611d4b573d6000803e3d6000fd5b505050505081600001516001600160a01b03167f16112c26e14efc4be6c690149aa5a1ba75160de245f60d2273e28adb277b9e1286846020015133604051611d9593929190615001565b60405180910390a25050600101611c79565b505050505b50505087816000015182602001517f133161f1c9161488f777ab9a26aae91d47c0d9a3fafb398960f138db02c737978c8b8f888b8b33604051611df59796959493929190615034565b60405180910390a45098975050505050505050565b336001600160a01b03841614801590611eb3575060405163c161c93f60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c161c93f90611e70903390879087908790600401615094565b602060405180830381865afa158015611e8d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eb19190614a65565b155b8015611f50575060405163c161c93f60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c161c93f90611f0d90339087906000908790600401615094565b602060405180830381865afa158015611f2a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f4e9190614a65565b155b1561189d5760405163075fd2b160e01b815260040160405180910390fd5b60405163c664459760e01b8152600481018790526024810186905260448101859052600090819081906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c664459790606401610140604051808303816000875af1158015611feb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061200f91906150bd565b91509150858110156120345760405163b01493c160e01b815260040160405180910390fd5b6040516331a9108f60e11b8152600481018a90526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa15801561209c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120c09190614aab565b90506000806002546000146120dd576120d88c613143565b6120e3565b633b9aca005b90506000806121198e88602001517f000000000000000000000000000000000000000000000000000000000000000089876132af565b92509050633b9aca00831461212d57908101905b8160000361213c576000612149565b6121498e88848887613457565b935080156121755761215e816002548561239a565b6121689082614a98565b975061217530868a611893565b5050508a846000015185602001517fc41a8d26c70cfcf1b9ea10f82482ac947b8be5bea2750bc729af844bbfde1e28858e88878c8f8f336040516121c0989796959493929190615115565b60405180910390a4505050509695505050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b8015801561223d5750336001600160a01b03851614155b80156122d9575060405163c161c93f60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c161c93f90612296903390889088908890600401615094565b602060405180830381865afa1580156122b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122d79190614a65565b155b8015612376575060405163c161c93f60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c161c93f9061233390339088906000908890600401615094565b602060405180830381865afa158015612350573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123749190614a65565b155b156123945760405163075fd2b160e01b815260040160405180910390fd5b50505050565b6000806123ac8484633b9aca00612940565b6123b69085614a98565b90506123cb85633b9aca006115d28185615168565b6123d59086614a98565b9150505b9392505050565b604051630862026560e41b8152600160048201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660248301526000917f000000000000000000000000000000000000000000000000000000000000000090911690638620265090604401602060405180830381865afa158015612472573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124969190614aab565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661eeee146124d35760006124d5565b845b604080516020808252818301909252919250600091906020820181803683370190505090508360405160200161250d91815260200190565b60408051808303601f1901815290829052631ebc263f60e01b825291506001600160a01b03841690631ebc263f908490612579906001908b907f0000000000000000000000000000000000000000000000000000000000000000908c9060009081908b9060040161517b565b60206040518083038185885af1935050505080156125b4575060408051601f3d908101601f191682019092526125b191810190614ac8565b60015b6126ad573d8080156125e2576040519150601f19603f3d011682016040523d82523d6000602084013e6125e7565b606091505b5060405163e7c8e3e360e01b815260048101869052602481018890527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7c8e3e390604401600060405180830381600087803b15801561265157600080fd5b505af1158015612665573d6000803e3d6000fd5b505050506001857f80a889d08f0d59eb962335b57fb1d5b29e86e3d23f15087b5541fddf15422bbe89843360405161269f939291906151d3565b60405180910390a3506126af565b505b505050505050565b604051632538671560e01b8152600481018990526024810188905260448101879052600090819081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632538671590606401610140604051808303816000875af1158015612734573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061275891906150bd565b915091508781101561277d5760405163b01493c160e01b815260040160405180910390fd5b6040516331a9108f60e11b8152600481018c905260009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa1580156127e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061280b9190614aab565b905060006002546000148061282f57503360009081526004602052604090205460ff165b6128415761283c8e613143565b612847565b633b9aca005b9050633b9aca008114612866576128618e86868585613457565b612869565b60005b8085039650925083831461288257612882308b88611893565b5050508a826000015183602001517f2eeee47c6d8d31c3523c3aa07b4c3e3795db36be4c04546ef3e30a5102f568e18a8e86898d8d8d336040516128cd989796959493929190615204565b60405180910390a4505098975050505050505050565b60008282036128f35750826123d9565b82821115612921576129058383614a98565b61291090600a614c9b565b61291a9085615264565b90506123d9565b61292b8284614a98565b61293690600a614c9b565b61291a9085615299565b600080806000198587098587029250828110838203039150508060000361297a5783828161297057612970615283565b04925050506123d9565b8381106129a457604051631dcf306360e21b81526004810182905260248101859052604401610e04565b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b600083612a1b576000612a25565b612a2586866135e6565b90506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663e7c8e3e387612a618489615168565b6040516001600160e01b031960e085901b16815260048101929092526024820152604401600060405180830381600087803b158015612a9f57600080fd5b505af1158015612ab3573d6000803e3d6000fd5b50505050857f9ecaf7fc3dfffd6867c175d6e684b1f1e3aef019398ba8db2c1ffab4a09db2538683868633604051612aef9594939291906152bb565b60405180910390a2505050505050565b60006001600160a01b038416612b2857604051637ba50db360e11b815260040160405180910390fd5b612b3061430e565b60405163a2df1f9560e01b81526060906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a2df1f9590612b87908d908d908d908b908b90600401615307565b6000604051808303816000875af1158015612ba6573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612bce9190810190615346565b9750909450909250905086831015612bf95760405163f896960b60e01b815260040160405180910390fd5b8715612d0957604051632eec7b5560e11b8152600481018a90527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635dd8f6aa90602401602060405180830381865afa158015612c64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c889190614aab565b604051631665bc0f60e01b81526001600160a01b038c81166004830152602482018c9052604482018b905260a06064830152600060a4830181905260848301529190911690631665bc0f9060c401600060405180830381600087803b158015612cf057600080fd5b505af1158015612d04573d6000803e3d6000fd5b505050505b805115612fbe57600060405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602001600081526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f0000000000000000000000000000000000000000000000000000000000000000815250905060006040518061012001604052808d6001600160a01b031681526020018c8152602001856020015181526020018b815260200160405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020018881526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000008152508152602001838152602001896001600160a01b0316815260200188815260200187815250905060008351905060005b81811015612fb9576000858281518110612ea757612ea7614ba1565b60209081029190910101519050600061eeed197f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031601612ef0575060208101515b60208083015160a0870151909101528151604051632b13c58f60e01b81526001600160a01b0390911690632b13c58f908390612f309089906004016154bd565b6000604051808303818588803b158015612f4957600080fd5b505af1158015612f5d573d6000803e3d6000fd5b505050505081600001516001600160a01b03167f54b3744c489f40987dd2726ca12131243334e8292f567389f761c5a432d813e486846020015133604051612fa7939291906154d0565b60405180910390a25050600101612e8b565b505050505b508115612fd057612fd0308684611893565b87816000015182602001517f2be10f2a0203c77d0fcaa9fd6484a8a1d6904de31cd820587f60c1c8c338c8148c898c888b8b336040516130169796959493929190615034565b60405180910390a450979650505050505050565b8047101561307a5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401610e04565b6000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146130c7576040519150601f19603f3d011682016040523d82523d6000602084013e6130cc565b606091505b505090508061189d5760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401610e04565b604051630862026560e41b8152600160048201526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116602483015260009182917f00000000000000000000000000000000000000000000000000000000000000001690638620265090604401602060405180830381865afa1580156131d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131f99190614aab565b6001600160a01b0316036132125750633b9aca00919050565b6003546001600160a01b0316156132a757600354604051633bb4ac4b60e11b8152600481018490526001600160a01b0390911690637769589690602401602060405180830381865afa925050508015613288575060408051601f3d908101601f1916820190925261328591810190614ac8565b60015b61329457506000919050565b633b9aca0081116132a55792915050565b505b506000919050565b6040516369e11cc560e01b81526004810186905260248101859052604481018490528290600090633b9aca009082907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906369e11cc590606401600060405180830381865afa15801561332f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261335791908101906154e3565b905060005b815181101561344a57600082828151811061337957613379614ba1565b602002602001015190506000848260400151146133a8576133a3898360400151633b9aca00612940565b6133aa565b865b90508160400151856133bc9190614a98565b945060006133cd838e8d858d6139b6565b905080158015906133de5750818114155b156133f0576133ed8288615168565b96505b81156133fc5781880397505b8a8c8e7f0d31ab573f6daa4b1edba8d31973b4ba9f98fbfecc47010c1533eeefd2a1225a868686336040516134349493929190615640565b60405180910390a483600101935050505061335c565b5050509550959350505050565b6000613466846002548461239a565b610100860151909150604f1c60019081160361358957600086815260016020818152604080842081516080810183528981526002805463ffffffff9081168387019081528a82168487019081526001600160a01b03808e16606087019081528754808c018955978c5298909a2094519584029094019485555193909601805492519551909716600160401b02600160401b600160e01b03199587166401000000000267ffffffffffffffff19909316939096169290921717929092169290921790925590549051859088907f77813be0661650ddc1a5193ff2837df4162b251cb432651e2c060c3fc39756be9061357c908790899033909283526001600160a01b03918216602084015216604082015260600190565b60405180910390a46135dd565b6135948184886123e0565b604080516001600160a01b0385168152336020820152600091839189917fcf0c92a2c6d7c42f488326b0cb900104b99984b6b218db81cd29371364a35251910160405180910390a45b95945050505050565b600082815260016020908152604080832080548251818502810185019093528083528493849084015b8282101561367c57600084815260209081902060408051608081018252600286029092018054835260019081015463ffffffff8082168587015264010000000082041692840192909252600160401b9091046001600160a01b03166060830152908352909201910161360f565b505050600086815260016020526040812092935061369b9291506142ed565b8051839060005b8181101561396e578260000361376157600087815260016020526040902084518590839081106136d4576136d4614ba1565b60209081029190910181015182546001818101855560009485529383902082516002909202019081559181015191909201805460408401516060909401516001600160a01b0316600160401b02600160401b600160e01b031963ffffffff9586166401000000000267ffffffffffffffff1990931695909416949094171791909116919091179055613966565b83818151811061377357613773614ba1565b60200260200101516000015183106138075783818151811061379757613797614ba1565b602002602001015160000151830392506137fe8482815181106137bc576137bc614ba1565b6020026020010151600001518583815181106137da576137da614ba1565b60200260200101516020015163ffffffff1686848151811061118e5761118e614ba1565b85019450613966565b6001600088815260200190815260200160002060405180608001604052808587858151811061383857613838614ba1565b60200260200101516000015103815260200186848151811061385c5761385c614ba1565b60200260200101516020015163ffffffff16815260200186848151811061388557613885614ba1565b60200260200101516040015163ffffffff1681526020018684815181106138ae576138ae614ba1565b6020908102919091018101516060908101516001600160a01b0390811690935284546001818101875560009687529583902085516002909202019081559184015191909401805460408501519490950151909216600160401b02600160401b600160e01b031963ffffffff9485166401000000000267ffffffffffffffff1990961694909216939093179390931792909216179055835161395d9084908690849081106137da576137da614ba1565b85019450600092505b6001016136a2565b50604080518381523360208201528591879189917f59860d79d97c1fce2be7f987915c631471f4b08f671200463cc40a3380194ffb910160405180910390a450505092915050565b60c08501516000906001600160a01b031615613cb757633b9aca008214806139fa575060c08601516001600160a01b031660009081526004602052604090205460ff165b15613a06575081613a18565b613a13836002548461239a565b830390505b60006040518060c001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020018381526020017f0000000000000000000000000000000000000000000000000000000000000000815260200187815260200186815260200188815250905060006060613aab8960c00151634eba05fd60e11b6141b5565b15613b93578860c001516001600160a01b0316639d740bfa61eeee6001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614613b05576000613b07565b855b856040518363ffffffff1660e01b8152600401613b249190615675565b6000604051808303818588803b158015613b3d57600080fd5b505af193505050508015613b4f575060015b613b8e573d808015613b7d576040519150601f19603f3d011682016040523d82523d6000602084013e613b82565b606091505b50600192509050613b98565b613b98565b600291505b8115613caf5760405163e7c8e3e360e01b81526004810189905260248101879052600094507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7c8e3e390604401600060405180830381600087803b158015613c0b57600080fd5b505af1158015613c1f573d6000803e3d6000fd5b50505050877f290b5df59e172593762964e4f8ed2b4a9192d3197bfd2be4bae123908f8007968a8885600114613c9357604051602001613c7f906020808252600c908201526b12515490cc4d8d4819985a5b60a21b604082015260600190565b604051602081830303815290604052613c95565b845b33604051613ca694939291906156c9565b60405180910390a25b5050506135dd565b606086015115614158576060860151604051630862026560e41b81526000916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691638620265091613d47917f0000000000000000000000000000000000000000000000000000000000000000906004019182526001600160a01b0316602082015260400190565b602060405180830381865afa158015613d64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d889190614aab565b90506001600160a01b038116613db157604051636921234360e01b815260040160405180910390fd5b6001600160a01b038116301480613dcb5750633b9aca0083145b80613dee57506001600160a01b03811660009081526004602052604090205460ff165b15613dfb57839150613e0d565b613e08846002548561239a565b840391505b60408051602080825281830190925260009160208201818036833701905050905086604051602001613e4191815260200190565b604051602081830303815290604052905087602001511561402357816001600160a01b0316630cf8e85861eeee6001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614613ead576000613eaf565b845b8a60600151867f0000000000000000000000000000000000000000000000000000000000000000866040518663ffffffff1660e01b8152600401613ef69493929190614b31565b6000604051808303818588803b158015613f0f57600080fd5b505af193505050508015613f21575060015b61401e573d808015613f4f576040519150601f19603f3d011682016040523d82523d6000602084013e613f54565b606091505b5060405163e7c8e3e360e01b81526004810189905260248101879052600094507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7c8e3e390604401600060405180830381600087803b158015613fc257600080fd5b505af1158015613fd6573d6000803e3d6000fd5b50505050877f290b5df59e172593762964e4f8ed2b4a9192d3197bfd2be4bae123908f8007968a88843360405161401094939291906156c9565b60405180910390a250614151565b614151565b816001600160a01b0316631ebc263f61eeee6001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614614074576000614076565b845b60608b015160808c015187907f0000000000000000000000000000000000000000000000000000000000000000906001600160a01b03166140b757336140bd565b8d608001515b8e516040516001600160e01b031960e089901b1681526140e895949392916000918b9060040161517b565b60206040518083038185885af193505050508015614123575060408051601f3d908101601f1916820190925261412091810190614ac8565b60015b613caf573d808015613f4f576040519150601f19603f3d011682016040523d82523d6000602084013e613f54565b50506135dd565b60808601516000906001600160a01b03166141735733614179565b86608001515b9050633b9aca00830361418e578391506141a0565b61419b846002548561239a565b840391505b6141ab308284611893565b5095945050505050565b60006141c0836141d1565b80156123d957506123d98383614204565b60006141e4826301ffc9a760e01b614204565b801561083557506141fd826001600160e01b0319614204565b1592915050565b604080516001600160e01b0319831660248083019190915282518083039091018152604490910182526020810180516001600160e01b03166301ffc9a760e01b179052905160009190829081906001600160a01b038716906175309061426b90869061570c565b6000604051808303818686fa925050503d80600081146142a7576040519150601f19603f3d011682016040523d82523d6000602084013e6142ac565b606091505b50915091506020815110156142c75760009350505050610835565b8180156142e35750808060200190518101906142e39190614a65565b9695505050505050565b50805460008255600202906000526020600020908101906118209190614363565b6040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b5b8082111561438a57600081556001810180546001600160e01b0319169055600201614364565b5090565b6000602082840312156143a057600080fd5b81356001600160e01b0319811681146123d957600080fd5b6001600160a01b038116811461182057600080fd5b60008083601f8401126143df57600080fd5b5081356001600160401b038111156143f657600080fd5b60208301915083602082850101111561440e57600080fd5b9250929050565b600080600080600080600060a0888a03121561443057600080fd5b87359650602088013595506040880135614449816143b8565b945060608801356001600160401b038082111561446557600080fd5b6144718b838c016143cd565b909650945060808a013591508082111561448a57600080fd5b506144978a828b016143cd565b989b979a50959850939692959293505050565b6000602082840312156144bc57600080fd5b81356123d9816143b8565b801515811461182057600080fd5b6000806000806000806000806000806101008b8d0312156144f557600080fd5b8a35995060208b0135985060408b013561450e816143b8565b975060608b013561451e816143b8565b965060808b0135955060a08b0135614535816144c7565b945060c08b01356001600160401b038082111561455157600080fd5b61455d8e838f016143cd565b909650945060e08d013591508082111561457657600080fd5b506145838d828e016143cd565b915080935050809150509295989b9194979a5092959850565b600080604083850312156145af57600080fd5b8235915060208301356145c1816143b8565b809150509250929050565b600080600080600080600060c0888a0312156145e757600080fd5b8735965060208801359550604088013594506060880135614607816143b8565b93506080880135925060a08801356001600160401b0381111561462957600080fd5b6144978a828b016143cd565b60006020828403121561464757600080fd5b5035919050565b6000806040838503121561466157600080fd5b823561466c816143b8565b915060208301356145c1816144c7565b602080825282518282018190526000919060409081850190868401855b828110156146e5578151805185528681015163ffffffff908116888701528682015116868601526060908101516001600160a01b03169085015260809093019290850190600101614699565b5091979650505050505050565b634e487b7160e01b600052604160045260246000fd5b60405161012081016001600160401b038111828210171561472b5761472b6146f2565b60405290565b604080519081016001600160401b038111828210171561472b5761472b6146f2565b60405160e081016001600160401b038111828210171561472b5761472b6146f2565b604051601f8201601f191681016001600160401b038111828210171561479d5761479d6146f2565b604052919050565b60006001600160401b038211156147be576147be6146f2565b50601f01601f191660200190565b600082601f8301126147dd57600080fd5b81356147f06147eb826147a5565b614775565b81815284602083860101111561480557600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060008060006101008a8c03121561484157600080fd5b8935985060208a0135975060408a0135965060608a0135614861816143b8565b955060808a0135945060a08a0135614878816143b8565b935060c08a01356001600160401b038082111561489457600080fd5b6148a08d838e016147cc565b945060e08c01359150808211156148b657600080fd5b506148c38c828d016143cd565b915080935050809150509295985092959850929598565b60008060008060008060008060c0898b0312156148f657600080fd5b8835975060208901359650604089013561490f816143b8565b9550606089013561491f816144c7565b945060808901356001600160401b038082111561493b57600080fd5b6149478c838d016143cd565b909650945060a08b013591508082111561496057600080fd5b5061496d8b828c016143cd565b999c989b5096995094979396929594505050565b6000806040838503121561499457600080fd5b823561499f816143b8565b946020939093013593505050565b600080600080600080600080610100898b0312156149ca57600080fd5b88356149d5816143b8565b9750602089013596506040890135955060608901356149f3816143b8565b94506080890135935060a0890135614a0a816143b8565b925060c08901356001600160401b0380821115614a2657600080fd5b614a328c838d016147cc565b935060e08b0135915080821115614a4857600080fd5b50614a558b828c016147cc565b9150509295985092959890939650565b600060208284031215614a7757600080fd5b81516123d9816144c7565b634e487b7160e01b600052601160045260246000fd5b8181038181111561083557610835614a82565b600060208284031215614abd57600080fd5b81516123d9816143b8565b600060208284031215614ada57600080fd5b5051919050565b60005b83811015614afc578181015183820152602001614ae4565b50506000910152565b60008151808452614b1d816020860160208601614ae1565b601f01601f19169290920160200192915050565b84815283602082015260018060a01b038316604082015260a06060820152600060a082015260c0608082015260006142e360c0830184614b05565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b634e487b7160e01b600052603260045260246000fd5b600181815b80851115614bf2578160001904821115614bd857614bd8614a82565b80851615614be557918102915b93841c9390800290614bbc565b509250929050565b600082614c0957506001610835565b81614c1657506000610835565b8160018114614c2c5760028114614c3657614c52565b6001915050610835565b60ff841115614c4757614c47614a82565b50506001821b610835565b5060208310610133831016604e8410600b8410161715614c75575081810a610835565b614c7f8383614bb7565b8060001904821115614c9357614c93614a82565b029392505050565b60006123d98383614bfa565b80516001600160a01b031682526020808201519083015260408082015190830152606090810151910152565b6001600160a01b03888116825260009061014090614cf4602085018b614ca7565b8860a08501528760c085015280871660e08501525080610100840152614d1c81840186614b05565b9050828103610120840152614d318185614b05565b9a9950505050505050505050565b8051614d4a816143b8565b919050565b60006101208284031215614d6257600080fd5b614d6a614708565b9050815181526020820151602082015260408201516040820152606082015160608201526080820151608082015260a082015160a082015260c082015160c0820152614db860e08301614d3f565b60e082015261010080830151818301525092915050565b60006001600160401b03821115614de857614de86146f2565b5060051b60200190565b600082601f830112614e0357600080fd5b8151614e116147eb826147a5565b818152846020838601011115614e2657600080fd5b6115de826020830160208701614ae1565b6000806000806101808587031215614e4e57600080fd5b614e588686614d4f565b935061012085015192506101408501516001600160401b0380821115614e7d57600080fd5b818701915087601f830112614e9157600080fd5b81516020614ea16147eb83614dcf565b82815260069290921b8401810191818101908b841115614ec057600080fd5b948201945b83861015614f0c576040868d031215614ede5760008081fd5b614ee6614731565b8651614ef1816143b8565b81528684015184820152825260409095019490820190614ec5565b6101608b0151909750945050505080821115614f2757600080fd5b50614f3487828801614df2565b91505092959194509250565b80516001600160a01b03168252600061020060208301516020850152604083015160408501526060830151614f786060860182614ca7565b506080830151614f8b60e0860182614ca7565b5060a083015161016085015260c08301516001600160a01b031661018085015260e083015115156101a08501526101008301516101c08501829052614fd282860182614b05565b9150506101208301518482036101e08601526135dd8282614b05565b6020815260006123d96020830184614f40565b6060815260006150146060830186614f40565b6020830194909452506001600160a01b0391909116604090910152919050565b600060018060a01b03808a168352808916602084015287604084015286606084015260e0608084015261506a60e0840187614b05565b83810360a085015261507c8187614b05565b92505080841660c08401525098975050505050505050565b6001600160a01b0394851681529290931660208301526040820152606081019190915260800190565b60008061014083850312156150d157600080fd5b6150db8484614d4f565b915061012083015190509250929050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b600060018060a01b03808b16835289602084015288604084015287606084015286608084015260e060a084015261515060e0840186886150ec565b915080841660c0840152509998505050505050505050565b8082018082111561083557610835614a82565b878152602081018790526001600160a01b038681166040830152851660608201526080810184905282151560a082015261010060c08201819052600090820181905261012060e08301819052614d3181840185614b05565b8381526060602082015260006151ec6060830185614b05565b905060018060a01b0383166040830152949350505050565b600060018060a01b03808b16835289602084015288604084015287606084015260e0608084015261523860e0840188614b05565b83810360a085015261524b8187896150ec565b92505080841660c0840152509998505050505050505050565b600081600019048311821515161561527e5761527e614a82565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826152b657634e487b7160e01b600052601260045260246000fd5b500490565b85815284602082015260a0604082015260006152da60a0830186614b05565b82810360608401526152ec8186614b05565b91505060018060a01b03831660808301529695505050505050565b60018060a01b038616815284602082015283604082015260a06060820152600061533460a0830185614b05565b8281036080840152610dce8185614b05565b600080600080610180858703121561535d57600080fd5b6153678686614d4f565b935061012085015192506101408501516001600160401b038082111561538c57600080fd5b818701915087601f8301126153a057600080fd5b815160206153b06147eb83614dcf565b82815260069290921b8401810191818101908b8411156153cf57600080fd5b948201945b83861015614f0c576040868d0312156153ed5760008081fd5b6153f5614731565b8651615400816143b8565b815286840151848201528252604090950194908201906153d4565b80516001600160a01b0316825260006101e0602083015160208501526040830151604085015260608301516060850152608083015161545d6080860182614ca7565b5060a083015161010061547281870183614ca7565b60c08501516001600160a01b031661018087015260e08501516101a0870184905291506154a183870183614b05565b9250808501519150508482036101c08601526135dd8282614b05565b6020815260006123d9602083018461541b565b606081526000615014606083018661541b565b600060208083850312156154f657600080fd5b82516001600160401b0381111561550c57600080fd5b8301601f8101851361551d57600080fd5b805161552b6147eb82614dcf565b81815260e0918202830184019184820191908884111561554a57600080fd5b938501935b838510156155e05780858a0312156155675760008081fd5b61556f614753565b855161557a816144c7565b815285870151615589816144c7565b8188015260408681015190820152606080870151908201526080808701516155b0816143b8565b9082015260a0868101519082015260c0808701516155cd816143b8565b908201528352938401939185019161554f565b50979650505050505050565b80511515825260208082015115159083015260408082015190830152606080820151908301526080808201516001600160a01b039081169184019190915260a0808301519084015260c09182015116910152565b610140810161564f82876155ec565b60e08201949094526101008101929092526001600160a01b031661012090910152919050565b81516001600160a01b031681526020808301519082015260408083015190820152606080830151908201526080808301519082015260a0828101516101808301916156c2908401826155ec565b5092915050565b60006101406156d883886155ec565b8560e0840152806101008401526156f181840186614b05565b91505060018060a01b03831661012083015295945050505050565b6000825161571e818460208701614ae1565b919091019291505056fea2646970667358221220c3f80bbebf0439e321e9ff47ad34942c88d225a02367cc8d6ce0a1135400c7f164736f6c63430008100033", "deployedBytecode": "0x6080604052600436106101f95760003560e01c80638da5cb5b1161010d578063c715967a116100a0578063df21a7dd1161006f578063df21a7dd146106ae578063e5a6b10f146106fc578063f2fde38b14610730578063fc0c546a14610750578063fe663f0f1461078457600080fd5b8063c715967a14610631578063d3419bf314610644578063d6dacc5314610678578063ddca3f431461069857600080fd5b8063ad007d63116100dc578063ad007d6314610559578063b631b5001461058d578063b7bad1b1146105bd578063c41c2f24146105fd57600080fd5b80638da5cb5b146104c7578063975057e7146104e5578063a02f801c14610519578063a32e1e961461053957600080fd5b80634a4305c011610190578063715018a61161015f578063715018a6146104115780637258002c1461042657806389701db5146104465780638af56094146104665780638b79543c1461049357600080fd5b80634a4305c01461037d578063637913ac1461039d57806366248b86146103bd57806369fe0e2d146103f157600080fd5b80632bdfe004116101cc5780632bdfe004146102a95780632d1a5903146102f5578063313ce56714610329578063405b84fa1461035d57600080fd5b806301ffc9a7146101fe5780630cf8e858146102335780631982d679146102485780631ebc263f14610296575b600080fd5b34801561020a57600080fd5b5061021e61021936600461438e565b6107a4565b60405190151581526020015b60405180910390f35b610246610241366004614415565b61083b565b005b34801561025457600080fd5b506102886102633660046144aa565b507f000000000000000000000000000000000000000000000000000000000000000090565b60405190815260200161022a565b6102886102a43660046144d5565b610904565b3480156102b557600080fd5b506102dd7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161022a565b34801561030157600080fd5b506102887f000000000000000000000000000000000000000000000000000000000000000081565b34801561033557600080fd5b506102887f000000000000000000000000000000000000000000000000000000000000000081565b34801561036957600080fd5b5061028861037836600461459c565b610ac2565b34801561038957600080fd5b506102886103983660046145cc565b610dbe565b3480156103a957600080fd5b506102466103b83660046144aa565b610dda565b3480156103c957600080fd5b506102887f000000000000000000000000000000000000000000000000000000000000000081565b3480156103fd57600080fd5b5061024661040c366004614635565b610e61565b34801561041d57600080fd5b50610246610ef0565b34801561043257600080fd5b5061024661044136600461464e565b610f26565b34801561045257600080fd5b50610246610461366004614635565b610fb2565b34801561047257600080fd5b50610486610481366004614635565b611249565b60405161022a919061467c565b34801561049f57600080fd5b506102dd7f000000000000000000000000000000000000000000000000000000000000000081565b3480156104d357600080fd5b506000546001600160a01b03166102dd565b3480156104f157600080fd5b506102dd7f000000000000000000000000000000000000000000000000000000000000000081565b34801561052557600080fd5b50610288610534366004614822565b6112f6565b34801561054557600080fd5b50610288610554366004614635565b6113b1565b34801561056557600080fd5b506102dd7f000000000000000000000000000000000000000000000000000000000000000081565b34801561059957600080fd5b5061021e6105a83660046144aa565b60046020526000908152604090205460ff1681565b3480156105c957600080fd5b506102886105d83660046144aa565b507f000000000000000000000000000000000000000000000000000000000000000090565b34801561060957600080fd5b506102dd7f000000000000000000000000000000000000000000000000000000000000000081565b61024661063f3660046148da565b6115e6565b34801561065057600080fd5b506102dd7f000000000000000000000000000000000000000000000000000000000000000081565b34801561068457600080fd5b506003546102dd906001600160a01b031681565b3480156106a457600080fd5b5061028860025481565b3480156106ba57600080fd5b5061021e6106c9366004614981565b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161490565b34801561070857600080fd5b506102887f000000000000000000000000000000000000000000000000000000000000000081565b34801561073c57600080fd5b5061024661074b3660046144aa565b611788565b34801561075c57600080fd5b506102dd7f000000000000000000000000000000000000000000000000000000000000000081565b34801561079057600080fd5b5061028861079f3660046149ad565b611823565b60006001600160e01b0319821663edb527eb60e01b14806107d557506001600160e01b031982166301290c1760e61b145b806107f057506001600160e01b0319821663280be00760e21b145b8061080b57506001600160e01b0319821663fe663f0f60e01b145b8061082657506001600160e01b0319821663ad007d6360e01b145b80610835575061083582611843565b92915050565b604051636e49181f60e01b81526004810188905230602482015287907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636e49181f90604401602060405180830381865afa1580156108a8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108cc9190614a65565b6108e957604051631b1d5a5960e31b815260040160405180910390fd5b6108fa8888886000898989896115e6565b5050505050505050565b604051636e49181f60e01b8152600481018b90523060248201526000908b906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636e49181f90604401602060405180830381865afa158015610974573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109989190614a65565b6109b557604051631b1d5a5960e31b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661eeee14610a24573415610a0657604051635e7e9adf60e11b815260040160405180910390fd5b47610a1233308e611893565b610a1c8147614a98565b9b5050610a28565b349a505b610ab28b338e8c8c8c8c8c8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506118a292505050565b9c9b505050505050505050505050565b6040516331a9108f60e11b8152600481018390526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015610b2a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b4e9190614aab565b836004610b5c838383611e0a565b60405163df21a7dd60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301526024820188905286169063df21a7dd90604401602060405180830381865afa158015610bc9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bed9190614a65565b610c0a5760405163581010ed60e01b815260040160405180910390fd5b604051636bb6a5ad60e01b8152600481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636bb6a5ad906024016020604051808303816000875af1158015610c71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c959190614ac8565b93508315610d705760007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661eeee14610cd8576000610cda565b845b6040805160208101825260008152905163019f1d0b60e31b81529192506001600160a01b03881691630cf8e858918491610d3c918c918b917f000000000000000000000000000000000000000000000000000000000000000091600401614b31565b6000604051808303818588803b158015610d5557600080fd5b505af1158015610d69573d6000803e3d6000fd5b5050505050505b604080518581523360208201526001600160a01b0387169188917fa7519e5f94697b7f53e97c5eb46a0c730a296ab686ab8fd333835c5f735784eb910160405180910390a350505092915050565b6000610dce888888878787611f6e565b98975050505050505050565b6000546001600160a01b03163314610e0d5760405162461bcd60e51b8152600401610e0490614b6c565b60405180910390fd5b600380546001600160a01b0319166001600160a01b0383169081179091556040513381527f0a9a80fe9716605b3e52abb3d792d6a4e7816d6afc02a5a4ef023081feaf9f609060200160405180910390a250565b6000546001600160a01b03163314610e8b5760405162461bcd60e51b8152600401610e0490614b6c565b6302faf080811115610eb0576040516345fbd9c160e01b815260040160405180910390fd5b6002819055604080518281523360208201527fd7414e590e1cb532989ab2a34c8f4c2c17f7ab6f006efeeaef2e87cd5008c202910160405180910390a150565b6000546001600160a01b03163314610f1a5760405162461bcd60e51b8152600401610e0490614b6c565b610f2460006121d6565b565b6000546001600160a01b03163314610f505760405162461bcd60e51b8152600401610e0490614b6c565b6001600160a01b038216600081815260046020908152604091829020805460ff191685151590811790915591513381529192917fa2653e25a502c023a5830d0de847ef6f458387865b1f4f575d7594f9f2c0d71e910160405180910390a35050565b6040516331a9108f60e11b8152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa158015611017573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061103b9190614aab565b8160056110506000546001600160a01b031690565b6001600160a01b0316336001600160a01b03161461107084848484612226565b600085815260016020908152604080832080548251818502810185019093528083529192909190849084015b8282101561110957600084815260209081902060408051608081018252600286029092018054835260019081015463ffffffff8082168587015264010000000082041692840192909252600160401b9091046001600160a01b03166060830152908352909201910161109c565b50505060008881526001602052604081209293506111289291506142ed565b805160005b818110156108fa5760006111a584838151811061114c5761114c614ba1565b60200260200101516000015185848151811061116a5761116a614ba1565b60200260200101516020015163ffffffff1686858151811061118e5761118e614ba1565b60200260200101516040015163ffffffff1661239a565b90506111cf818584815181106111bd576111bd614ba1565b6020026020010151606001518b6123e0565b60011515818a7fcf0c92a2c6d7c42f488326b0cb900104b99984b6b218db81cd29371364a3525187868151811061120857611208614ba1565b602002602001015160600151336040516112389291906001600160a01b0392831681529116602082015260400190565b60405180910390a45060010161112d565b606060016000838152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b828210156112eb57600084815260209081902060408051608081018252600286029092018054835260019081015463ffffffff8082168587015264010000000082041692840192909252600160401b9091046001600160a01b03166060830152908352909201910161127e565b505050509050919050565b6040516331a9108f60e11b8152600481018a90526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa15801561135e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113829190614aab565b8a6011611390838383611e0a565b6113a08d8d8d8c8c8c8c8c6126b7565b9d9c50505050505050505050505050565b60405163035240c760e61b81523060048201526024810182905260009081906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063d49031c090604401602060405180830381865afa158015611421573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114459190614ac8565b905060007f00000000000000000000000000000000000000000000000000000000000000006012146114a25761149d827f000000000000000000000000000000000000000000000000000000000000000060126128e3565b6114a4565b815b905060017f0000000000000000000000000000000000000000000000000000000000000000146115dc576115d7816114fd7f0000000000000000000000000000000000000000000000000000000000000000600a614c9b565b604051635268657960e11b81527f00000000000000000000000000000000000000000000000000000000000000006004820152600160248201527f000000000000000000000000000000000000000000000000000000000000000060448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a4d0caf290606401602060405180830381865afa1580156115ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115d29190614ac8565b612940565b6115de565b805b949350505050565b604051636e49181f60e01b81526004810189905230602482015288907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636e49181f90604401602060405180830381865afa158015611653573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116779190614a65565b61169457604051631b1d5a5960e31b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661eeee146117035734156116e557604051635e7e9adf60e11b815260040160405180910390fd5b476116f133308b611893565b6116fb8147614a98565b985050611707565b3497505b61177d89898888888080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8c018190048102820181019092528a815292508a9150899081908401838280828437600092019190915250612a0d92505050565b505050505050505050565b6000546001600160a01b031633146117b25760405162461bcd60e51b8152600401610e0490614b6c565b6001600160a01b0381166118175760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610e04565b611820816121d6565b50565b600088886002611834838383611e0a565b610ab28c8c8c8b8b8b8b612aff565b60006001600160e01b0319821663301cdc3960e21b148061187457506001600160e01b0319821663144b000160e11b145b8061083557506301ffc9a760e01b6001600160e01b0319831614610835565b61189d828261302a565b505050565b60006001600160a01b0386166118cb5760405163a762251360e01b815260040160405180910390fd5b6118d361430e565b606060008060405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020018e81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f000000000000000000000000000000000000000000000000000000000000000081525090507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632fa1b3918d838e7f00000000000000000000000000000000000000000000000000000000000000008f8d8d6040518863ffffffff1660e01b81526004016119dc9796959493929190614cd3565b6000604051808303816000875af11580156119fb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611a239190810190614e37565b995091955090935091508115611b5857604051632eec7b5560e11b8152600481018c90527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635dd8f6aa90602401602060405180830381865afa158015611a98573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abc9190614aab565b604051638ae9c07b60e01b8152600481018d9052602481018490526001600160a01b038c8116604483015260c06064830152600060c48301528a15156084830152600160a48301529190911690638ae9c07b9060e4016020604051808303816000875af1158015611b31573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b559190614ac8565b94505b88851015611b7957604051633dca309360e11b815260040160405180910390fd5b825115611dac57600060405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020018f81526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f0000000000000000000000000000000000000000000000000000000000000000815250905060006040518061014001604052808f6001600160a01b031681526020018e8152602001876020015181526020018481526020018381526020018881526020018d6001600160a01b031681526020018b151581526020018a815260200189815250905060008551905060005b81811015611da7576000878281518110611c9557611c95614ba1565b60209081029190910101519050600061eeed197f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031601611cde575060208101515b602080830151608087015190910152815160405163da9ee8b760e01b81526001600160a01b039091169063da9ee8b7908390611d1e908990600401614fee565b6000604051808303818588803b158015611d3757600080fd5b505af1158015611d4b573d6000803e3d6000fd5b505050505081600001516001600160a01b03167f16112c26e14efc4be6c690149aa5a1ba75160de245f60d2273e28adb277b9e1286846020015133604051611d9593929190615001565b60405180910390a25050600101611c79565b505050505b50505087816000015182602001517f133161f1c9161488f777ab9a26aae91d47c0d9a3fafb398960f138db02c737978c8b8f888b8b33604051611df59796959493929190615034565b60405180910390a45098975050505050505050565b336001600160a01b03841614801590611eb3575060405163c161c93f60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c161c93f90611e70903390879087908790600401615094565b602060405180830381865afa158015611e8d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eb19190614a65565b155b8015611f50575060405163c161c93f60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c161c93f90611f0d90339087906000908790600401615094565b602060405180830381865afa158015611f2a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f4e9190614a65565b155b1561189d5760405163075fd2b160e01b815260040160405180910390fd5b60405163c664459760e01b8152600481018790526024810186905260448101859052600090819081906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c664459790606401610140604051808303816000875af1158015611feb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061200f91906150bd565b91509150858110156120345760405163b01493c160e01b815260040160405180910390fd5b6040516331a9108f60e11b8152600481018a90526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636352211e90602401602060405180830381865afa15801561209c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120c09190614aab565b90506000806002546000146120dd576120d88c613143565b6120e3565b633b9aca005b90506000806121198e88602001517f000000000000000000000000000000000000000000000000000000000000000089876132af565b92509050633b9aca00831461212d57908101905b8160000361213c576000612149565b6121498e88848887613457565b935080156121755761215e816002548561239a565b6121689082614a98565b975061217530868a611893565b5050508a846000015185602001517fc41a8d26c70cfcf1b9ea10f82482ac947b8be5bea2750bc729af844bbfde1e28858e88878c8f8f336040516121c0989796959493929190615115565b60405180910390a4505050509695505050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b8015801561223d5750336001600160a01b03851614155b80156122d9575060405163c161c93f60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c161c93f90612296903390889088908890600401615094565b602060405180830381865afa1580156122b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122d79190614a65565b155b8015612376575060405163c161c93f60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c161c93f9061233390339088906000908890600401615094565b602060405180830381865afa158015612350573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123749190614a65565b155b156123945760405163075fd2b160e01b815260040160405180910390fd5b50505050565b6000806123ac8484633b9aca00612940565b6123b69085614a98565b90506123cb85633b9aca006115d28185615168565b6123d59086614a98565b9150505b9392505050565b604051630862026560e41b8152600160048201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660248301526000917f000000000000000000000000000000000000000000000000000000000000000090911690638620265090604401602060405180830381865afa158015612472573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124969190614aab565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031661eeee146124d35760006124d5565b845b604080516020808252818301909252919250600091906020820181803683370190505090508360405160200161250d91815260200190565b60408051808303601f1901815290829052631ebc263f60e01b825291506001600160a01b03841690631ebc263f908490612579906001908b907f0000000000000000000000000000000000000000000000000000000000000000908c9060009081908b9060040161517b565b60206040518083038185885af1935050505080156125b4575060408051601f3d908101601f191682019092526125b191810190614ac8565b60015b6126ad573d8080156125e2576040519150601f19603f3d011682016040523d82523d6000602084013e6125e7565b606091505b5060405163e7c8e3e360e01b815260048101869052602481018890527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7c8e3e390604401600060405180830381600087803b15801561265157600080fd5b505af1158015612665573d6000803e3d6000fd5b505050506001857f80a889d08f0d59eb962335b57fb1d5b29e86e3d23f15087b5541fddf15422bbe89843360405161269f939291906151d3565b60405180910390a3506126af565b505b505050505050565b604051632538671560e01b8152600481018990526024810188905260448101879052600090819081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632538671590606401610140604051808303816000875af1158015612734573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061275891906150bd565b915091508781101561277d5760405163b01493c160e01b815260040160405180910390fd5b6040516331a9108f60e11b8152600481018c905260009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636352211e90602401602060405180830381865afa1580156127e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061280b9190614aab565b905060006002546000148061282f57503360009081526004602052604090205460ff165b6128415761283c8e613143565b612847565b633b9aca005b9050633b9aca008114612866576128618e86868585613457565b612869565b60005b8085039650925083831461288257612882308b88611893565b5050508a826000015183602001517f2eeee47c6d8d31c3523c3aa07b4c3e3795db36be4c04546ef3e30a5102f568e18a8e86898d8d8d336040516128cd989796959493929190615204565b60405180910390a4505098975050505050505050565b60008282036128f35750826123d9565b82821115612921576129058383614a98565b61291090600a614c9b565b61291a9085615264565b90506123d9565b61292b8284614a98565b61293690600a614c9b565b61291a9085615299565b600080806000198587098587029250828110838203039150508060000361297a5783828161297057612970615283565b04925050506123d9565b8381106129a457604051631dcf306360e21b81526004810182905260248101859052604401610e04565b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b600083612a1b576000612a25565b612a2586866135e6565b90506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663e7c8e3e387612a618489615168565b6040516001600160e01b031960e085901b16815260048101929092526024820152604401600060405180830381600087803b158015612a9f57600080fd5b505af1158015612ab3573d6000803e3d6000fd5b50505050857f9ecaf7fc3dfffd6867c175d6e684b1f1e3aef019398ba8db2c1ffab4a09db2538683868633604051612aef9594939291906152bb565b60405180910390a2505050505050565b60006001600160a01b038416612b2857604051637ba50db360e11b815260040160405180910390fd5b612b3061430e565b60405163a2df1f9560e01b81526060906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a2df1f9590612b87908d908d908d908b908b90600401615307565b6000604051808303816000875af1158015612ba6573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612bce9190810190615346565b9750909450909250905086831015612bf95760405163f896960b60e01b815260040160405180910390fd5b8715612d0957604051632eec7b5560e11b8152600481018a90527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635dd8f6aa90602401602060405180830381865afa158015612c64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c889190614aab565b604051631665bc0f60e01b81526001600160a01b038c81166004830152602482018c9052604482018b905260a06064830152600060a4830181905260848301529190911690631665bc0f9060c401600060405180830381600087803b158015612cf057600080fd5b505af1158015612d04573d6000803e3d6000fd5b505050505b805115612fbe57600060405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602001600081526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f0000000000000000000000000000000000000000000000000000000000000000815250905060006040518061012001604052808d6001600160a01b031681526020018c8152602001856020015181526020018b815260200160405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020018881526020017f000000000000000000000000000000000000000000000000000000000000000081526020017f00000000000000000000000000000000000000000000000000000000000000008152508152602001838152602001896001600160a01b0316815260200188815260200187815250905060008351905060005b81811015612fb9576000858281518110612ea757612ea7614ba1565b60209081029190910101519050600061eeed197f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031601612ef0575060208101515b60208083015160a0870151909101528151604051632b13c58f60e01b81526001600160a01b0390911690632b13c58f908390612f309089906004016154bd565b6000604051808303818588803b158015612f4957600080fd5b505af1158015612f5d573d6000803e3d6000fd5b505050505081600001516001600160a01b03167f54b3744c489f40987dd2726ca12131243334e8292f567389f761c5a432d813e486846020015133604051612fa7939291906154d0565b60405180910390a25050600101612e8b565b505050505b508115612fd057612fd0308684611893565b87816000015182602001517f2be10f2a0203c77d0fcaa9fd6484a8a1d6904de31cd820587f60c1c8c338c8148c898c888b8b336040516130169796959493929190615034565b60405180910390a450979650505050505050565b8047101561307a5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e63650000006044820152606401610e04565b6000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146130c7576040519150601f19603f3d011682016040523d82523d6000602084013e6130cc565b606091505b505090508061189d5760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d617920686176652072657665727465640000000000006064820152608401610e04565b604051630862026560e41b8152600160048201526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116602483015260009182917f00000000000000000000000000000000000000000000000000000000000000001690638620265090604401602060405180830381865afa1580156131d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131f99190614aab565b6001600160a01b0316036132125750633b9aca00919050565b6003546001600160a01b0316156132a757600354604051633bb4ac4b60e11b8152600481018490526001600160a01b0390911690637769589690602401602060405180830381865afa925050508015613288575060408051601f3d908101601f1916820190925261328591810190614ac8565b60015b61329457506000919050565b633b9aca0081116132a55792915050565b505b506000919050565b6040516369e11cc560e01b81526004810186905260248101859052604481018490528290600090633b9aca009082907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906369e11cc590606401600060405180830381865afa15801561332f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261335791908101906154e3565b905060005b815181101561344a57600082828151811061337957613379614ba1565b602002602001015190506000848260400151146133a8576133a3898360400151633b9aca00612940565b6133aa565b865b90508160400151856133bc9190614a98565b945060006133cd838e8d858d6139b6565b905080158015906133de5750818114155b156133f0576133ed8288615168565b96505b81156133fc5781880397505b8a8c8e7f0d31ab573f6daa4b1edba8d31973b4ba9f98fbfecc47010c1533eeefd2a1225a868686336040516134349493929190615640565b60405180910390a483600101935050505061335c565b5050509550959350505050565b6000613466846002548461239a565b610100860151909150604f1c60019081160361358957600086815260016020818152604080842081516080810183528981526002805463ffffffff9081168387019081528a82168487019081526001600160a01b03808e16606087019081528754808c018955978c5298909a2094519584029094019485555193909601805492519551909716600160401b02600160401b600160e01b03199587166401000000000267ffffffffffffffff19909316939096169290921717929092169290921790925590549051859088907f77813be0661650ddc1a5193ff2837df4162b251cb432651e2c060c3fc39756be9061357c908790899033909283526001600160a01b03918216602084015216604082015260600190565b60405180910390a46135dd565b6135948184886123e0565b604080516001600160a01b0385168152336020820152600091839189917fcf0c92a2c6d7c42f488326b0cb900104b99984b6b218db81cd29371364a35251910160405180910390a45b95945050505050565b600082815260016020908152604080832080548251818502810185019093528083528493849084015b8282101561367c57600084815260209081902060408051608081018252600286029092018054835260019081015463ffffffff8082168587015264010000000082041692840192909252600160401b9091046001600160a01b03166060830152908352909201910161360f565b505050600086815260016020526040812092935061369b9291506142ed565b8051839060005b8181101561396e578260000361376157600087815260016020526040902084518590839081106136d4576136d4614ba1565b60209081029190910181015182546001818101855560009485529383902082516002909202019081559181015191909201805460408401516060909401516001600160a01b0316600160401b02600160401b600160e01b031963ffffffff9586166401000000000267ffffffffffffffff1990931695909416949094171791909116919091179055613966565b83818151811061377357613773614ba1565b60200260200101516000015183106138075783818151811061379757613797614ba1565b602002602001015160000151830392506137fe8482815181106137bc576137bc614ba1565b6020026020010151600001518583815181106137da576137da614ba1565b60200260200101516020015163ffffffff1686848151811061118e5761118e614ba1565b85019450613966565b6001600088815260200190815260200160002060405180608001604052808587858151811061383857613838614ba1565b60200260200101516000015103815260200186848151811061385c5761385c614ba1565b60200260200101516020015163ffffffff16815260200186848151811061388557613885614ba1565b60200260200101516040015163ffffffff1681526020018684815181106138ae576138ae614ba1565b6020908102919091018101516060908101516001600160a01b0390811690935284546001818101875560009687529583902085516002909202019081559184015191909401805460408501519490950151909216600160401b02600160401b600160e01b031963ffffffff9485166401000000000267ffffffffffffffff1990961694909216939093179390931792909216179055835161395d9084908690849081106137da576137da614ba1565b85019450600092505b6001016136a2565b50604080518381523360208201528591879189917f59860d79d97c1fce2be7f987915c631471f4b08f671200463cc40a3380194ffb910160405180910390a450505092915050565b60c08501516000906001600160a01b031615613cb757633b9aca008214806139fa575060c08601516001600160a01b031660009081526004602052604090205460ff165b15613a06575081613a18565b613a13836002548461239a565b830390505b60006040518060c001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020018381526020017f0000000000000000000000000000000000000000000000000000000000000000815260200187815260200186815260200188815250905060006060613aab8960c00151634eba05fd60e11b6141b5565b15613b93578860c001516001600160a01b0316639d740bfa61eeee6001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614613b05576000613b07565b855b856040518363ffffffff1660e01b8152600401613b249190615675565b6000604051808303818588803b158015613b3d57600080fd5b505af193505050508015613b4f575060015b613b8e573d808015613b7d576040519150601f19603f3d011682016040523d82523d6000602084013e613b82565b606091505b50600192509050613b98565b613b98565b600291505b8115613caf5760405163e7c8e3e360e01b81526004810189905260248101879052600094507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7c8e3e390604401600060405180830381600087803b158015613c0b57600080fd5b505af1158015613c1f573d6000803e3d6000fd5b50505050877f290b5df59e172593762964e4f8ed2b4a9192d3197bfd2be4bae123908f8007968a8885600114613c9357604051602001613c7f906020808252600c908201526b12515490cc4d8d4819985a5b60a21b604082015260600190565b604051602081830303815290604052613c95565b845b33604051613ca694939291906156c9565b60405180910390a25b5050506135dd565b606086015115614158576060860151604051630862026560e41b81526000916001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691638620265091613d47917f0000000000000000000000000000000000000000000000000000000000000000906004019182526001600160a01b0316602082015260400190565b602060405180830381865afa158015613d64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d889190614aab565b90506001600160a01b038116613db157604051636921234360e01b815260040160405180910390fd5b6001600160a01b038116301480613dcb5750633b9aca0083145b80613dee57506001600160a01b03811660009081526004602052604090205460ff165b15613dfb57839150613e0d565b613e08846002548561239a565b840391505b60408051602080825281830190925260009160208201818036833701905050905086604051602001613e4191815260200190565b604051602081830303815290604052905087602001511561402357816001600160a01b0316630cf8e85861eeee6001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614613ead576000613eaf565b845b8a60600151867f0000000000000000000000000000000000000000000000000000000000000000866040518663ffffffff1660e01b8152600401613ef69493929190614b31565b6000604051808303818588803b158015613f0f57600080fd5b505af193505050508015613f21575060015b61401e573d808015613f4f576040519150601f19603f3d011682016040523d82523d6000602084013e613f54565b606091505b5060405163e7c8e3e360e01b81526004810189905260248101879052600094507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e7c8e3e390604401600060405180830381600087803b158015613fc257600080fd5b505af1158015613fd6573d6000803e3d6000fd5b50505050877f290b5df59e172593762964e4f8ed2b4a9192d3197bfd2be4bae123908f8007968a88843360405161401094939291906156c9565b60405180910390a250614151565b614151565b816001600160a01b0316631ebc263f61eeee6001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031614614074576000614076565b845b60608b015160808c015187907f0000000000000000000000000000000000000000000000000000000000000000906001600160a01b03166140b757336140bd565b8d608001515b8e516040516001600160e01b031960e089901b1681526140e895949392916000918b9060040161517b565b60206040518083038185885af193505050508015614123575060408051601f3d908101601f1916820190925261412091810190614ac8565b60015b613caf573d808015613f4f576040519150601f19603f3d011682016040523d82523d6000602084013e613f54565b50506135dd565b60808601516000906001600160a01b03166141735733614179565b86608001515b9050633b9aca00830361418e578391506141a0565b61419b846002548561239a565b840391505b6141ab308284611893565b5095945050505050565b60006141c0836141d1565b80156123d957506123d98383614204565b60006141e4826301ffc9a760e01b614204565b801561083557506141fd826001600160e01b0319614204565b1592915050565b604080516001600160e01b0319831660248083019190915282518083039091018152604490910182526020810180516001600160e01b03166301ffc9a760e01b179052905160009190829081906001600160a01b038716906175309061426b90869061570c565b6000604051808303818686fa925050503d80600081146142a7576040519150601f19603f3d011682016040523d82523d6000602084013e6142ac565b606091505b50915091506020815110156142c75760009350505050610835565b8180156142e35750808060200190518101906142e39190614a65565b9695505050505050565b50805460008255600202906000526020600020908101906118209190614363565b6040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b5b8082111561438a57600081556001810180546001600160e01b0319169055600201614364565b5090565b6000602082840312156143a057600080fd5b81356001600160e01b0319811681146123d957600080fd5b6001600160a01b038116811461182057600080fd5b60008083601f8401126143df57600080fd5b5081356001600160401b038111156143f657600080fd5b60208301915083602082850101111561440e57600080fd5b9250929050565b600080600080600080600060a0888a03121561443057600080fd5b87359650602088013595506040880135614449816143b8565b945060608801356001600160401b038082111561446557600080fd5b6144718b838c016143cd565b909650945060808a013591508082111561448a57600080fd5b506144978a828b016143cd565b989b979a50959850939692959293505050565b6000602082840312156144bc57600080fd5b81356123d9816143b8565b801515811461182057600080fd5b6000806000806000806000806000806101008b8d0312156144f557600080fd5b8a35995060208b0135985060408b013561450e816143b8565b975060608b013561451e816143b8565b965060808b0135955060a08b0135614535816144c7565b945060c08b01356001600160401b038082111561455157600080fd5b61455d8e838f016143cd565b909650945060e08d013591508082111561457657600080fd5b506145838d828e016143cd565b915080935050809150509295989b9194979a5092959850565b600080604083850312156145af57600080fd5b8235915060208301356145c1816143b8565b809150509250929050565b600080600080600080600060c0888a0312156145e757600080fd5b8735965060208801359550604088013594506060880135614607816143b8565b93506080880135925060a08801356001600160401b0381111561462957600080fd5b6144978a828b016143cd565b60006020828403121561464757600080fd5b5035919050565b6000806040838503121561466157600080fd5b823561466c816143b8565b915060208301356145c1816144c7565b602080825282518282018190526000919060409081850190868401855b828110156146e5578151805185528681015163ffffffff908116888701528682015116868601526060908101516001600160a01b03169085015260809093019290850190600101614699565b5091979650505050505050565b634e487b7160e01b600052604160045260246000fd5b60405161012081016001600160401b038111828210171561472b5761472b6146f2565b60405290565b604080519081016001600160401b038111828210171561472b5761472b6146f2565b60405160e081016001600160401b038111828210171561472b5761472b6146f2565b604051601f8201601f191681016001600160401b038111828210171561479d5761479d6146f2565b604052919050565b60006001600160401b038211156147be576147be6146f2565b50601f01601f191660200190565b600082601f8301126147dd57600080fd5b81356147f06147eb826147a5565b614775565b81815284602083860101111561480557600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060008060006101008a8c03121561484157600080fd5b8935985060208a0135975060408a0135965060608a0135614861816143b8565b955060808a0135945060a08a0135614878816143b8565b935060c08a01356001600160401b038082111561489457600080fd5b6148a08d838e016147cc565b945060e08c01359150808211156148b657600080fd5b506148c38c828d016143cd565b915080935050809150509295985092959850929598565b60008060008060008060008060c0898b0312156148f657600080fd5b8835975060208901359650604089013561490f816143b8565b9550606089013561491f816144c7565b945060808901356001600160401b038082111561493b57600080fd5b6149478c838d016143cd565b909650945060a08b013591508082111561496057600080fd5b5061496d8b828c016143cd565b999c989b5096995094979396929594505050565b6000806040838503121561499457600080fd5b823561499f816143b8565b946020939093013593505050565b600080600080600080600080610100898b0312156149ca57600080fd5b88356149d5816143b8565b9750602089013596506040890135955060608901356149f3816143b8565b94506080890135935060a0890135614a0a816143b8565b925060c08901356001600160401b0380821115614a2657600080fd5b614a328c838d016147cc565b935060e08b0135915080821115614a4857600080fd5b50614a558b828c016147cc565b9150509295985092959890939650565b600060208284031215614a7757600080fd5b81516123d9816144c7565b634e487b7160e01b600052601160045260246000fd5b8181038181111561083557610835614a82565b600060208284031215614abd57600080fd5b81516123d9816143b8565b600060208284031215614ada57600080fd5b5051919050565b60005b83811015614afc578181015183820152602001614ae4565b50506000910152565b60008151808452614b1d816020860160208601614ae1565b601f01601f19169290920160200192915050565b84815283602082015260018060a01b038316604082015260a06060820152600060a082015260c0608082015260006142e360c0830184614b05565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b634e487b7160e01b600052603260045260246000fd5b600181815b80851115614bf2578160001904821115614bd857614bd8614a82565b80851615614be557918102915b93841c9390800290614bbc565b509250929050565b600082614c0957506001610835565b81614c1657506000610835565b8160018114614c2c5760028114614c3657614c52565b6001915050610835565b60ff841115614c4757614c47614a82565b50506001821b610835565b5060208310610133831016604e8410600b8410161715614c75575081810a610835565b614c7f8383614bb7565b8060001904821115614c9357614c93614a82565b029392505050565b60006123d98383614bfa565b80516001600160a01b031682526020808201519083015260408082015190830152606090810151910152565b6001600160a01b03888116825260009061014090614cf4602085018b614ca7565b8860a08501528760c085015280871660e08501525080610100840152614d1c81840186614b05565b9050828103610120840152614d318185614b05565b9a9950505050505050505050565b8051614d4a816143b8565b919050565b60006101208284031215614d6257600080fd5b614d6a614708565b9050815181526020820151602082015260408201516040820152606082015160608201526080820151608082015260a082015160a082015260c082015160c0820152614db860e08301614d3f565b60e082015261010080830151818301525092915050565b60006001600160401b03821115614de857614de86146f2565b5060051b60200190565b600082601f830112614e0357600080fd5b8151614e116147eb826147a5565b818152846020838601011115614e2657600080fd5b6115de826020830160208701614ae1565b6000806000806101808587031215614e4e57600080fd5b614e588686614d4f565b935061012085015192506101408501516001600160401b0380821115614e7d57600080fd5b818701915087601f830112614e9157600080fd5b81516020614ea16147eb83614dcf565b82815260069290921b8401810191818101908b841115614ec057600080fd5b948201945b83861015614f0c576040868d031215614ede5760008081fd5b614ee6614731565b8651614ef1816143b8565b81528684015184820152825260409095019490820190614ec5565b6101608b0151909750945050505080821115614f2757600080fd5b50614f3487828801614df2565b91505092959194509250565b80516001600160a01b03168252600061020060208301516020850152604083015160408501526060830151614f786060860182614ca7565b506080830151614f8b60e0860182614ca7565b5060a083015161016085015260c08301516001600160a01b031661018085015260e083015115156101a08501526101008301516101c08501829052614fd282860182614b05565b9150506101208301518482036101e08601526135dd8282614b05565b6020815260006123d96020830184614f40565b6060815260006150146060830186614f40565b6020830194909452506001600160a01b0391909116604090910152919050565b600060018060a01b03808a168352808916602084015287604084015286606084015260e0608084015261506a60e0840187614b05565b83810360a085015261507c8187614b05565b92505080841660c08401525098975050505050505050565b6001600160a01b0394851681529290931660208301526040820152606081019190915260800190565b60008061014083850312156150d157600080fd5b6150db8484614d4f565b915061012083015190509250929050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b600060018060a01b03808b16835289602084015288604084015287606084015286608084015260e060a084015261515060e0840186886150ec565b915080841660c0840152509998505050505050505050565b8082018082111561083557610835614a82565b878152602081018790526001600160a01b038681166040830152851660608201526080810184905282151560a082015261010060c08201819052600090820181905261012060e08301819052614d3181840185614b05565b8381526060602082015260006151ec6060830185614b05565b905060018060a01b0383166040830152949350505050565b600060018060a01b03808b16835289602084015288604084015287606084015260e0608084015261523860e0840188614b05565b83810360a085015261524b8187896150ec565b92505080841660c0840152509998505050505050505050565b600081600019048311821515161561527e5761527e614a82565b500290565b634e487b7160e01b600052601260045260246000fd5b6000826152b657634e487b7160e01b600052601260045260246000fd5b500490565b85815284602082015260a0604082015260006152da60a0830186614b05565b82810360608401526152ec8186614b05565b91505060018060a01b03831660808301529695505050505050565b60018060a01b038616815284602082015283604082015260a06060820152600061533460a0830185614b05565b8281036080840152610dce8185614b05565b600080600080610180858703121561535d57600080fd5b6153678686614d4f565b935061012085015192506101408501516001600160401b038082111561538c57600080fd5b818701915087601f8301126153a057600080fd5b815160206153b06147eb83614dcf565b82815260069290921b8401810191818101908b8411156153cf57600080fd5b948201945b83861015614f0c576040868d0312156153ed5760008081fd5b6153f5614731565b8651615400816143b8565b815286840151848201528252604090950194908201906153d4565b80516001600160a01b0316825260006101e0602083015160208501526040830151604085015260608301516060850152608083015161545d6080860182614ca7565b5060a083015161010061547281870183614ca7565b60c08501516001600160a01b031661018087015260e08501516101a0870184905291506154a183870183614b05565b9250808501519150508482036101c08601526135dd8282614b05565b6020815260006123d9602083018461541b565b606081526000615014606083018661541b565b600060208083850312156154f657600080fd5b82516001600160401b0381111561550c57600080fd5b8301601f8101851361551d57600080fd5b805161552b6147eb82614dcf565b81815260e0918202830184019184820191908884111561554a57600080fd5b938501935b838510156155e05780858a0312156155675760008081fd5b61556f614753565b855161557a816144c7565b815285870151615589816144c7565b8188015260408681015190820152606080870151908201526080808701516155b0816143b8565b9082015260a0868101519082015260c0808701516155cd816143b8565b908201528352938401939185019161554f565b50979650505050505050565b80511515825260208082015115159083015260408082015190830152606080820151908301526080808201516001600160a01b039081169184019190915260a0808301519084015260c09182015116910152565b610140810161564f82876155ec565b60e08201949094526101008101929092526001600160a01b031661012090910152919050565b81516001600160a01b031681526020808301519082015260408083015190820152606080830151908201526080808301519082015260a0828101516101808301916156c2908401826155ec565b5092915050565b60006101406156d883886155ec565b8560e0840152806101008401526156f181840186614b05565b91505060018060a01b03831661012083015295945050505050565b6000825161571e818460208701614ae1565b919091019291505056fea2646970667358221220c3f80bbebf0439e321e9ff47ad34942c88d225a02367cc8d6ce0a1135400c7f164736f6c63430008100033", "devdoc": { diff --git a/deployments/mainnet/JBSingleTokenPaymentTerminalStore.json b/deployments/mainnet/JBSingleTokenPaymentTerminalStore.json index 731df79e2..96b41f0f5 100644 --- a/deployments/mainnet/JBSingleTokenPaymentTerminalStore.json +++ b/deployments/mainnet/JBSingleTokenPaymentTerminalStore.json @@ -816,7 +816,7 @@ ], "numDeployments": 1, "solcInputHash": "7f5ae5369c2a685c882e67f75315b841", - "metadata": "{\"compiler\":{\"version\":\"0.8.16+commit.07a7930e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IJBDirectory\",\"name\":\"_directory\",\"type\":\"address\"},{\"internalType\":\"contract IJBFundingCycleStore\",\"name\":\"_fundingCycleStore\",\"type\":\"address\"},{\"internalType\":\"contract IJBPrices\",\"name\":\"_prices\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CURRENCY_MISMATCH\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DISTRIBUTION_AMOUNT_LIMIT_REACHED\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FUNDING_CYCLE_DISTRIBUTION_PAUSED\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FUNDING_CYCLE_PAYMENT_PAUSED\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FUNDING_CYCLE_REDEEM_PAUSED\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INADEQUATE_CONTROLLER_ALLOWANCE\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INSUFFICIENT_TOKENS\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INVALID_AMOUNT_TO_SEND_DELEGATE\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INVALID_FUNDING_CYCLE\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"prod1\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"denominator\",\"type\":\"uint256\"}],\"name\":\"PRBMath__MulDivOverflow\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminal\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminal\",\"name\":\"_terminal\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"}],\"name\":\"currentOverflowOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_tokenCount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_overflow\",\"type\":\"uint256\"}],\"name\":\"currentReclaimableOverflowOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminal\",\"name\":\"_terminal\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_tokenCount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"_useTotalOverflow\",\"type\":\"bool\"}],\"name\":\"currentReclaimableOverflowOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_decimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_currency\",\"type\":\"uint256\"}],\"name\":\"currentTotalOverflowOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"directory\",\"outputs\":[{\"internalType\":\"contract IJBDirectory\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fundingCycleStore\",\"outputs\":[{\"internalType\":\"contract IJBFundingCycleStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"prices\",\"outputs\":[{\"internalType\":\"contract IJBPrices\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"recordAddedBalanceFor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_currency\",\"type\":\"uint256\"}],\"name\":\"recordDistributionFor\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"configuration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"basedOn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"discountRate\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBFundingCycleBallot\",\"name\":\"ballot\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"metadata\",\"type\":\"uint256\"}],\"internalType\":\"struct JBFundingCycle\",\"name\":\"fundingCycle\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"distributedAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"}],\"name\":\"recordMigration\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_payer\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"decimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"currency\",\"type\":\"uint256\"}],\"internalType\":\"struct JBTokenAmount\",\"name\":\"_amount\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_baseWeightCurrency\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"recordPaymentFrom\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"configuration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"basedOn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"discountRate\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBFundingCycleBallot\",\"name\":\"ballot\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"metadata\",\"type\":\"uint256\"}],\"internalType\":\"struct JBFundingCycle\",\"name\":\"fundingCycle\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"tokenCount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"contract IJBPayDelegate\",\"name\":\"delegate\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"struct JBPayDelegateAllocation[]\",\"name\":\"delegateAllocations\",\"type\":\"tuple[]\"},{\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_holder\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_tokenCount\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"recordRedemptionFor\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"configuration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"basedOn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"discountRate\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBFundingCycleBallot\",\"name\":\"ballot\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"metadata\",\"type\":\"uint256\"}],\"internalType\":\"struct JBFundingCycle\",\"name\":\"fundingCycle\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"reclaimAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"contract IJBRedemptionDelegate\",\"name\":\"delegate\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"struct JBRedemptionDelegateAllocation[]\",\"name\":\"delegateAllocations\",\"type\":\"tuple[]\"},{\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_currency\",\"type\":\"uint256\"}],\"name\":\"recordUsedAllowanceOf\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"configuration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"basedOn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"discountRate\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBFundingCycleBallot\",\"name\":\"ballot\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"metadata\",\"type\":\"uint256\"}],\"internalType\":\"struct JBFundingCycle\",\"name\":\"fundingCycle\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"usedAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminal\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"usedDistributionLimitOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminal\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"usedOverflowAllowanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Adheres to: IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.Inherits from - ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_directory\":\"A contract storing directories of terminals and controllers for each project.\",\"_fundingCycleStore\":\"A contract storing all funding cycle configurations.\",\"_prices\":\"A contract that exposes price feeds.\"}},\"currentOverflowOf(address,uint256)\":{\"details\":\"The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\",\"params\":{\"_projectId\":\"The ID of the project to get overflow for.\",\"_terminal\":\"The terminal for which the overflow is being calculated.\"},\"returns\":{\"_0\":\"The current amount of overflow that project has in the specified terminal.\"}},\"currentReclaimableOverflowOf(address,uint256,uint256,bool)\":{\"details\":\" If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.The current reclaimable overflow is returned in terms of the specified terminal's currency.The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\",\"params\":{\"_projectId\":\"The ID of the project to get the reclaimable overflow amount for.\",\"_terminal\":\"The terminal from which the reclaimable amount would come.\",\"_tokenCount\":\"The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\",\"_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`.\"},\"returns\":{\"_0\":\"The amount of overflowed tokens that can be reclaimed, as a fixed point number with the same number of decimals as the provided `_terminal`.\"}},\"currentReclaimableOverflowOf(uint256,uint256,uint256,uint256)\":{\"details\":\" If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\",\"params\":{\"_overflow\":\"The amount of overflow to make the calculation with, as a fixed point number.\",\"_projectId\":\"The ID of the project to get the reclaimable overflow amount for.\",\"_tokenCount\":\"The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\",\"_totalSupply\":\"The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\"},\"returns\":{\"_0\":\"The amount of overflowed tokens that can be reclaimed, as a fixed point number with the same number of decimals as the provided `_overflow`.\"}},\"currentTotalOverflowOf(uint256,uint256,uint256)\":{\"params\":{\"_currency\":\"The currency that the total overflow should be in terms of.\",\"_decimals\":\"The number of decimals that the fixed point overflow should include.\",\"_projectId\":\"The ID of the project to get total overflow for.\"},\"returns\":{\"_0\":\"The current total amount of overflow that project has across all terminals.\"}},\"recordAddedBalanceFor(uint256,uint256)\":{\"details\":\"The msg.sender must be an IJBSingleTokenPaymentTerminal. \",\"params\":{\"_amount\":\"The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\",\"_projectId\":\"The ID of the project to which the funds being added belong.\"}},\"recordDistributionFor(uint256,uint256,uint256)\":{\"details\":\"The msg.sender must be an IJBSingleTokenPaymentTerminal. \",\"params\":{\"_amount\":\"The amount to use from the distribution limit, as a fixed point number.\",\"_currency\":\"The currency of the `_amount`. This must match the project's current funding cycle's currency.\",\"_projectId\":\"The ID of the project that is having funds distributed.\"},\"returns\":{\"distributedAmount\":\"The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\",\"fundingCycle\":\"The funding cycle during which the distribution was made.\"}},\"recordMigration(uint256)\":{\"details\":\"The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\",\"params\":{\"_projectId\":\"The ID of the project being migrated.\"},\"returns\":{\"balance\":\"The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\"}},\"recordPaymentFrom(address,(address,uint256,uint256,uint256),uint256,uint256,address,string,bytes)\":{\"details\":\"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.The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\",\"params\":{\"_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.\",\"_baseWeightCurrency\":\"The currency to base token issuance on.\",\"_beneficiary\":\"The specified address that should be the beneficiary of anything that results from the payment.\",\"_memo\":\"A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\",\"_metadata\":\"Bytes to send along to the data source, if one is provided.\",\"_payer\":\"The original address that sent the payment to the terminal.\",\"_projectId\":\"The ID of the project being paid.\"},\"returns\":{\"delegateAllocations\":\"The amount to send to delegates instead of adding to the local balance.\",\"fundingCycle\":\"The project's funding cycle during which payment was made.\",\"memo\":\"A memo that should be passed along to the emitted event.\",\"tokenCount\":\"The number of project tokens that were minted, as a fixed point number with 18 decimals.\"}},\"recordRedemptionFor(address,uint256,uint256,string,bytes)\":{\"details\":\"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.The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\",\"params\":{\"_holder\":\"The account that is having its tokens redeemed.\",\"_memo\":\"A memo to pass along to the emitted event.\",\"_metadata\":\"Bytes to send along to the data source, if one is provided.\",\"_projectId\":\"The ID of the project to which the tokens being redeemed belong.\",\"_tokenCount\":\"The number of project tokens to redeem, as a fixed point number with 18 decimals.\"},\"returns\":{\"delegateAllocations\":\"The amount to send to delegates instead of sending to the beneficiary.\",\"fundingCycle\":\"The funding cycle during which the redemption was made.\",\"memo\":\"A memo that should be passed along to the emitted event.\",\"reclaimAmount\":\"The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\"}},\"recordUsedAllowanceOf(uint256,uint256,uint256)\":{\"details\":\"The msg.sender must be an IJBSingleTokenPaymentTerminal. \",\"params\":{\"_amount\":\"The amount to use from the allowance, as a fixed point number. \",\"_currency\":\"The currency of the `_amount`. Must match the currency of the overflow allowance.\",\"_projectId\":\"The ID of the project to use the allowance of.\"},\"returns\":{\"fundingCycle\":\"The funding cycle during which the overflow allowance is being used.\",\"usedAmount\":\"The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\"}}},\"stateVariables\":{\"balanceOf\":{\"details\":\"The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal. _terminal The terminal to which the balance applies. _projectId The ID of the project to get the balance of.\"},\"usedDistributionLimitOf\":{\"details\":\"Increases as projects use their preconfigured distribution limits.The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal. _terminal The terminal to which the used distribution limit applies. _projectId The ID of the project to get the used distribution limit of. _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\"},\"usedOverflowAllowanceOf\":{\"details\":\"Increases as projects use their allowance.The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal. _terminal The terminal to which the overflow allowance applies. _projectId The ID of the project to get the used overflow allowance of. _configuration The configuration of the during which the allowance was used.\"}},\"version\":1},\"userdoc\":{\"errors\":{\"PRBMath__MulDivOverflow(uint256,uint256)\":[{\"notice\":\"Emitted when the result overflows uint256.\"}]},\"kind\":\"user\",\"methods\":{\"balanceOf(address,uint256)\":{\"notice\":\"The amount of tokens that each project has for each terminal, in terms of the terminal's token.\"},\"currentOverflowOf(address,uint256)\":{\"notice\":\"Gets the current overflowed amount in a terminal for a specified project.\"},\"currentReclaimableOverflowOf(address,uint256,uint256,bool)\":{\"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.\"},\"currentReclaimableOverflowOf(uint256,uint256,uint256,uint256)\":{\"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.\"},\"currentTotalOverflowOf(uint256,uint256,uint256)\":{\"notice\":\"Gets the current overflowed amount for a specified project across all terminals.\"},\"directory()\":{\"notice\":\"The directory of terminals and controllers for projects.\"},\"fundingCycleStore()\":{\"notice\":\"The contract storing all funding cycle configurations.\"},\"prices()\":{\"notice\":\"The contract that exposes price feeds.\"},\"recordAddedBalanceFor(uint256,uint256)\":{\"notice\":\"Records newly added funds for the project.\"},\"recordDistributionFor(uint256,uint256,uint256)\":{\"notice\":\"Records newly distributed funds for a project.\"},\"recordMigration(uint256)\":{\"notice\":\"Records the migration of funds from this store.\"},\"recordPaymentFrom(address,(address,uint256,uint256,uint256),uint256,uint256,address,string,bytes)\":{\"notice\":\"Records newly contributed tokens to a project.\"},\"recordRedemptionFor(address,uint256,uint256,string,bytes)\":{\"notice\":\"Records newly redeemed tokens of a project.\"},\"recordUsedAllowanceOf(uint256,uint256,uint256)\":{\"notice\":\"Records newly used allowance funds of a project.\"},\"usedDistributionLimitOf(address,uint256,uint256)\":{\"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.\"},\"usedOverflowAllowanceOf(address,uint256,uint256)\":{\"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.\"}},\"notice\":\"Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/JBSingleTokenPaymentTerminalStore.sol\":\"JBSingleTokenPaymentTerminalStore\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/security/ReentrancyGuard.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuard {\\n // Booleans are more expensive than uint256 or any type that takes up a full\\n // word because each write operation emits an extra SLOAD to first read the\\n // slot's contents, replace the bits taken up by the boolean, and then write\\n // back. This is the compiler's defense against contract upgrades and\\n // pointer aliasing, and it cannot be disabled.\\n\\n // The values being non-zero value makes deployment a bit more expensive,\\n // but in exchange the refund on every call to nonReentrant will be lower in\\n // amount. Since refunds are capped to a percentage of the total\\n // transaction's gas, it is best to keep them low in cases like this one, to\\n // increase the likelihood of the full refund coming into effect.\\n uint256 private constant _NOT_ENTERED = 1;\\n uint256 private constant _ENTERED = 2;\\n\\n uint256 private _status;\\n\\n constructor() {\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and making it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n // On the first call to nonReentrant, _notEntered will be true\\n require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n _status = _ENTERED;\\n\\n _;\\n\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n _status = _NOT_ENTERED;\\n }\\n}\\n\",\"keccak256\":\"0x0e9621f60b2faabe65549f7ed0f24e8853a45c1b7990d47e8160e523683f3935\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool _approved) external;\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x516a22876c1fab47f49b1bc22b4614491cd05338af8bd2e7b382da090a079990\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"@paulrberg/contracts/math/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\nimport \\\"prb-math/contracts/PRBMath.sol\\\";\\n\",\"keccak256\":\"0x42821345981bc0434a90ba2268a2f5278dfe9e38166981d72fc7f3b776a29495\",\"license\":\"Unlicense\"},\"contracts/JBSingleTokenPaymentTerminalStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\\nimport '@paulrberg/contracts/math/PRBMath.sol';\\nimport './interfaces/IJBController.sol';\\nimport './interfaces/IJBFundingCycleDataSource.sol';\\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\\nimport './libraries/JBConstants.sol';\\nimport './libraries/JBCurrencies.sol';\\nimport './libraries/JBFixedPointNumber.sol';\\nimport './libraries/JBFundingCycleMetadataResolver.sol';\\nimport './structs/JBPayDelegateAllocation.sol';\\nimport './structs/JBPayParamsData.sol';\\n\\n/**\\n @notice\\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\\n\\n @dev\\n Adheres to:\\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n\\n @dev\\n Inherits from -\\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\\n*/\\ncontract JBSingleTokenPaymentTerminalStore is ReentrancyGuard, IJBSingleTokenPaymentTerminalStore {\\n // A library that parses the packed funding cycle metadata into a friendlier format.\\n using JBFundingCycleMetadataResolver for JBFundingCycle;\\n\\n //*********************************************************************//\\n // --------------------------- custom errors ------------------------- //\\n //*********************************************************************//\\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\\n error CURRENCY_MISMATCH();\\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\\n error FUNDING_CYCLE_PAYMENT_PAUSED();\\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\\n error FUNDING_CYCLE_REDEEM_PAUSED();\\n error INADEQUATE_CONTROLLER_ALLOWANCE();\\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\\n error INSUFFICIENT_TOKENS();\\n error INVALID_FUNDING_CYCLE();\\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\\n\\n //*********************************************************************//\\n // -------------------------- private constants ---------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \\n */\\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\\n\\n //*********************************************************************//\\n // ---------------- public immutable stored properties --------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The directory of terminals and controllers for projects.\\n */\\n IJBDirectory public immutable override directory;\\n\\n /**\\n @notice\\n The contract storing all funding cycle configurations.\\n */\\n IJBFundingCycleStore public immutable override fundingCycleStore;\\n\\n /**\\n @notice\\n The contract that exposes price feeds.\\n */\\n IJBPrices public immutable override prices;\\n\\n //*********************************************************************//\\n // --------------------- public stored properties -------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\\n\\n @dev\\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\\n\\n _terminal The terminal to which the balance applies.\\n _projectId The ID of the project to get the balance of.\\n */\\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\\n\\n /**\\n @notice\\n 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.\\n\\n @dev\\n Increases as projects use their preconfigured distribution limits.\\n\\n @dev\\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\\n\\n _terminal The terminal to which the used distribution limit applies.\\n _projectId The ID of the project to get the used distribution limit of.\\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\\n */\\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\\n public\\n override usedDistributionLimitOf;\\n\\n /**\\n @notice\\n 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.\\n\\n @dev\\n Increases as projects use their allowance.\\n\\n @dev\\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\\n\\n _terminal The terminal to which the overflow allowance applies.\\n _projectId The ID of the project to get the used overflow allowance of.\\n _configuration The configuration of the during which the allowance was used.\\n */\\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\\n public\\n override usedOverflowAllowanceOf;\\n\\n //*********************************************************************//\\n // ------------------------- external views -------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Gets the current overflowed amount in a terminal for a specified project.\\n\\n @dev\\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\\n\\n @param _terminal The terminal for which the overflow is being calculated.\\n @param _projectId The ID of the project to get overflow for.\\n\\n @return The current amount of overflow that project has in the specified terminal.\\n */\\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\\n external\\n view\\n override\\n returns (uint256)\\n {\\n // Return the overflow during the project's current funding cycle.\\n return\\n _overflowDuring(\\n _terminal,\\n _projectId,\\n fundingCycleStore.currentOf(_projectId),\\n _terminal.currency()\\n );\\n }\\n\\n /**\\n @notice\\n Gets the current overflowed amount for a specified project across all terminals.\\n\\n @param _projectId The ID of the project to get total overflow for.\\n @param _decimals The number of decimals that the fixed point overflow should include.\\n @param _currency The currency that the total overflow should be in terms of.\\n\\n @return The current total amount of overflow that project has across all terminals.\\n */\\n function currentTotalOverflowOf(\\n uint256 _projectId,\\n uint256 _decimals,\\n uint256 _currency\\n ) external view override returns (uint256) {\\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\\n }\\n\\n /**\\n @notice\\n 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.\\n\\n @dev \\n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\\n\\n @dev\\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\\n\\n @dev\\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\\n\\n @param _terminal The terminal from which the reclaimable amount would come.\\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\\n @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`.\\n\\n @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`.\\n */\\n function currentReclaimableOverflowOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n bool _useTotalOverflow\\n ) external view override returns (uint256) {\\n // Get a reference to the project's current funding cycle.\\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // Get the amount of current overflow.\\n // 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.\\n uint256 _currentOverflow = _useTotalOverflow\\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\\n\\n // If there's no overflow, there's no reclaimable overflow.\\n if (_currentOverflow == 0) return 0;\\n\\n // Get the number of outstanding tokens the project has.\\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\\n\\n // Can't redeem more tokens that is in the supply.\\n if (_tokenCount > _totalSupply) return 0;\\n\\n // Return the reclaimable overflow amount.\\n return\\n _reclaimableOverflowDuring(\\n _projectId,\\n _fundingCycle,\\n _tokenCount,\\n _totalSupply,\\n _currentOverflow\\n );\\n }\\n\\n /**\\n @notice\\n 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.\\n\\n @dev \\n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\\n\\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\\n\\n @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`.\\n */\\n function currentReclaimableOverflowOf(\\n uint256 _projectId,\\n uint256 _tokenCount,\\n uint256 _totalSupply,\\n uint256 _overflow\\n ) external view override returns (uint256) {\\n // If there's no overflow, there's no reclaimable overflow.\\n if (_overflow == 0) return 0;\\n\\n // Can't redeem more tokens that is in the supply.\\n if (_tokenCount > _totalSupply) return 0;\\n\\n // Get a reference to the project's current funding cycle.\\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // Return the reclaimable overflow amount.\\n return\\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\\n }\\n\\n //*********************************************************************//\\n // -------------------------- constructor ---------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @param _directory A contract storing directories of terminals and controllers for each project.\\n @param _fundingCycleStore A contract storing all funding cycle configurations.\\n @param _prices A contract that exposes price feeds.\\n */\\n constructor(\\n IJBDirectory _directory,\\n IJBFundingCycleStore _fundingCycleStore,\\n IJBPrices _prices\\n ) {\\n directory = _directory;\\n fundingCycleStore = _fundingCycleStore;\\n prices = _prices;\\n }\\n\\n //*********************************************************************//\\n // ---------------------- external transactions ---------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Records newly contributed tokens to a project.\\n\\n @dev\\n 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.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\\n\\n @param _payer The original address that sent the payment to the terminal.\\n @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.\\n @param _projectId The ID of the project being paid.\\n @param _baseWeightCurrency The currency to base token issuance on.\\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\\n @param _metadata Bytes to send along to the data source, if one is provided.\\n\\n @return fundingCycle The project's funding cycle during which payment was made.\\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\\n @return memo A memo that should be passed along to the emitted event.\\n */\\n function recordPaymentFrom(\\n address _payer,\\n JBTokenAmount calldata _amount,\\n uint256 _projectId,\\n uint256 _baseWeightCurrency,\\n address _beneficiary,\\n string calldata _memo,\\n bytes memory _metadata\\n )\\n external\\n override\\n nonReentrant\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 tokenCount,\\n JBPayDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n )\\n {\\n // Get a reference to the current funding cycle for the project.\\n fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // The project must have a funding cycle configured.\\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\\n\\n // Must not be paused.\\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\\n\\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\\n uint256 _weight;\\n\\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\\n // Create the params that'll be sent to the data source.\\n JBPayParamsData memory _data = JBPayParamsData(\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n _payer,\\n _amount,\\n _projectId,\\n fundingCycle.configuration,\\n _beneficiary,\\n fundingCycle.weight,\\n fundingCycle.reservedRate(),\\n _memo,\\n _metadata\\n );\\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\\n .payParams(_data);\\n }\\n // Otherwise use the funding cycle's weight\\n else {\\n _weight = fundingCycle.weight;\\n memo = _memo;\\n }\\n\\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\\n {\\n // Keep a reference to the amount that should be added to the project's balance.\\n uint256 _balanceDiff = _amount.value;\\n\\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\\n if (delegateAllocations.length != 0) {\\n for (uint256 _i; _i < delegateAllocations.length; ) {\\n // Get a reference to the amount to be delegated.\\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\\n\\n // Validate if non-zero.\\n if (_delegatedAmount != 0) {\\n // Can't delegate more than was paid.\\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\\n\\n // Decrement the total amount being added to the balance.\\n _balanceDiff = _balanceDiff - _delegatedAmount;\\n }\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n\\n // If there's no amount being recorded, there's nothing left to do.\\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\\n\\n // Add the correct balance difference to the token balance of the project.\\n if (_balanceDiff != 0)\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\\n _balanceDiff;\\n }\\n\\n // If there's no weight, token count must be 0 so there's nothing left to do.\\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\\n\\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\\n uint256 _decimals = _amount.decimals;\\n\\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\\n // 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`.\\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\\n ? 10**_decimals\\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\\n\\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\\n }\\n\\n /**\\n @notice\\n Records newly redeemed tokens of a project.\\n\\n @dev\\n 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.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\\n\\n @param _holder The account that is having its tokens redeemed.\\n @param _projectId The ID of the project to which the tokens being redeemed belong.\\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Bytes to send along to the data source, if one is provided.\\n\\n @return fundingCycle The funding cycle during which the redemption was made.\\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\\n @return memo A memo that should be passed along to the emitted event.\\n */\\n function recordRedemptionFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n string memory _memo,\\n bytes memory _metadata\\n )\\n external\\n override\\n nonReentrant\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 reclaimAmount,\\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n )\\n {\\n // Get a reference to the project's current funding cycle.\\n fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // The current funding cycle must not be paused.\\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\\n\\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\\n {\\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\\n JBTokenAmount memory _reclaimedTokenAmount;\\n uint256 _currentOverflow;\\n uint256 _totalSupply;\\n\\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\\n {\\n // Get a reference to the terminal's tokens.\\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\\n\\n // Get a reference to the terminal's decimals.\\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\\n\\n // Get areference to the terminal's currency.\\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\\n\\n // Get the amount of current overflow.\\n // 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.\\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\\n : _overflowDuring(\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n _projectId,\\n fundingCycle,\\n _currency\\n );\\n\\n // Get the number of outstanding tokens the project has.\\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\\n _projectId,\\n fundingCycle.reservedRate()\\n );\\n\\n // Can't redeem more tokens that is in the supply.\\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\\n\\n if (_currentOverflow != 0)\\n // Calculate reclaim amount using the current overflow amount.\\n reclaimAmount = _reclaimableOverflowDuring(\\n _projectId,\\n fundingCycle,\\n _tokenCount,\\n _totalSupply,\\n _currentOverflow\\n );\\n\\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\\n }\\n\\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\\n {\\n // Get a reference to the ballot state.\\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\\n\\n // Create the params that'll be sent to the data source.\\n JBRedeemParamsData memory _data = JBRedeemParamsData(\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n _holder,\\n _projectId,\\n fundingCycle.configuration,\\n _tokenCount,\\n _totalSupply,\\n _currentOverflow,\\n _reclaimedTokenAmount,\\n fundingCycle.useTotalOverflowForRedemptions(),\\n _state == JBBallotState.Active\\n ? fundingCycle.ballotRedemptionRate()\\n : fundingCycle.redemptionRate(),\\n _memo,\\n _metadata\\n );\\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\\n fundingCycle.dataSource()\\n ).redeemParams(_data);\\n }\\n } else {\\n memo = _memo;\\n }\\n }\\n\\n // Keep a reference to the amount that should be subtracted from the project's balance.\\n uint256 _balanceDiff = reclaimAmount;\\n\\n if (delegateAllocations.length != 0) {\\n // Validate all delegated amounts.\\n for (uint256 _i; _i < delegateAllocations.length; ) {\\n // Get a reference to the amount to be delegated.\\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\\n\\n // Validate if non-zero.\\n if (_delegatedAmount != 0)\\n // Increment the total amount being subtracted from the balance.\\n _balanceDiff = _balanceDiff + _delegatedAmount;\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n\\n // The amount being reclaimed must be within the project's balance.\\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\\n\\n // Remove the reclaimed funds from the project's balance.\\n if (_balanceDiff != 0) {\\n unchecked {\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\\n _balanceDiff;\\n }\\n }\\n }\\n\\n /**\\n @notice\\n Records newly distributed funds for a project.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \\n\\n @param _projectId The ID of the project that is having funds distributed.\\n @param _amount The amount to use from the distribution limit, as a fixed point number.\\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\\n\\n @return fundingCycle The funding cycle during which the distribution was made.\\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\\n */\\n function recordDistributionFor(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n )\\n external\\n override\\n nonReentrant\\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\\n {\\n // Get a reference to the project's current funding cycle.\\n fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // The funding cycle must not be configured to have distributions paused.\\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\\n\\n // The new total amount that has been distributed during this funding cycle.\\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\\n IJBSingleTokenPaymentTerminal(msg.sender)\\n ][_projectId][fundingCycle.number] + _amount;\\n\\n // Amount must be within what is still distributable.\\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\\n directory.controllerOf(_projectId)\\n ).distributionLimitOf(\\n _projectId,\\n fundingCycle.configuration,\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n IJBSingleTokenPaymentTerminal(msg.sender).token()\\n );\\n\\n // Make sure the new used amount is within the distribution limit.\\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\\n\\n // Make sure the currencies match.\\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\\n\\n // Get a reference to the terminal's currency.\\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\\n\\n // Convert the amount to the balance's currency.\\n distributedAmount = (_currency == _balanceCurrency)\\n ? _amount\\n : PRBMath.mulDiv(\\n _amount,\\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\\n );\\n\\n // The amount being distributed must be available.\\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\\n\\n // Store the new amount.\\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\\n fundingCycle.number\\n ] = _newUsedDistributionLimitOf;\\n\\n // Removed the distributed funds from the project's token balance.\\n unchecked {\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\\n distributedAmount;\\n }\\n }\\n\\n /**\\n @notice\\n Records newly used allowance funds of a project.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \\n\\n @param _projectId The ID of the project to use the allowance of.\\n @param _amount The amount to use from the allowance, as a fixed point number. \\n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\\n\\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\\n */\\n function recordUsedAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n )\\n external\\n override\\n nonReentrant\\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\\n {\\n // Get a reference to the project's current funding cycle.\\n fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\\n IJBSingleTokenPaymentTerminal(msg.sender)\\n ][_projectId][fundingCycle.configuration] + _amount;\\n\\n // There must be sufficient allowance available.\\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\\n directory.controllerOf(_projectId)\\n ).overflowAllowanceOf(\\n _projectId,\\n fundingCycle.configuration,\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n IJBSingleTokenPaymentTerminal(msg.sender).token()\\n );\\n\\n // Make sure the new used amount is within the allowance.\\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\\n\\n // Make sure the currencies match.\\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\\n\\n // Get a reference to the terminal's currency.\\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\\n\\n // Convert the amount to this store's terminal's token.\\n usedAmount = (_currency == _balanceCurrency)\\n ? _amount\\n : PRBMath.mulDiv(\\n _amount,\\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\\n );\\n\\n // The amount being distributed must be available in the overflow.\\n if (\\n usedAmount >\\n _overflowDuring(\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n _projectId,\\n fundingCycle,\\n _balanceCurrency\\n )\\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\\n\\n // Store the incremented value.\\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\\n fundingCycle.configuration\\n ] = _newUsedOverflowAllowanceOf;\\n\\n // Update the project's balance.\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\\n usedAmount;\\n }\\n\\n /**\\n @notice\\n Records newly added funds for the project.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \\n\\n @param _projectId The ID of the project to which the funds being added belong.\\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\\n */\\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\\n // Increment the balance.\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\\n _amount;\\n }\\n\\n /**\\n @notice\\n Records the migration of funds from this store.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\\n\\n @param _projectId The ID of the project being migrated.\\n\\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\\n */\\n function recordMigration(uint256 _projectId)\\n external\\n override\\n nonReentrant\\n returns (uint256 balance)\\n {\\n // Get a reference to the project's current funding cycle.\\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // Migration must be allowed.\\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\\n\\n // Return the current balance.\\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\\n\\n // Set the balance to 0.\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\\n }\\n\\n //*********************************************************************//\\n // --------------------- private helper functions -------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\\n\\n @dev \\n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\\n\\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\\n @param _overflow The amount of overflow to make the calculation with.\\n\\n @return The amount of overflowed tokens that can be reclaimed.\\n */\\n function _reclaimableOverflowDuring(\\n uint256 _projectId,\\n JBFundingCycle memory _fundingCycle,\\n uint256 _tokenCount,\\n uint256 _totalSupply,\\n uint256 _overflow\\n ) private view returns (uint256) {\\n // If the amount being redeemed is the total supply, return the rest of the overflow.\\n if (_tokenCount == _totalSupply) return _overflow;\\n\\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\\n JBBallotState.Active\\n ? _fundingCycle.ballotRedemptionRate()\\n : _fundingCycle.redemptionRate();\\n\\n // If the redemption rate is 0, nothing is claimable.\\n if (_redemptionRate == 0) return 0;\\n\\n // Get a reference to the linear proportion.\\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\\n\\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\\n\\n return\\n PRBMath.mulDiv(\\n _base,\\n _redemptionRate +\\n PRBMath.mulDiv(\\n _tokenCount,\\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\\n _totalSupply\\n ),\\n JBConstants.MAX_REDEMPTION_RATE\\n );\\n }\\n\\n /**\\n @notice\\n Gets the amount that is overflowing when measured from the specified funding cycle.\\n\\n @dev\\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\\n\\n @param _terminal The terminal for which the overflow is being calculated.\\n @param _projectId The ID of the project to get overflow for.\\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\\n\\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\\n */\\n function _overflowDuring(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n JBFundingCycle memory _fundingCycle,\\n uint256 _balanceCurrency\\n ) private view returns (uint256) {\\n // Get the current balance of the project.\\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\\n\\n // If there's no balance, there's no overflow.\\n if (_balanceOf == 0) return 0;\\n\\n // Get a reference to the distribution limit during the funding cycle.\\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\\n directory.controllerOf(_projectId)\\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\\n\\n // Get a reference to the amount still distributable during the funding cycle.\\n uint256 _distributionLimitRemaining = _distributionLimit -\\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\\n\\n // Convert the _distributionRemaining to be in terms of the provided currency.\\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\\n _distributionLimitRemaining = PRBMath.mulDiv(\\n _distributionLimitRemaining,\\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\\n );\\n\\n // Overflow is the balance of this project minus the amount that can still be distributed.\\n unchecked {\\n return\\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\\n }\\n }\\n\\n /**\\n @notice\\n Gets the amount that is currently overflowing across all of a project's terminals. \\n\\n @dev\\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\\n\\n @param _projectId The ID of the project to get the total overflow for.\\n @param _decimals The number of decimals that the fixed point overflow should include.\\n @param _currency The currency that the overflow should be in terms of.\\n\\n @return overflow The total overflow of a project's funds.\\n */\\n function _currentTotalOverflowOf(\\n uint256 _projectId,\\n uint256 _decimals,\\n uint256 _currency\\n ) private view returns (uint256) {\\n // Get a reference to the project's terminals.\\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\\n\\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\\n uint256 _ethOverflow;\\n\\n // Add the current ETH overflow for each terminal.\\n for (uint256 _i; _i < _terminals.length; ) {\\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\\n unchecked {\\n ++_i;\\n }\\n }\\n\\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.ETH\\n ? _ethOverflow\\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.ETH, _currency, 18));\\n\\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\\n return\\n (_decimals == 18)\\n ? _totalOverflow18Decimal\\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\\n }\\n}\\n\",\"keccak256\":\"0x17c0330168982f5da39eb12537ff22871b2d73220ca1012c1ad59d6999db7dd6\",\"license\":\"MIT\"},\"contracts/enums/JBBallotState.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nenum JBBallotState {\\n Active,\\n Approved,\\n Failed\\n}\\n\",\"keccak256\":\"0x891fcac63470398b3a11239da7feba6b07d640809fcefd2404303b823d7378f8\",\"license\":\"MIT\"},\"contracts/interfaces/IJBController.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBFundAccessConstraints.sol';\\nimport './../structs/JBFundingCycleData.sol';\\nimport './../structs/JBFundingCycleMetadata.sol';\\nimport './../structs/JBGroupedSplits.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBMigratable.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBSplitsStore.sol';\\nimport './IJBTokenStore.sol';\\n\\ninterface IJBController is IERC165 {\\n event LaunchProject(uint256 configuration, uint256 projectId, string memo, address caller);\\n\\n event LaunchFundingCycles(uint256 configuration, uint256 projectId, string memo, address caller);\\n\\n event ReconfigureFundingCycles(\\n uint256 configuration,\\n uint256 projectId,\\n string memo,\\n address caller\\n );\\n\\n event SetFundAccessConstraints(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n JBFundAccessConstraints constraints,\\n address caller\\n );\\n\\n event DistributeReservedTokens(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address beneficiary,\\n uint256 tokenCount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n address caller\\n );\\n\\n event DistributeToReservedTokenSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n uint256 tokenCount,\\n address caller\\n );\\n\\n event MintTokens(\\n address indexed beneficiary,\\n uint256 indexed projectId,\\n uint256 tokenCount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n uint256 reservedRate,\\n address caller\\n );\\n\\n event BurnTokens(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 tokenCount,\\n string memo,\\n address caller\\n );\\n\\n event Migrate(uint256 indexed projectId, IJBMigratable to, address caller);\\n\\n event PrepMigration(uint256 indexed projectId, address from, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function tokenStore() external view returns (IJBTokenStore);\\n\\n function splitsStore() external view returns (IJBSplitsStore);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function reservedTokenBalanceOf(uint256 _projectId, uint256 _reservedRate)\\n external\\n view\\n returns (uint256);\\n\\n function distributionLimitOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n IJBPaymentTerminal _terminal,\\n address _token\\n ) external view returns (uint256 distributionLimit, uint256 distributionLimitCurrency);\\n\\n function overflowAllowanceOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n IJBPaymentTerminal _terminal,\\n address _token\\n ) external view returns (uint256 overflowAllowance, uint256 overflowAllowanceCurrency);\\n\\n function totalOutstandingTokensOf(uint256 _projectId, uint256 _reservedRate)\\n external\\n view\\n returns (uint256);\\n\\n function getFundingCycleOf(uint256 _projectId, uint256 _configuration)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function latestConfiguredFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (\\n JBFundingCycle memory,\\n JBFundingCycleMetadata memory metadata,\\n JBBallotState\\n );\\n\\n function currentFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function queuedFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function launchProjectFor(\\n address _owner,\\n JBProjectMetadata calldata _projectMetadata,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n IJBPaymentTerminal[] memory _terminals,\\n string calldata _memo\\n ) external returns (uint256 projectId);\\n\\n function launchFundingCyclesFor(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n IJBPaymentTerminal[] memory _terminals,\\n string calldata _memo\\n ) external returns (uint256 configuration);\\n\\n function reconfigureFundingCyclesOf(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n string calldata _memo\\n ) external returns (uint256);\\n\\n function mintTokensOf(\\n uint256 _projectId,\\n uint256 _tokenCount,\\n address _beneficiary,\\n string calldata _memo,\\n bool _preferClaimedTokens,\\n bool _useReservedRate\\n ) external returns (uint256 beneficiaryTokenCount);\\n\\n function burnTokensOf(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n string calldata _memo,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function distributeReservedTokensOf(uint256 _projectId, string memory _memo)\\n external\\n returns (uint256);\\n\\n function migrate(uint256 _projectId, IJBMigratable _to) external;\\n}\\n\",\"keccak256\":\"0xb1ee4b41f2a06f28f69c74cb729b8964f2e75f3c545a68f85bd9082b5575bc85\",\"license\":\"MIT\"},\"contracts/interfaces/IJBDirectory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBProjects.sol';\\n\\ninterface IJBDirectory {\\n event SetController(uint256 indexed projectId, address indexed controller, address caller);\\n\\n event AddTerminal(uint256 indexed projectId, IJBPaymentTerminal indexed terminal, address caller);\\n\\n event SetTerminals(uint256 indexed projectId, IJBPaymentTerminal[] terminals, address caller);\\n\\n event SetPrimaryTerminal(\\n uint256 indexed projectId,\\n address indexed token,\\n IJBPaymentTerminal indexed terminal,\\n address caller\\n );\\n\\n event SetIsAllowedToSetFirstController(address indexed addr, bool indexed flag, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function controllerOf(uint256 _projectId) external view returns (address);\\n\\n function isAllowedToSetFirstController(address _address) external view returns (bool);\\n\\n function terminalsOf(uint256 _projectId) external view returns (IJBPaymentTerminal[] memory);\\n\\n function isTerminalOf(uint256 _projectId, IJBPaymentTerminal _terminal)\\n external\\n view\\n returns (bool);\\n\\n function primaryTerminalOf(uint256 _projectId, address _token)\\n external\\n view\\n returns (IJBPaymentTerminal);\\n\\n function setControllerOf(uint256 _projectId, address _controller) external;\\n\\n function setTerminalsOf(uint256 _projectId, IJBPaymentTerminal[] calldata _terminals) external;\\n\\n function setPrimaryTerminalOf(\\n uint256 _projectId,\\n address _token,\\n IJBPaymentTerminal _terminal\\n ) external;\\n\\n function setIsAllowedToSetFirstController(address _address, bool _flag) external;\\n}\\n\",\"keccak256\":\"0x715321646db00514d1355ed43c40cd3f01e94959552fd07797b315d9c49cdb1d\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleBallot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../enums/JBBallotState.sol';\\n\\ninterface IJBFundingCycleBallot is IERC165 {\\n function duration() external view returns (uint256);\\n\\n function stateOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n uint256 _start\\n ) external view returns (JBBallotState);\\n}\\n\",\"keccak256\":\"0x49553a56209237846bc400cf27f260824a6bd06fd8094a7eb5abb9de75779598\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleDataSource.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBPayDelegateAllocation.sol';\\nimport './../structs/JBPayParamsData.sol';\\nimport './../structs/JBRedeemParamsData.sol';\\nimport './../structs/JBRedemptionDelegateAllocation.sol';\\n\\n/**\\n @title\\n Datasource\\n\\n @notice\\n The datasource is called by JBPaymentTerminal on pay and redemption, and provide an extra layer of logic to use \\n a custom weight, a custom memo and/or a pay/redeem delegate\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n*/\\ninterface IJBFundingCycleDataSource is IERC165 {\\n /**\\n @notice\\n The datasource implementation for JBPaymentTerminal.pay(..)\\n\\n @param _data the data passed to the data source in terminal.pay(..), as a JBPayParamsData struct:\\n IJBPaymentTerminal terminal;\\n address payer;\\n JBTokenAmount amount;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n address beneficiary;\\n uint256 weight;\\n uint256 reservedRate;\\n string memo;\\n bytes metadata;\\n\\n @return weight the weight to use to override the funding cycle weight\\n @return memo the memo to override the pay(..) memo\\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\\n */\\n function payParams(JBPayParamsData calldata _data)\\n external\\n returns (\\n uint256 weight,\\n string memory memo,\\n JBPayDelegateAllocation[] memory delegateAllocations\\n );\\n\\n /**\\n @notice\\n The datasource implementation for JBPaymentTerminal.redeemTokensOf(..)\\n\\n @param _data the data passed to the data source in terminal.redeemTokensOf(..), as a JBRedeemParamsData struct:\\n IJBPaymentTerminal terminal;\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 tokenCount;\\n uint256 totalSupply;\\n uint256 overflow;\\n JBTokenAmount reclaimAmount;\\n bool useTotalOverflow;\\n uint256 redemptionRate;\\n uint256 ballotRedemptionRate;\\n string memo;\\n bytes metadata;\\n\\n @return reclaimAmount The amount to claim, overriding the terminal logic.\\n @return memo The memo to override the redeemTokensOf(..) memo.\\n @return delegateAllocations The amount to send to delegates instead of adding to the beneficiary.\\n */\\n function redeemParams(JBRedeemParamsData calldata _data)\\n external\\n returns (\\n uint256 reclaimAmount,\\n string memory memo,\\n JBRedemptionDelegateAllocation[] memory delegateAllocations\\n );\\n}\\n\",\"keccak256\":\"0xa424abc146a61b69db83e511c064492da6fab6d8226e13d1580bc9fbc50d6738\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../enums/JBBallotState.sol';\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBFundingCycleData.sol';\\n\\ninterface IJBFundingCycleStore {\\n event Configure(\\n uint256 indexed configuration,\\n uint256 indexed projectId,\\n JBFundingCycleData data,\\n uint256 metadata,\\n uint256 mustStartAtOrAfter,\\n address caller\\n );\\n\\n event Init(uint256 indexed configuration, uint256 indexed projectId, uint256 indexed basedOn);\\n\\n function latestConfigurationOf(uint256 _projectId) external view returns (uint256);\\n\\n function get(uint256 _projectId, uint256 _configuration)\\n external\\n view\\n returns (JBFundingCycle memory);\\n\\n function latestConfiguredOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBBallotState ballotState);\\n\\n function queuedOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentBallotStateOf(uint256 _projectId) external view returns (JBBallotState);\\n\\n function configureFor(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n uint256 _metadata,\\n uint256 _mustStartAtOrAfter\\n ) external returns (JBFundingCycle memory fundingCycle);\\n}\\n\",\"keccak256\":\"0xaead823851433be0c2ddc8f8086813e6cd647de3a1bc0f7570a5d6b38c378b5a\",\"license\":\"MIT\"},\"contracts/interfaces/IJBMigratable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBMigratable {\\n function prepForMigrationOf(uint256 _projectId, address _from) external;\\n}\\n\",\"keccak256\":\"0xc81053e4b4754fc510aa04fecd3ab1460f01e3e27761e7a8c94f631a978ae127\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPayDelegate.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBDidPayData.sol';\\n\\n/**\\n @title\\n Pay delegate\\n\\n @notice\\n Delegate called after JBTerminal.pay(..) logic completion (if passed by the funding cycle datasource)\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n*/\\ninterface IJBPayDelegate is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.pay(..), after the execution of its logic\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control\\n \\n @param _data the data passed by the terminal, as a JBDidPayData struct:\\n address payer;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n JBTokenAmount amount;\\n JBTokenAmount forwardedAmount;\\n uint256 projectTokenCount;\\n address beneficiary;\\n bool preferClaimedTokens;\\n string memo;\\n bytes metadata;\\n */\\n function didPay(JBDidPayData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0xa797de18b69eceba117e1f0b3810cf3cc2d2791417d580a5bdc510d1b868ab26\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\n\\ninterface IJBPaymentTerminal is IERC165 {\\n function acceptsToken(address _token, uint256 _projectId) external view returns (bool);\\n\\n function currencyForToken(address _token) external view returns (uint256);\\n\\n function decimalsForToken(address _token) external view returns (uint256);\\n\\n // Return value must be a fixed point number with 18 decimals.\\n function currentEthOverflowOf(uint256 _projectId) external view returns (uint256);\\n\\n function pay(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable returns (uint256 beneficiaryTokenCount);\\n\\n function addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable;\\n}\\n\",\"keccak256\":\"0xb7826f5ed609359ce322c09e83236c47ba385df1c3cad3607e56fd0a2e00eee2\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPriceFeed.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBPriceFeed {\\n function currentPrice(uint256 _targetDecimals) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x57c71282fec1b34b00cf991ffed2e36031c393e35bfa7ca5d723eb6572fb7122\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPrices.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBPriceFeed.sol';\\n\\ninterface IJBPrices {\\n event AddFeed(uint256 indexed currency, uint256 indexed base, IJBPriceFeed feed);\\n\\n function feedFor(uint256 _currency, uint256 _base) external view returns (IJBPriceFeed);\\n\\n function priceFor(\\n uint256 _currency,\\n uint256 _base,\\n uint256 _decimals\\n ) external view returns (uint256);\\n\\n function addFeedFor(\\n uint256 _currency,\\n uint256 _base,\\n IJBPriceFeed _priceFeed\\n ) external;\\n}\\n\",\"keccak256\":\"0x82a175b1f4b95b506c98406576cd59cbe04615e3df24f9cf3587b61b8ee323b1\",\"license\":\"MIT\"},\"contracts/interfaces/IJBProjects.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBTokenUriResolver.sol';\\n\\ninterface IJBProjects is IERC721 {\\n event Create(\\n uint256 indexed projectId,\\n address indexed owner,\\n JBProjectMetadata metadata,\\n address caller\\n );\\n\\n event SetMetadata(uint256 indexed projectId, JBProjectMetadata metadata, address caller);\\n\\n event SetTokenUriResolver(IJBTokenUriResolver indexed resolver, address caller);\\n\\n function count() external view returns (uint256);\\n\\n function metadataContentOf(uint256 _projectId, uint256 _domain)\\n external\\n view\\n returns (string memory);\\n\\n function tokenUriResolver() external view returns (IJBTokenUriResolver);\\n\\n function createFor(address _owner, JBProjectMetadata calldata _metadata)\\n external\\n returns (uint256 projectId);\\n\\n function setMetadataOf(uint256 _projectId, JBProjectMetadata calldata _metadata) external;\\n\\n function setTokenUriResolver(IJBTokenUriResolver _newResolver) external;\\n}\\n\",\"keccak256\":\"0x7cfc021d0bd7e73b1ba8f4845d7d35e3419d6a14d3d25ca3a8010e7f91062fe4\",\"license\":\"MIT\"},\"contracts/interfaces/IJBRedemptionDelegate.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBDidRedeemData.sol';\\n\\n/**\\n @title\\n Redemption delegate\\n\\n @notice\\n Delegate called after JBTerminal.redeemTokensOf(..) logic completion (if passed by the funding cycle datasource)\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n*/\\ninterface IJBRedemptionDelegate is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.redeemTokensOf(..), after the execution of its logic\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control\\n \\n @param _data the data passed by the terminal, as a JBDidRedeemData struct:\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 projectTokenCount;\\n JBTokenAmount reclaimedAmount;\\n JBTokenAmount forwardedAmount;\\n address payable beneficiary;\\n string memo;\\n bytes metadata;\\n */\\n function didRedeem(JBDidRedeemData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0x172d2c0be65e72e54f71ae521907067f0fa30e8ca05c4f88826903208aa437e2\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSingleTokenPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBPaymentTerminal.sol';\\n\\ninterface IJBSingleTokenPaymentTerminal is IJBPaymentTerminal {\\n function token() external view returns (address);\\n\\n function currency() external view returns (uint256);\\n\\n function decimals() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xf6e78323caa9af7bbf024f44b2032a83fed0394e0b3a242a6346e73c85b2e46f\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSingleTokenPaymentTerminalStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBPayDelegateAllocation.sol';\\nimport './../structs/JBRedemptionDelegateAllocation.sol';\\nimport './../structs/JBTokenAmount.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBPrices.sol';\\nimport './IJBSingleTokenPaymentTerminal.sol';\\n\\ninterface IJBSingleTokenPaymentTerminalStore {\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function prices() external view returns (IJBPrices);\\n\\n function balanceOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\\n external\\n view\\n returns (uint256);\\n\\n function usedDistributionLimitOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _fundingCycleNumber\\n ) external view returns (uint256);\\n\\n function usedOverflowAllowanceOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _fundingCycleConfiguration\\n ) external view returns (uint256);\\n\\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\\n external\\n view\\n returns (uint256);\\n\\n function currentTotalOverflowOf(\\n uint256 _projectId,\\n uint256 _decimals,\\n uint256 _currency\\n ) external view returns (uint256);\\n\\n function currentReclaimableOverflowOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n bool _useTotalOverflow\\n ) external view returns (uint256);\\n\\n function currentReclaimableOverflowOf(\\n uint256 _projectId,\\n uint256 _tokenCount,\\n uint256 _totalSupply,\\n uint256 _overflow\\n ) external view returns (uint256);\\n\\n function recordPaymentFrom(\\n address _payer,\\n JBTokenAmount memory _amount,\\n uint256 _projectId,\\n uint256 _baseWeightCurrency,\\n address _beneficiary,\\n string calldata _memo,\\n bytes calldata _metadata\\n )\\n external\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 tokenCount,\\n JBPayDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n );\\n\\n function recordRedemptionFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n string calldata _memo,\\n bytes calldata _metadata\\n )\\n external\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 reclaimAmount,\\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n );\\n\\n function recordDistributionFor(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n ) external returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount);\\n\\n function recordUsedAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n ) external returns (JBFundingCycle memory fundingCycle, uint256 withdrawnAmount);\\n\\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external;\\n\\n function recordMigration(uint256 _projectId) external returns (uint256 balance);\\n}\\n\",\"keccak256\":\"0xd78929c9371fd7895b829ef5e4ad4b3786523c3580ac3f6f5f25d2b5941c0dd3\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSplitAllocator.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport '../structs/JBSplitAllocationData.sol';\\n\\n/**\\n @title\\n Split allocator\\n\\n @notice\\n Provide a way to process a single split with extra logic\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n\\n @dev\\n The contract address should be set as an allocator in the adequate split\\n*/\\ninterface IJBSplitAllocator is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.distributePayoutOf(..), during the processing of the split including it\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control. The token and/or eth are optimistically transfered\\n to the allocator for its logic.\\n \\n @param _data the data passed by the terminal, as a JBSplitAllocationData struct:\\n address token;\\n uint256 amount;\\n uint256 decimals;\\n uint256 projectId;\\n uint256 group;\\n JBSplit split;\\n */\\n function allocate(JBSplitAllocationData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0x5efb6f51fc161f42ff58989386ad99028e4039a0ba897d66f358c3dfcf686105\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSplitsStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBGroupedSplits.sol';\\nimport './../structs/JBSplit.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBProjects.sol';\\n\\ninterface IJBSplitsStore {\\n event SetSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n address caller\\n );\\n\\n function projects() external view returns (IJBProjects);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function splitsOf(\\n uint256 _projectId,\\n uint256 _domain,\\n uint256 _group\\n ) external view returns (JBSplit[] memory);\\n\\n function set(\\n uint256 _projectId,\\n uint256 _domain,\\n JBGroupedSplits[] memory _groupedSplits\\n ) external;\\n}\\n\",\"keccak256\":\"0x66dab3dd394e318b850401ca92c2963b906cc0ad5562fa5d4f6f850175d1c77a\",\"license\":\"MIT\"},\"contracts/interfaces/IJBToken.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBToken {\\n function projectId() external view returns (uint256);\\n\\n function decimals() external view returns (uint8);\\n\\n function totalSupply(uint256 _projectId) external view returns (uint256);\\n\\n function balanceOf(address _account, uint256 _projectId) external view returns (uint256);\\n\\n function mint(\\n uint256 _projectId,\\n address _account,\\n uint256 _amount\\n ) external;\\n\\n function burn(\\n uint256 _projectId,\\n address _account,\\n uint256 _amount\\n ) external;\\n\\n function approve(\\n uint256,\\n address _spender,\\n uint256 _amount\\n ) external;\\n\\n function transfer(\\n uint256 _projectId,\\n address _to,\\n uint256 _amount\\n ) external;\\n\\n function transferFrom(\\n uint256 _projectId,\\n address _from,\\n address _to,\\n uint256 _amount\\n ) external;\\n}\\n\",\"keccak256\":\"0xe8969210417736c85d71101bf1c0bd8ebbf9d1e62a93e758148bd5709a6c7097\",\"license\":\"MIT\"},\"contracts/interfaces/IJBTokenStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBProjects.sol';\\nimport './IJBToken.sol';\\n\\ninterface IJBTokenStore {\\n event Issue(\\n uint256 indexed projectId,\\n IJBToken indexed token,\\n string name,\\n string symbol,\\n address caller\\n );\\n\\n event Mint(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 amount,\\n bool tokensWereClaimed,\\n bool preferClaimedTokens,\\n address caller\\n );\\n\\n event Burn(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 amount,\\n uint256 initialUnclaimedBalance,\\n uint256 initialClaimedBalance,\\n bool preferClaimedTokens,\\n address caller\\n );\\n\\n event Claim(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 initialUnclaimedBalance,\\n uint256 amount,\\n address caller\\n );\\n\\n event Set(uint256 indexed projectId, IJBToken indexed newToken, address caller);\\n\\n event Transfer(\\n address indexed holder,\\n uint256 indexed projectId,\\n address indexed recipient,\\n uint256 amount,\\n address caller\\n );\\n\\n function tokenOf(uint256 _projectId) external view returns (IJBToken);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function unclaimedBalanceOf(address _holder, uint256 _projectId) external view returns (uint256);\\n\\n function unclaimedTotalSupplyOf(uint256 _projectId) external view returns (uint256);\\n\\n function totalSupplyOf(uint256 _projectId) external view returns (uint256);\\n\\n function balanceOf(address _holder, uint256 _projectId) external view returns (uint256 _result);\\n\\n function issueFor(\\n uint256 _projectId,\\n string calldata _name,\\n string calldata _symbol\\n ) external returns (IJBToken token);\\n\\n function setFor(uint256 _projectId, IJBToken _token) external;\\n\\n function burnFrom(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function mintFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function claimFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount\\n ) external;\\n\\n function transferFrom(\\n address _holder,\\n uint256 _projectId,\\n address _recipient,\\n uint256 _amount\\n ) external;\\n}\\n\",\"keccak256\":\"0x98459e3af050d41dfeffdc97f1c93330207ba450f8ff3613224b49a89eeca9c6\",\"license\":\"MIT\"},\"contracts/interfaces/IJBTokenUriResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBTokenUriResolver {\\n function getUri(uint256 _projectId) external view returns (string memory tokenUri);\\n}\\n\",\"keccak256\":\"0xd267fd8ca7c21c2c71794acdb9a98314c33a35fc559e0bf0897a6686d196d174\",\"license\":\"MIT\"},\"contracts/libraries/JBConstants.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/**\\n @notice\\n Global constants used across Juicebox contracts.\\n*/\\nlibrary JBConstants {\\n uint256 public constant MAX_RESERVED_RATE = 10_000;\\n uint256 public constant MAX_REDEMPTION_RATE = 10_000;\\n uint256 public constant MAX_DISCOUNT_RATE = 1_000_000_000;\\n uint256 public constant SPLITS_TOTAL_PERCENT = 1_000_000_000;\\n uint256 public constant MAX_FEE = 1_000_000_000;\\n uint256 public constant MAX_FEE_DISCOUNT = 1_000_000_000;\\n}\\n\",\"keccak256\":\"0x34362846a1cd428a8bdedf4ab6857e11402f345cb87b994b2e7fb6d2474b808d\",\"license\":\"MIT\"},\"contracts/libraries/JBCurrencies.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBCurrencies {\\n uint256 public constant ETH = 1;\\n uint256 public constant USD = 2;\\n}\\n\",\"keccak256\":\"0x7e417ff25c173608ee4fe6d9fc3dcd5e1458c78c889af12bac47b1189a436076\",\"license\":\"MIT\"},\"contracts/libraries/JBFixedPointNumber.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nlibrary JBFixedPointNumber {\\n function adjustDecimals(\\n uint256 _value,\\n uint256 _decimals,\\n uint256 _targetDecimals\\n ) internal pure returns (uint256) {\\n // If decimals need adjusting, multiply or divide the price by the decimal adjuster to get the normalized result.\\n if (_targetDecimals == _decimals) return _value;\\n else if (_targetDecimals > _decimals) return _value * 10**(_targetDecimals - _decimals);\\n else return _value / 10**(_decimals - _targetDecimals);\\n }\\n}\\n\",\"keccak256\":\"0x18efac48269f3a3bd7e9a1c770776f950e0afa86769e6f8b128002c3b8c6742c\",\"license\":\"MIT\"},\"contracts/libraries/JBFundingCycleMetadataResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBFundingCycleMetadata.sol';\\nimport './../structs/JBGlobalFundingCycleMetadata.sol';\\nimport './JBConstants.sol';\\nimport './JBGlobalFundingCycleMetadataResolver.sol';\\n\\nlibrary JBFundingCycleMetadataResolver {\\n function global(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (JBGlobalFundingCycleMetadata memory)\\n {\\n return JBGlobalFundingCycleMetadataResolver.expandMetadata(uint8(_fundingCycle.metadata >> 8));\\n }\\n\\n function reservedRate(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n return uint256(uint16(_fundingCycle.metadata >> 24));\\n }\\n\\n function redemptionRate(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n // Redemption rate is a number 0-10000. It's inverse was stored so the most common case of 100% results in no storage needs.\\n return JBConstants.MAX_REDEMPTION_RATE - uint256(uint16(_fundingCycle.metadata >> 40));\\n }\\n\\n function ballotRedemptionRate(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (uint256)\\n {\\n // Redemption rate is a number 0-10000. It's inverse was stored so the most common case of 100% results in no storage needs.\\n return JBConstants.MAX_REDEMPTION_RATE - uint256(uint16(_fundingCycle.metadata >> 56));\\n }\\n\\n function payPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 72) & 1) == 1;\\n }\\n\\n function distributionsPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 73) & 1) == 1;\\n }\\n\\n function redeemPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 74) & 1) == 1;\\n }\\n\\n function burnPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 75) & 1) == 1;\\n }\\n\\n function mintingAllowed(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 76) & 1) == 1;\\n }\\n\\n function terminalMigrationAllowed(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 77) & 1) == 1;\\n }\\n\\n function controllerMigrationAllowed(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 78) & 1) == 1;\\n }\\n\\n function shouldHoldFees(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 79) & 1) == 1;\\n }\\n\\n function preferClaimedTokenOverride(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 80) & 1) == 1;\\n }\\n\\n function useTotalOverflowForRedemptions(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 81) & 1) == 1;\\n }\\n\\n function useDataSourceForPay(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return (_fundingCycle.metadata >> 82) & 1 == 1;\\n }\\n\\n function useDataSourceForRedeem(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return (_fundingCycle.metadata >> 83) & 1 == 1;\\n }\\n\\n function dataSource(JBFundingCycle memory _fundingCycle) internal pure returns (address) {\\n return address(uint160(_fundingCycle.metadata >> 84));\\n }\\n\\n function metadata(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n return uint256(uint8(_fundingCycle.metadata >> 244));\\n }\\n\\n /**\\n @notice\\n Pack the funding cycle metadata.\\n\\n @param _metadata The metadata to validate and pack.\\n\\n @return packed The packed uint256 of all metadata params. The first 8 bits specify the version.\\n */\\n function packFundingCycleMetadata(JBFundingCycleMetadata memory _metadata)\\n internal\\n pure\\n returns (uint256 packed)\\n {\\n // version 1 in the bits 0-7 (8 bits).\\n packed = 1;\\n // global metadta in bits 8-23 (16 bits).\\n packed |=\\n JBGlobalFundingCycleMetadataResolver.packFundingCycleGlobalMetadata(_metadata.global) <<\\n 8;\\n // reserved rate in bits 24-39 (16 bits).\\n packed |= _metadata.reservedRate << 24;\\n // redemption rate in bits 40-55 (16 bits).\\n // redemption rate is a number 0-10000. Store the reverse so the most common case of 100% results in no storage needs.\\n packed |= (JBConstants.MAX_REDEMPTION_RATE - _metadata.redemptionRate) << 40;\\n // ballot redemption rate rate in bits 56-71 (16 bits).\\n // ballot redemption rate is a number 0-10000. Store the reverse so the most common case of 100% results in no storage needs.\\n packed |= (JBConstants.MAX_REDEMPTION_RATE - _metadata.ballotRedemptionRate) << 56;\\n // pause pay in bit 72.\\n if (_metadata.pausePay) packed |= 1 << 72;\\n // pause tap in bit 73.\\n if (_metadata.pauseDistributions) packed |= 1 << 73;\\n // pause redeem in bit 74.\\n if (_metadata.pauseRedeem) packed |= 1 << 74;\\n // pause burn in bit 75.\\n if (_metadata.pauseBurn) packed |= 1 << 75;\\n // allow minting in bit 76.\\n if (_metadata.allowMinting) packed |= 1 << 76;\\n // allow terminal migration in bit 77.\\n if (_metadata.allowTerminalMigration) packed |= 1 << 77;\\n // allow controller migration in bit 78.\\n if (_metadata.allowControllerMigration) packed |= 1 << 78;\\n // hold fees in bit 79.\\n if (_metadata.holdFees) packed |= 1 << 79;\\n // prefer claimed token override in bit 80.\\n if (_metadata.preferClaimedTokenOverride) packed |= 1 << 80;\\n // useTotalOverflowForRedemptions in bit 81.\\n if (_metadata.useTotalOverflowForRedemptions) packed |= 1 << 81;\\n // use pay data source in bit 82.\\n if (_metadata.useDataSourceForPay) packed |= 1 << 82;\\n // use redeem data source in bit 83.\\n if (_metadata.useDataSourceForRedeem) packed |= 1 << 83;\\n // data source address in bits 84-243.\\n packed |= uint256(uint160(address(_metadata.dataSource))) << 84;\\n // metadata in bits 244-252 (8 bits).\\n packed |= _metadata.metadata << 244;\\n }\\n\\n /**\\n @notice\\n Expand the funding cycle metadata.\\n\\n @param _fundingCycle The funding cycle having its metadata expanded.\\n\\n @return metadata The metadata object.\\n */\\n function expandMetadata(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (JBFundingCycleMetadata memory)\\n {\\n return\\n JBFundingCycleMetadata(\\n global(_fundingCycle),\\n reservedRate(_fundingCycle),\\n redemptionRate(_fundingCycle),\\n ballotRedemptionRate(_fundingCycle),\\n payPaused(_fundingCycle),\\n distributionsPaused(_fundingCycle),\\n redeemPaused(_fundingCycle),\\n burnPaused(_fundingCycle),\\n mintingAllowed(_fundingCycle),\\n terminalMigrationAllowed(_fundingCycle),\\n controllerMigrationAllowed(_fundingCycle),\\n shouldHoldFees(_fundingCycle),\\n preferClaimedTokenOverride(_fundingCycle),\\n useTotalOverflowForRedemptions(_fundingCycle),\\n useDataSourceForPay(_fundingCycle),\\n useDataSourceForRedeem(_fundingCycle),\\n dataSource(_fundingCycle),\\n metadata(_fundingCycle)\\n );\\n }\\n}\\n\",\"keccak256\":\"0x3d045c38593102cfb6ac67f3ddf2232e1ff5518d6d021423ae2681387599fbd3\",\"license\":\"MIT\"},\"contracts/libraries/JBGlobalFundingCycleMetadataResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport './../structs/JBFundingCycleMetadata.sol';\\n\\nlibrary JBGlobalFundingCycleMetadataResolver {\\n function setTerminalsAllowed(uint8 _data) internal pure returns (bool) {\\n return (_data & 1) == 1;\\n }\\n\\n function setControllerAllowed(uint8 _data) internal pure returns (bool) {\\n return ((_data >> 1) & 1) == 1;\\n }\\n\\n function transfersPaused(uint8 _data) internal pure returns (bool) {\\n return ((_data >> 2) & 1) == 1;\\n }\\n\\n /**\\n @notice\\n Pack the global funding cycle metadata.\\n\\n @param _metadata The metadata to validate and pack.\\n\\n @return packed The packed uint256 of all global metadata params. The first 8 bits specify the version.\\n */\\n function packFundingCycleGlobalMetadata(JBGlobalFundingCycleMetadata memory _metadata)\\n internal\\n pure\\n returns (uint256 packed)\\n {\\n // allow set terminals in bit 0.\\n if (_metadata.allowSetTerminals) packed |= 1;\\n // allow set controller in bit 1.\\n if (_metadata.allowSetController) packed |= 1 << 1;\\n // pause transfers in bit 2.\\n if (_metadata.pauseTransfers) packed |= 1 << 2;\\n }\\n\\n /**\\n @notice\\n Expand the global funding cycle metadata.\\n\\n @param _packedMetadata The packed metadata to expand.\\n\\n @return metadata The global metadata object.\\n */\\n function expandMetadata(uint8 _packedMetadata)\\n internal\\n pure\\n returns (JBGlobalFundingCycleMetadata memory metadata)\\n {\\n return\\n JBGlobalFundingCycleMetadata(\\n setTerminalsAllowed(_packedMetadata),\\n setControllerAllowed(_packedMetadata),\\n transfersPaused(_packedMetadata)\\n );\\n }\\n}\\n\",\"keccak256\":\"0x0d998f938026edeb755987a79421267cf860801161b5f171206a200b60f1061f\",\"license\":\"MIT\"},\"contracts/structs/JBDidPayData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member payer The address from which the payment originated.\\n @member projectId The ID of the project for which the payment was made.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the payment is being made.\\n @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.\\n @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.\\n @member projectTokenCount The number of project tokens minted for the beneficiary.\\n @member beneficiary The address to which the tokens were minted.\\n @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.\\n @member memo The memo that is being emitted alongside the payment.\\n @member metadata Extra data to send to the delegate.\\n*/\\nstruct JBDidPayData {\\n address payer;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n JBTokenAmount amount;\\n JBTokenAmount forwardedAmount;\\n uint256 projectTokenCount;\\n address beneficiary;\\n bool preferClaimedTokens;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0xf3c664309b37790f16047ae97b0459889ae0242dfcde7fc8902c8d10c7f8e6b6\",\"license\":\"MIT\"},\"contracts/structs/JBDidRedeemData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member holder The holder of the tokens being redeemed.\\n @member projectId The ID of the project with which the redeemed tokens are associated.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the redemption is being made.\\n @member projectTokenCount The number of project tokens being redeemed.\\n @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.\\n @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.\\n @member beneficiary The address to which the reclaimed amount will be sent.\\n @member memo The memo that is being emitted alongside the redemption.\\n @member metadata Extra data to send to the delegate.\\n*/\\nstruct JBDidRedeemData {\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 projectTokenCount;\\n JBTokenAmount reclaimedAmount;\\n JBTokenAmount forwardedAmount;\\n address payable beneficiary;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0xe2c401f39723a7ce915b8bef328744c66daaf57460843964b941456c2258a412\",\"license\":\"MIT\"},\"contracts/structs/JBFundAccessConstraints.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBPaymentTerminal.sol';\\n\\n/** \\n @member terminal The terminal within which the distribution limit and the overflow allowance applies.\\n @member token The token for which the fund access constraints apply.\\n @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.\\n @member distributionLimitCurrency The currency of the distribution limit.\\n @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.\\n @member overflowAllowanceCurrency The currency of the overflow allowance.\\n*/\\nstruct JBFundAccessConstraints {\\n IJBPaymentTerminal terminal;\\n address token;\\n uint256 distributionLimit;\\n uint256 distributionLimitCurrency;\\n uint256 overflowAllowance;\\n uint256 overflowAllowanceCurrency;\\n}\\n\",\"keccak256\":\"0x85ebaa57b788cbdedc7a3d0eec4892eda5d79db7c1a6103797f10d0d989775b2\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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.\\n @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.\\n @member basedOn The `configuration` of the funding cycle that was active when this cycle was created.\\n @member start The timestamp marking the moment from which the funding cycle is considered active. It is a unix timestamp measured in seconds.\\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n @member metadata Extra data that can be associated with a funding cycle.\\n*/\\nstruct JBFundingCycle {\\n uint256 number;\\n uint256 configuration;\\n uint256 basedOn;\\n uint256 start;\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n uint256 metadata;\\n}\\n\",\"keccak256\":\"0xcdd3ac9b6fa67e62ada88d09b73bc35ade1cd77d43db712289266a788928b4c2\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycleData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n*/\\nstruct JBFundingCycleData {\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n}\\n\",\"keccak256\":\"0x2aa6368bf4dfc5797e8b02a978293de0c777fae2658de2c825a103587240f3b0\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycleMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBGlobalFundingCycleMetadata.sol';\\n\\n/** \\n @member global Data used globally in non-migratable ecosystem contracts.\\n @member reservedRate The reserved rate of the funding cycle. This number is a percentage calculated out of `JBConstants.MAX_RESERVED_RATE`.\\n @member redemptionRate The redemption rate of the funding cycle. This number is a percentage calculated out of `JBConstants.MAX_REDEMPTION_RATE`.\\n @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`.\\n @member pausePay A flag indicating if the pay functionality should be paused during the funding cycle.\\n @member pauseDistributions A flag indicating if the distribute functionality should be paused during the funding cycle.\\n @member pauseRedeem A flag indicating if the redeem functionality should be paused during the funding cycle.\\n @member pauseBurn A flag indicating if the burn functionality should be paused during the funding cycle.\\n @member allowMinting A flag indicating if minting tokens should be allowed during this funding cycle.\\n @member allowTerminalMigration A flag indicating if migrating terminals should be allowed during this funding cycle.\\n @member allowControllerMigration A flag indicating if migrating controllers should be allowed during this funding cycle.\\n @member holdFees A flag indicating if fees should be held during this funding cycle.\\n @member preferClaimedTokenOverride A flag indicating if claimed tokens should always be prefered to unclaimed tokens when minting.\\n @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.\\n @member useDataSourceForPay A flag indicating if the data source should be used for pay transactions during this funding cycle.\\n @member useDataSourceForRedeem A flag indicating if the data source should be used for redeem transactions during this funding cycle.\\n @member dataSource The data source to use during this funding cycle.\\n @member metadata Metadata of the metadata, up to uint8 in size.\\n*/\\nstruct JBFundingCycleMetadata {\\n JBGlobalFundingCycleMetadata global;\\n uint256 reservedRate;\\n uint256 redemptionRate;\\n uint256 ballotRedemptionRate;\\n bool pausePay;\\n bool pauseDistributions;\\n bool pauseRedeem;\\n bool pauseBurn;\\n bool allowMinting;\\n bool allowTerminalMigration;\\n bool allowControllerMigration;\\n bool holdFees;\\n bool preferClaimedTokenOverride;\\n bool useTotalOverflowForRedemptions;\\n bool useDataSourceForPay;\\n bool useDataSourceForRedeem;\\n address dataSource;\\n uint256 metadata;\\n}\\n\",\"keccak256\":\"0x783604440cac8d176332eab28166f188ee5c230378c08cfc95fea4f7187dc77d\",\"license\":\"MIT\"},\"contracts/structs/JBGlobalFundingCycleMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member allowSetTerminals A flag indicating if setting terminals should be allowed during this funding cycle.\\n @member allowSetController A flag indicating if setting a new controller should be allowed during this funding cycle.\\n @member pauseTransfers A flag indicating if the project token transfer functionality should be paused during the funding cycle.\\n*/\\nstruct JBGlobalFundingCycleMetadata {\\n bool allowSetTerminals;\\n bool allowSetController;\\n bool pauseTransfers;\\n}\\n\",\"keccak256\":\"0x05d85530305fec6d6eca54cdbc2cd9110cbda0146598032b0203aa4b622944ff\",\"license\":\"MIT\"},\"contracts/structs/JBGroupedSplits.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBSplit.sol';\\n\\n/** \\n @member group The group indentifier.\\n @member splits The splits to associate with the group.\\n*/\\nstruct JBGroupedSplits {\\n uint256 group;\\n JBSplit[] splits;\\n}\\n\",\"keccak256\":\"0x80be1b220da4ac04851ea540ebb94c1ec2b0442ec5bd1e88fdf78a56becd8b5a\",\"license\":\"MIT\"},\"contracts/structs/JBPayDelegateAllocation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '../interfaces/IJBPayDelegate.sol';\\n\\n/** \\n @member delegate A delegate contract to use for subsequent calls.\\n @member amount The amount to send to the delegate.\\n*/\\nstruct JBPayDelegateAllocation {\\n IJBPayDelegate delegate;\\n uint256 amount;\\n}\\n\",\"keccak256\":\"0xb4e558dc62231d89e9b48998012577d22c3e52b58e23401f22d9096827f6ea0c\",\"license\":\"MIT\"},\"contracts/structs/JBPayParamsData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBPaymentTerminal.sol';\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member terminal The terminal that is facilitating the payment.\\n @member payer The address from which the payment originated.\\n @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.\\n @member projectId The ID of the project being paid.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the payment is being made.\\n @member beneficiary The specified address that should be the beneficiary of anything that results from the payment.\\n @member weight The weight of the funding cycle during which the payment is being made.\\n @member reservedRate The reserved rate of the funding cycle during which the payment is being made.\\n @member memo The memo that was sent alongside the payment.\\n @member metadata Extra data provided by the payer.\\n*/\\nstruct JBPayParamsData {\\n IJBPaymentTerminal terminal;\\n address payer;\\n JBTokenAmount amount;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n address beneficiary;\\n uint256 weight;\\n uint256 reservedRate;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0x05007b26feb5d9a026b883c6d734a341b5a49ef7b8215fb40507882e2c14e24d\",\"license\":\"MIT\"},\"contracts/structs/JBProjectMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member content The metadata content.\\n @member domain The domain within which the metadata applies.\\n*/\\nstruct JBProjectMetadata {\\n string content;\\n uint256 domain;\\n}\\n\",\"keccak256\":\"0x90ad7b1014c0a9f945fe7a2efde9d5de41e40574fa27969070b1d2ff52033ea0\",\"license\":\"MIT\"},\"contracts/structs/JBRedeemParamsData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBPaymentTerminal.sol';\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member terminal The terminal that is facilitating the redemption.\\n @member holder The holder of the tokens being redeemed.\\n @member projectId The ID of the project whos tokens are being redeemed.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the redemption is being made.\\n @member tokenCount The proposed number of tokens being redeemed, as a fixed point number with 18 decimals.\\n @member totalSupply The total supply of tokens used in the calculation, as a fixed point number with 18 decimals.\\n @member overflow The amount of overflow used in the reclaim amount calculation.\\n @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.\\n @member useTotalOverflow If overflow across all of a project's terminals is being used when making redemptions.\\n @member redemptionRate The redemption rate of the funding cycle during which the redemption is being made.\\n @member memo The proposed memo that is being emitted alongside the redemption.\\n @member metadata Extra data provided by the redeemer.\\n*/\\nstruct JBRedeemParamsData {\\n IJBPaymentTerminal terminal;\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 tokenCount;\\n uint256 totalSupply;\\n uint256 overflow;\\n JBTokenAmount reclaimAmount;\\n bool useTotalOverflow;\\n uint256 redemptionRate;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0x5065a824ebb34952f016c6dfa47e8a7ac28427b719470e74a41022c11ace7788\",\"license\":\"MIT\"},\"contracts/structs/JBRedemptionDelegateAllocation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '../interfaces/IJBRedemptionDelegate.sol';\\n\\n/** \\n @member delegate A delegate contract to use for subsequent calls.\\n @member amount The amount to send to the delegate.\\n*/\\nstruct JBRedemptionDelegateAllocation {\\n IJBRedemptionDelegate delegate;\\n uint256 amount;\\n}\\n\",\"keccak256\":\"0x10c29d33dd0d875a0d4692a2b9a9355c2ebf433cc06a9a60253d4366b60d4d31\",\"license\":\"MIT\"},\"contracts/structs/JBSplit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBSplitAllocator.sol';\\n\\n/** \\n @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.\\n @member preferAddToBalance A flag indicating if a distribution to a project should prefer triggering it's addToBalance function instead of its pay function.\\n @member percent The percent of the whole group that this split occupies. This number is out of `JBConstants.SPLITS_TOTAL_PERCENT`.\\n @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.\\n @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.\\n @member lockedUntil Specifies if the split should be unchangeable until the specified time, with the exception of extending the locked period.\\n @member allocator If an allocator is specified, funds will be sent to the allocator contract along with all properties of this split.\\n*/\\nstruct JBSplit {\\n bool preferClaimed;\\n bool preferAddToBalance;\\n uint256 percent;\\n uint256 projectId;\\n address payable beneficiary;\\n uint256 lockedUntil;\\n IJBSplitAllocator allocator;\\n}\\n\",\"keccak256\":\"0xc80a16606da8abf76d0f73abc38aee041e24f29342c1939018f70c286e89f105\",\"license\":\"MIT\"},\"contracts/structs/JBSplitAllocationData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBSplit.sol';\\n\\n/** \\n @member token The token being sent to the split allocator.\\n @member amount The amount being sent to the split allocator, as a fixed point number.\\n @member decimals The number of decimals in the amount.\\n @member projectId The project to which the split belongs.\\n @member group The group to which the split belongs.\\n @member split The split that caused the allocation.\\n*/\\nstruct JBSplitAllocationData {\\n address token;\\n uint256 amount;\\n uint256 decimals;\\n uint256 projectId;\\n uint256 group;\\n JBSplit split;\\n}\\n\",\"keccak256\":\"0x39f5c41bd31d36774744698ac94484b6cab62d7038df2f29d947668959782e63\",\"license\":\"MIT\"},\"contracts/structs/JBTokenAmount.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/* \\n @member token The token the payment was made in.\\n @member value The amount of tokens that was paid, as a fixed point number.\\n @member decimals The number of decimals included in the value fixed point number.\\n @member currency The expected currency of the value.\\n**/\\nstruct JBTokenAmount {\\n address token;\\n uint256 value;\\n uint256 decimals;\\n uint256 currency;\\n}\\n\",\"keccak256\":\"0x4a778e779ba257ba5638c5469e07a4d21b55a3128d56db5a0fdfacb1f3301c51\",\"license\":\"MIT\"},\"prb-math/contracts/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivFixedPointOverflow(uint256 prod1);\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivOverflow(uint256 prod1, uint256 denominator);\\n\\n/// @notice Emitted when one of the inputs is type(int256).min.\\nerror PRBMath__MulDivSignedInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows int256.\\nerror PRBMath__MulDivSignedOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is MIN_SD59x18.\\nerror PRBMathSD59x18__AbsInputTooSmall();\\n\\n/// @notice Emitted when ceiling a number overflows SD59x18.\\nerror PRBMathSD59x18__CeilOverflow(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__DivInputTooSmall();\\n\\n/// @notice Emitted when one of the intermediary unsigned results overflows SD59x18.\\nerror PRBMathSD59x18__DivOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathSD59x18__ExpInputTooBig(int256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathSD59x18__Exp2InputTooBig(int256 x);\\n\\n/// @notice Emitted when flooring a number underflows SD59x18.\\nerror PRBMathSD59x18__FloorUnderflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format overflows SD59x18.\\nerror PRBMathSD59x18__FromIntOverflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format underflows SD59x18.\\nerror PRBMathSD59x18__FromIntUnderflow(int256 x);\\n\\n/// @notice Emitted when the product of the inputs is negative.\\nerror PRBMathSD59x18__GmNegativeProduct(int256 x, int256 y);\\n\\n/// @notice Emitted when multiplying the inputs overflows SD59x18.\\nerror PRBMathSD59x18__GmOverflow(int256 x, int256 y);\\n\\n/// @notice Emitted when the input is less than or equal to zero.\\nerror PRBMathSD59x18__LogInputTooSmall(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__MulInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__MulOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__PowuOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is negative.\\nerror PRBMathSD59x18__SqrtNegativeInput(int256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows SD59x18.\\nerror PRBMathSD59x18__SqrtOverflow(int256 x);\\n\\n/// @notice Emitted when addition overflows UD60x18.\\nerror PRBMathUD60x18__AddOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when ceiling a number overflows UD60x18.\\nerror PRBMathUD60x18__CeilOverflow(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathUD60x18__ExpInputTooBig(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathUD60x18__Exp2InputTooBig(uint256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format format overflows UD60x18.\\nerror PRBMathUD60x18__FromUintOverflow(uint256 x);\\n\\n/// @notice Emitted when multiplying the inputs overflows UD60x18.\\nerror PRBMathUD60x18__GmOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when the input is less than 1.\\nerror PRBMathUD60x18__LogInputTooSmall(uint256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows UD60x18.\\nerror PRBMathUD60x18__SqrtOverflow(uint256 x);\\n\\n/// @notice Emitted when subtraction underflows UD60x18.\\nerror PRBMathUD60x18__SubUnderflow(uint256 x, uint256 y);\\n\\n/// @dev Common mathematical functions used in both PRBMathSD59x18 and PRBMathUD60x18. Note that this shared library\\n/// does not always assume the signed 59.18-decimal fixed-point or the unsigned 60.18-decimal fixed-point\\n/// representation. When it does not, it is explicitly mentioned in the NatSpec documentation.\\nlibrary PRBMath {\\n /// STRUCTS ///\\n\\n struct SD59x18 {\\n int256 value;\\n }\\n\\n struct UD60x18 {\\n uint256 value;\\n }\\n\\n /// STORAGE ///\\n\\n /// @dev How many trailing decimals can be represented.\\n uint256 internal constant SCALE = 1e18;\\n\\n /// @dev Largest power of two divisor of SCALE.\\n uint256 internal constant SCALE_LPOTD = 262144;\\n\\n /// @dev SCALE inverted mod 2^256.\\n uint256 internal constant SCALE_INVERSE =\\n 78156646155174841979727994598816262306175212592076161876661_508869554232690281;\\n\\n /// FUNCTIONS ///\\n\\n /// @notice Calculates the binary exponent of x using the binary fraction method.\\n /// @dev Has to use 192.64-bit fixed-point numbers.\\n /// See https://ethereum.stackexchange.com/a/96594/24693.\\n /// @param x The exponent as an unsigned 192.64-bit fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp2(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n // Start from 0.5 in the 192.64-bit fixed-point format.\\n result = 0x800000000000000000000000000000000000000000000000;\\n\\n // Multiply the result by root(2, 2^-i) when the bit at position i is 1. None of the intermediary results overflows\\n // because the initial result is 2^191 and all magic factors are less than 2^65.\\n if (x & 0x8000000000000000 > 0) {\\n result = (result * 0x16A09E667F3BCC909) >> 64;\\n }\\n if (x & 0x4000000000000000 > 0) {\\n result = (result * 0x1306FE0A31B7152DF) >> 64;\\n }\\n if (x & 0x2000000000000000 > 0) {\\n result = (result * 0x1172B83C7D517ADCE) >> 64;\\n }\\n if (x & 0x1000000000000000 > 0) {\\n result = (result * 0x10B5586CF9890F62A) >> 64;\\n }\\n if (x & 0x800000000000000 > 0) {\\n result = (result * 0x1059B0D31585743AE) >> 64;\\n }\\n if (x & 0x400000000000000 > 0) {\\n result = (result * 0x102C9A3E778060EE7) >> 64;\\n }\\n if (x & 0x200000000000000 > 0) {\\n result = (result * 0x10163DA9FB33356D8) >> 64;\\n }\\n if (x & 0x100000000000000 > 0) {\\n result = (result * 0x100B1AFA5ABCBED61) >> 64;\\n }\\n if (x & 0x80000000000000 > 0) {\\n result = (result * 0x10058C86DA1C09EA2) >> 64;\\n }\\n if (x & 0x40000000000000 > 0) {\\n result = (result * 0x1002C605E2E8CEC50) >> 64;\\n }\\n if (x & 0x20000000000000 > 0) {\\n result = (result * 0x100162F3904051FA1) >> 64;\\n }\\n if (x & 0x10000000000000 > 0) {\\n result = (result * 0x1000B175EFFDC76BA) >> 64;\\n }\\n if (x & 0x8000000000000 > 0) {\\n result = (result * 0x100058BA01FB9F96D) >> 64;\\n }\\n if (x & 0x4000000000000 > 0) {\\n result = (result * 0x10002C5CC37DA9492) >> 64;\\n }\\n if (x & 0x2000000000000 > 0) {\\n result = (result * 0x1000162E525EE0547) >> 64;\\n }\\n if (x & 0x1000000000000 > 0) {\\n result = (result * 0x10000B17255775C04) >> 64;\\n }\\n if (x & 0x800000000000 > 0) {\\n result = (result * 0x1000058B91B5BC9AE) >> 64;\\n }\\n if (x & 0x400000000000 > 0) {\\n result = (result * 0x100002C5C89D5EC6D) >> 64;\\n }\\n if (x & 0x200000000000 > 0) {\\n result = (result * 0x10000162E43F4F831) >> 64;\\n }\\n if (x & 0x100000000000 > 0) {\\n result = (result * 0x100000B1721BCFC9A) >> 64;\\n }\\n if (x & 0x80000000000 > 0) {\\n result = (result * 0x10000058B90CF1E6E) >> 64;\\n }\\n if (x & 0x40000000000 > 0) {\\n result = (result * 0x1000002C5C863B73F) >> 64;\\n }\\n if (x & 0x20000000000 > 0) {\\n result = (result * 0x100000162E430E5A2) >> 64;\\n }\\n if (x & 0x10000000000 > 0) {\\n result = (result * 0x1000000B172183551) >> 64;\\n }\\n if (x & 0x8000000000 > 0) {\\n result = (result * 0x100000058B90C0B49) >> 64;\\n }\\n if (x & 0x4000000000 > 0) {\\n result = (result * 0x10000002C5C8601CC) >> 64;\\n }\\n if (x & 0x2000000000 > 0) {\\n result = (result * 0x1000000162E42FFF0) >> 64;\\n }\\n if (x & 0x1000000000 > 0) {\\n result = (result * 0x10000000B17217FBB) >> 64;\\n }\\n if (x & 0x800000000 > 0) {\\n result = (result * 0x1000000058B90BFCE) >> 64;\\n }\\n if (x & 0x400000000 > 0) {\\n result = (result * 0x100000002C5C85FE3) >> 64;\\n }\\n if (x & 0x200000000 > 0) {\\n result = (result * 0x10000000162E42FF1) >> 64;\\n }\\n if (x & 0x100000000 > 0) {\\n result = (result * 0x100000000B17217F8) >> 64;\\n }\\n if (x & 0x80000000 > 0) {\\n result = (result * 0x10000000058B90BFC) >> 64;\\n }\\n if (x & 0x40000000 > 0) {\\n result = (result * 0x1000000002C5C85FE) >> 64;\\n }\\n if (x & 0x20000000 > 0) {\\n result = (result * 0x100000000162E42FF) >> 64;\\n }\\n if (x & 0x10000000 > 0) {\\n result = (result * 0x1000000000B17217F) >> 64;\\n }\\n if (x & 0x8000000 > 0) {\\n result = (result * 0x100000000058B90C0) >> 64;\\n }\\n if (x & 0x4000000 > 0) {\\n result = (result * 0x10000000002C5C860) >> 64;\\n }\\n if (x & 0x2000000 > 0) {\\n result = (result * 0x1000000000162E430) >> 64;\\n }\\n if (x & 0x1000000 > 0) {\\n result = (result * 0x10000000000B17218) >> 64;\\n }\\n if (x & 0x800000 > 0) {\\n result = (result * 0x1000000000058B90C) >> 64;\\n }\\n if (x & 0x400000 > 0) {\\n result = (result * 0x100000000002C5C86) >> 64;\\n }\\n if (x & 0x200000 > 0) {\\n result = (result * 0x10000000000162E43) >> 64;\\n }\\n if (x & 0x100000 > 0) {\\n result = (result * 0x100000000000B1721) >> 64;\\n }\\n if (x & 0x80000 > 0) {\\n result = (result * 0x10000000000058B91) >> 64;\\n }\\n if (x & 0x40000 > 0) {\\n result = (result * 0x1000000000002C5C8) >> 64;\\n }\\n if (x & 0x20000 > 0) {\\n result = (result * 0x100000000000162E4) >> 64;\\n }\\n if (x & 0x10000 > 0) {\\n result = (result * 0x1000000000000B172) >> 64;\\n }\\n if (x & 0x8000 > 0) {\\n result = (result * 0x100000000000058B9) >> 64;\\n }\\n if (x & 0x4000 > 0) {\\n result = (result * 0x10000000000002C5D) >> 64;\\n }\\n if (x & 0x2000 > 0) {\\n result = (result * 0x1000000000000162E) >> 64;\\n }\\n if (x & 0x1000 > 0) {\\n result = (result * 0x10000000000000B17) >> 64;\\n }\\n if (x & 0x800 > 0) {\\n result = (result * 0x1000000000000058C) >> 64;\\n }\\n if (x & 0x400 > 0) {\\n result = (result * 0x100000000000002C6) >> 64;\\n }\\n if (x & 0x200 > 0) {\\n result = (result * 0x10000000000000163) >> 64;\\n }\\n if (x & 0x100 > 0) {\\n result = (result * 0x100000000000000B1) >> 64;\\n }\\n if (x & 0x80 > 0) {\\n result = (result * 0x10000000000000059) >> 64;\\n }\\n if (x & 0x40 > 0) {\\n result = (result * 0x1000000000000002C) >> 64;\\n }\\n if (x & 0x20 > 0) {\\n result = (result * 0x10000000000000016) >> 64;\\n }\\n if (x & 0x10 > 0) {\\n result = (result * 0x1000000000000000B) >> 64;\\n }\\n if (x & 0x8 > 0) {\\n result = (result * 0x10000000000000006) >> 64;\\n }\\n if (x & 0x4 > 0) {\\n result = (result * 0x10000000000000003) >> 64;\\n }\\n if (x & 0x2 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n if (x & 0x1 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n\\n // We're doing two things at the same time:\\n //\\n // 1. Multiply the result by 2^n + 1, where \\\"2^n\\\" is the integer part and the one is added to account for\\n // the fact that we initially set the result to 0.5. This is accomplished by subtracting from 191\\n // rather than 192.\\n // 2. Convert the result to the unsigned 60.18-decimal fixed-point format.\\n //\\n // This works because 2^(191-ip) = 2^ip / 2^191, where \\\"ip\\\" is the integer part \\\"2^n\\\".\\n result *= SCALE;\\n result >>= (191 - (x >> 64));\\n }\\n }\\n\\n /// @notice Finds the zero-based index of the first one in the binary representation of x.\\n /// @dev See the note on msb in the \\\"Find First Set\\\" Wikipedia article https://en.wikipedia.org/wiki/Find_first_set\\n /// @param x The uint256 number for which to find the index of the most significant bit.\\n /// @return msb The index of the most significant bit as an uint256.\\n function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\\n if (x >= 2**128) {\\n x >>= 128;\\n msb += 128;\\n }\\n if (x >= 2**64) {\\n x >>= 64;\\n msb += 64;\\n }\\n if (x >= 2**32) {\\n x >>= 32;\\n msb += 32;\\n }\\n if (x >= 2**16) {\\n x >>= 16;\\n msb += 16;\\n }\\n if (x >= 2**8) {\\n x >>= 8;\\n msb += 8;\\n }\\n if (x >= 2**4) {\\n x >>= 4;\\n msb += 4;\\n }\\n if (x >= 2**2) {\\n x >>= 2;\\n msb += 2;\\n }\\n if (x >= 2**1) {\\n // No need to shift x any more.\\n msb += 1;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.\\n ///\\n /// Requirements:\\n /// - The denominator cannot be zero.\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The multiplicand as an uint256.\\n /// @param y The multiplier as an uint256.\\n /// @param denominator The divisor as an uint256.\\n /// @return result The result as an uint256.\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n unchecked {\\n result = prod0 / denominator;\\n }\\n return result;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n if (prod1 >= denominator) {\\n revert PRBMath__MulDivOverflow(prod1, denominator);\\n }\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n unchecked {\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 lpotdod = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by lpotdod.\\n denominator := div(denominator, lpotdod)\\n\\n // Divide [prod1 prod0] by lpotdod.\\n prod0 := div(prod0, lpotdod)\\n\\n // Flip lpotdod such that it is 2^256 / lpotdod. If lpotdod is zero, then it becomes one.\\n lpotdod := add(div(sub(0, lpotdod), lpotdod), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * lpotdod;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f71e18) with full precision.\\n ///\\n /// @dev Variant of \\\"mulDiv\\\" with constant folding, i.e. in which the denominator is always 1e18. Before returning the\\n /// final result, we add 1 if (x * y) % SCALE >= HALF_SCALE. Without this, 6.6e-19 would be truncated to 0 instead of\\n /// being rounded to 1e-18. See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717.\\n ///\\n /// Requirements:\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - The body is purposely left uncommented; see the NatSpec comments in \\\"PRBMath.mulDiv\\\" to understand how this works.\\n /// - It is assumed that the result can never be type(uint256).max when x and y solve the following two equations:\\n /// 1. x * y = type(uint256).max * SCALE\\n /// 2. (x * y) % SCALE >= SCALE / 2\\n ///\\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function mulDivFixedPoint(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n uint256 prod0;\\n uint256 prod1;\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n if (prod1 >= SCALE) {\\n revert PRBMath__MulDivFixedPointOverflow(prod1);\\n }\\n\\n uint256 remainder;\\n uint256 roundUpUnit;\\n assembly {\\n remainder := mulmod(x, y, SCALE)\\n roundUpUnit := gt(remainder, 499999999999999999)\\n }\\n\\n if (prod1 == 0) {\\n unchecked {\\n result = (prod0 / SCALE) + roundUpUnit;\\n return result;\\n }\\n }\\n\\n assembly {\\n result := add(\\n mul(\\n or(\\n div(sub(prod0, remainder), SCALE_LPOTD),\\n mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, SCALE_LPOTD), SCALE_LPOTD), 1))\\n ),\\n SCALE_INVERSE\\n ),\\n roundUpUnit\\n )\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev An extension of \\\"mulDiv\\\" for signed numbers. Works by computing the signs and the absolute values separately.\\n ///\\n /// Requirements:\\n /// - None of the inputs can be type(int256).min.\\n /// - The result must fit within int256.\\n ///\\n /// @param x The multiplicand as an int256.\\n /// @param y The multiplier as an int256.\\n /// @param denominator The divisor as an int256.\\n /// @return result The result as an int256.\\n function mulDivSigned(\\n int256 x,\\n int256 y,\\n int256 denominator\\n ) internal pure returns (int256 result) {\\n if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {\\n revert PRBMath__MulDivSignedInputTooSmall();\\n }\\n\\n // Get hold of the absolute values of x, y and the denominator.\\n uint256 ax;\\n uint256 ay;\\n uint256 ad;\\n unchecked {\\n ax = x < 0 ? uint256(-x) : uint256(x);\\n ay = y < 0 ? uint256(-y) : uint256(y);\\n ad = denominator < 0 ? uint256(-denominator) : uint256(denominator);\\n }\\n\\n // Compute the absolute value of (x*y)\\u00f7denominator. The result must fit within int256.\\n uint256 rAbs = mulDiv(ax, ay, ad);\\n if (rAbs > uint256(type(int256).max)) {\\n revert PRBMath__MulDivSignedOverflow(rAbs);\\n }\\n\\n // Get the signs of x, y and the denominator.\\n uint256 sx;\\n uint256 sy;\\n uint256 sd;\\n assembly {\\n sx := sgt(x, sub(0, 1))\\n sy := sgt(y, sub(0, 1))\\n sd := sgt(denominator, sub(0, 1))\\n }\\n\\n // XOR over sx, sy and sd. This is checking whether there are one or three negative signs in the inputs.\\n // If yes, the result should be negative.\\n result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs);\\n }\\n\\n /// @notice Calculates the square root of x, rounding down.\\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The uint256 number for which to calculate the square root.\\n /// @return result The result as an uint256.\\n function sqrt(uint256 x) internal pure returns (uint256 result) {\\n if (x == 0) {\\n return 0;\\n }\\n\\n // Set the initial guess to the closest power of two that is higher than x.\\n uint256 xAux = uint256(x);\\n result = 1;\\n if (xAux >= 0x100000000000000000000000000000000) {\\n xAux >>= 128;\\n result <<= 64;\\n }\\n if (xAux >= 0x10000000000000000) {\\n xAux >>= 64;\\n result <<= 32;\\n }\\n if (xAux >= 0x100000000) {\\n xAux >>= 32;\\n result <<= 16;\\n }\\n if (xAux >= 0x10000) {\\n xAux >>= 16;\\n result <<= 8;\\n }\\n if (xAux >= 0x100) {\\n xAux >>= 8;\\n result <<= 4;\\n }\\n if (xAux >= 0x10) {\\n xAux >>= 4;\\n result <<= 2;\\n }\\n if (xAux >= 0x8) {\\n result <<= 1;\\n }\\n\\n // The operations can never overflow because the result is max 2^127 when it enters this block.\\n unchecked {\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1; // Seven iterations should be enough\\n uint256 roundedDownResult = x / result;\\n return result >= roundedDownResult ? roundedDownResult : result;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x62cbabae4910e168e99b9c2c3e3b5c9c7ad5e7abd961dcc63b7ea3d83d8ea87e\",\"license\":\"Unlicense\"}},\"version\":1}", + "metadata": "{\"compiler\":{\"version\":\"0.8.16+commit.07a7930e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IJBDirectory\",\"name\":\"_directory\",\"type\":\"address\"},{\"internalType\":\"contract IJBFundingCycleStore\",\"name\":\"_fundingCycleStore\",\"type\":\"address\"},{\"internalType\":\"contract IJBPrices\",\"name\":\"_prices\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CURRENCY_MISMATCH\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DISTRIBUTION_AMOUNT_LIMIT_REACHED\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FUNDING_CYCLE_DISTRIBUTION_PAUSED\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FUNDING_CYCLE_PAYMENT_PAUSED\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FUNDING_CYCLE_REDEEM_PAUSED\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INADEQUATE_CONTROLLER_ALLOWANCE\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INSUFFICIENT_TOKENS\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INVALID_AMOUNT_TO_SEND_DELEGATE\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INVALID_FUNDING_CYCLE\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"prod1\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"denominator\",\"type\":\"uint256\"}],\"name\":\"PRBMath__MulDivOverflow\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminal\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminal\",\"name\":\"_terminal\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"}],\"name\":\"currentOverflowOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_tokenCount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_overflow\",\"type\":\"uint256\"}],\"name\":\"currentReclaimableOverflowOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminal\",\"name\":\"_terminal\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_tokenCount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"_useTotalOverflow\",\"type\":\"bool\"}],\"name\":\"currentReclaimableOverflowOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_decimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_currency\",\"type\":\"uint256\"}],\"name\":\"currentTotalOverflowOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"directory\",\"outputs\":[{\"internalType\":\"contract IJBDirectory\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fundingCycleStore\",\"outputs\":[{\"internalType\":\"contract IJBFundingCycleStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"prices\",\"outputs\":[{\"internalType\":\"contract IJBPrices\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"recordAddedBalanceFor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_currency\",\"type\":\"uint256\"}],\"name\":\"recordDistributionFor\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"configuration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"basedOn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"discountRate\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBFundingCycleBallot\",\"name\":\"ballot\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"metadata\",\"type\":\"uint256\"}],\"internalType\":\"struct JBFundingCycle\",\"name\":\"fundingCycle\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"distributedAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"}],\"name\":\"recordMigration\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_payer\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"decimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"currency\",\"type\":\"uint256\"}],\"internalType\":\"struct JBTokenAmount\",\"name\":\"_amount\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_baseWeightCurrency\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"recordPaymentFrom\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"configuration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"basedOn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"discountRate\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBFundingCycleBallot\",\"name\":\"ballot\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"metadata\",\"type\":\"uint256\"}],\"internalType\":\"struct JBFundingCycle\",\"name\":\"fundingCycle\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"tokenCount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"contract IJBPayDelegate\",\"name\":\"delegate\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"struct JBPayDelegateAllocation[]\",\"name\":\"delegateAllocations\",\"type\":\"tuple[]\"},{\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_holder\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_tokenCount\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"recordRedemptionFor\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"configuration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"basedOn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"discountRate\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBFundingCycleBallot\",\"name\":\"ballot\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"metadata\",\"type\":\"uint256\"}],\"internalType\":\"struct JBFundingCycle\",\"name\":\"fundingCycle\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"reclaimAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"contract IJBRedemptionDelegate\",\"name\":\"delegate\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"struct JBRedemptionDelegateAllocation[]\",\"name\":\"delegateAllocations\",\"type\":\"tuple[]\"},{\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_currency\",\"type\":\"uint256\"}],\"name\":\"recordUsedAllowanceOf\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"configuration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"basedOn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"discountRate\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBFundingCycleBallot\",\"name\":\"ballot\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"metadata\",\"type\":\"uint256\"}],\"internalType\":\"struct JBFundingCycle\",\"name\":\"fundingCycle\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"usedAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminal\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"usedDistributionLimitOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminal\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"usedOverflowAllowanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Adheres to: IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.Inherits from - ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_directory\":\"A contract storing directories of terminals and controllers for each project.\",\"_fundingCycleStore\":\"A contract storing all funding cycle configurations.\",\"_prices\":\"A contract that exposes price feeds.\"}},\"currentOverflowOf(address,uint256)\":{\"details\":\"The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\",\"params\":{\"_projectId\":\"The ID of the project to get overflow for.\",\"_terminal\":\"The terminal for which the overflow is being calculated.\"},\"returns\":{\"_0\":\"The current amount of overflow that project has in the specified terminal.\"}},\"currentReclaimableOverflowOf(address,uint256,uint256,bool)\":{\"details\":\" If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.The current reclaimable overflow is returned in terms of the specified terminal's currency.The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\",\"params\":{\"_projectId\":\"The ID of the project to get the reclaimable overflow amount for.\",\"_terminal\":\"The terminal from which the reclaimable amount would come.\",\"_tokenCount\":\"The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\",\"_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`.\"},\"returns\":{\"_0\":\"The amount of overflowed tokens that can be reclaimed, as a fixed point number with the same number of decimals as the provided `_terminal`.\"}},\"currentReclaimableOverflowOf(uint256,uint256,uint256,uint256)\":{\"details\":\" If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\",\"params\":{\"_overflow\":\"The amount of overflow to make the calculation with, as a fixed point number.\",\"_projectId\":\"The ID of the project to get the reclaimable overflow amount for.\",\"_tokenCount\":\"The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\",\"_totalSupply\":\"The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\"},\"returns\":{\"_0\":\"The amount of overflowed tokens that can be reclaimed, as a fixed point number with the same number of decimals as the provided `_overflow`.\"}},\"currentTotalOverflowOf(uint256,uint256,uint256)\":{\"params\":{\"_currency\":\"The currency that the total overflow should be in terms of.\",\"_decimals\":\"The number of decimals that the fixed point overflow should include.\",\"_projectId\":\"The ID of the project to get total overflow for.\"},\"returns\":{\"_0\":\"The current total amount of overflow that project has across all terminals.\"}},\"recordAddedBalanceFor(uint256,uint256)\":{\"details\":\"The msg.sender must be an IJBSingleTokenPaymentTerminal. \",\"params\":{\"_amount\":\"The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\",\"_projectId\":\"The ID of the project to which the funds being added belong.\"}},\"recordDistributionFor(uint256,uint256,uint256)\":{\"details\":\"The msg.sender must be an IJBSingleTokenPaymentTerminal. \",\"params\":{\"_amount\":\"The amount to use from the distribution limit, as a fixed point number.\",\"_currency\":\"The currency of the `_amount`. This must match the project's current funding cycle's currency.\",\"_projectId\":\"The ID of the project that is having funds distributed.\"},\"returns\":{\"distributedAmount\":\"The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\",\"fundingCycle\":\"The funding cycle during which the distribution was made.\"}},\"recordMigration(uint256)\":{\"details\":\"The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\",\"params\":{\"_projectId\":\"The ID of the project being migrated.\"},\"returns\":{\"balance\":\"The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\"}},\"recordPaymentFrom(address,(address,uint256,uint256,uint256),uint256,uint256,address,string,bytes)\":{\"details\":\"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.The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\",\"params\":{\"_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.\",\"_baseWeightCurrency\":\"The currency to base token issuance on.\",\"_beneficiary\":\"The specified address that should be the beneficiary of anything that results from the payment.\",\"_memo\":\"A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\",\"_metadata\":\"Bytes to send along to the data source, if one is provided.\",\"_payer\":\"The original address that sent the payment to the terminal.\",\"_projectId\":\"The ID of the project being paid.\"},\"returns\":{\"delegateAllocations\":\"The amount to send to delegates instead of adding to the local balance.\",\"fundingCycle\":\"The project's funding cycle during which payment was made.\",\"memo\":\"A memo that should be passed along to the emitted event.\",\"tokenCount\":\"The number of project tokens that were minted, as a fixed point number with 18 decimals.\"}},\"recordRedemptionFor(address,uint256,uint256,string,bytes)\":{\"details\":\"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.The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\",\"params\":{\"_holder\":\"The account that is having its tokens redeemed.\",\"_memo\":\"A memo to pass along to the emitted event.\",\"_metadata\":\"Bytes to send along to the data source, if one is provided.\",\"_projectId\":\"The ID of the project to which the tokens being redeemed belong.\",\"_tokenCount\":\"The number of project tokens to redeem, as a fixed point number with 18 decimals.\"},\"returns\":{\"delegateAllocations\":\"The amount to send to delegates instead of sending to the beneficiary.\",\"fundingCycle\":\"The funding cycle during which the redemption was made.\",\"memo\":\"A memo that should be passed along to the emitted event.\",\"reclaimAmount\":\"The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\"}},\"recordUsedAllowanceOf(uint256,uint256,uint256)\":{\"details\":\"The msg.sender must be an IJBSingleTokenPaymentTerminal. \",\"params\":{\"_amount\":\"The amount to use from the allowance, as a fixed point number. \",\"_currency\":\"The currency of the `_amount`. Must match the currency of the overflow allowance.\",\"_projectId\":\"The ID of the project to use the allowance of.\"},\"returns\":{\"fundingCycle\":\"The funding cycle during which the overflow allowance is being used.\",\"usedAmount\":\"The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\"}}},\"stateVariables\":{\"balanceOf\":{\"details\":\"The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal. _terminal The terminal to which the balance applies. _projectId The ID of the project to get the balance of.\"},\"usedDistributionLimitOf\":{\"details\":\"Increases as projects use their preconfigured distribution limits.The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal. _terminal The terminal to which the used distribution limit applies. _projectId The ID of the project to get the used distribution limit of. _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\"},\"usedOverflowAllowanceOf\":{\"details\":\"Increases as projects use their allowance.The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal. _terminal The terminal to which the overflow allowance applies. _projectId The ID of the project to get the used overflow allowance of. _configuration The configuration of the during which the allowance was used.\"}},\"version\":1},\"userdoc\":{\"errors\":{\"PRBMath__MulDivOverflow(uint256,uint256)\":[{\"notice\":\"Emitted when the result overflows uint256.\"}]},\"kind\":\"user\",\"methods\":{\"balanceOf(address,uint256)\":{\"notice\":\"The amount of tokens that each project has for each terminal, in terms of the terminal's token.\"},\"currentOverflowOf(address,uint256)\":{\"notice\":\"Gets the current overflowed amount in a terminal for a specified project.\"},\"currentReclaimableOverflowOf(address,uint256,uint256,bool)\":{\"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.\"},\"currentReclaimableOverflowOf(uint256,uint256,uint256,uint256)\":{\"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.\"},\"currentTotalOverflowOf(uint256,uint256,uint256)\":{\"notice\":\"Gets the current overflowed amount for a specified project across all terminals.\"},\"directory()\":{\"notice\":\"The directory of terminals and controllers for projects.\"},\"fundingCycleStore()\":{\"notice\":\"The contract storing all funding cycle configurations.\"},\"prices()\":{\"notice\":\"The contract that exposes price feeds.\"},\"recordAddedBalanceFor(uint256,uint256)\":{\"notice\":\"Records newly added funds for the project.\"},\"recordDistributionFor(uint256,uint256,uint256)\":{\"notice\":\"Records newly distributed funds for a project.\"},\"recordMigration(uint256)\":{\"notice\":\"Records the migration of funds from this store.\"},\"recordPaymentFrom(address,(address,uint256,uint256,uint256),uint256,uint256,address,string,bytes)\":{\"notice\":\"Records newly contributed tokens to a project.\"},\"recordRedemptionFor(address,uint256,uint256,string,bytes)\":{\"notice\":\"Records newly redeemed tokens of a project.\"},\"recordUsedAllowanceOf(uint256,uint256,uint256)\":{\"notice\":\"Records newly used allowance funds of a project.\"},\"usedDistributionLimitOf(address,uint256,uint256)\":{\"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.\"},\"usedOverflowAllowanceOf(address,uint256,uint256)\":{\"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.\"}},\"notice\":\"Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/JBSingleTokenPaymentTerminalStore.sol\":\"JBSingleTokenPaymentTerminalStore\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/security/ReentrancyGuard.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuard {\\n // Booleans are more expensive than uint256 or any type that takes up a full\\n // word because each write operation emits an extra SLOAD to first read the\\n // slot's contents, replace the bits taken up by the boolean, and then write\\n // back. This is the compiler's defense against contract upgrades and\\n // pointer aliasing, and it cannot be disabled.\\n\\n // The values being non-zero value makes deployment a bit more expensive,\\n // but in exchange the refund on every call to nonReentrant will be lower in\\n // amount. Since refunds are capped to a percentage of the total\\n // transaction's gas, it is best to keep them low in cases like this one, to\\n // increase the likelihood of the full refund coming into effect.\\n uint256 private constant _NOT_ENTERED = 1;\\n uint256 private constant _ENTERED = 2;\\n\\n uint256 private _status;\\n\\n constructor() {\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and making it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n // On the first call to nonReentrant, _notEntered will be true\\n require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n _status = _ENTERED;\\n\\n _;\\n\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n _status = _NOT_ENTERED;\\n }\\n}\\n\",\"keccak256\":\"0x0e9621f60b2faabe65549f7ed0f24e8853a45c1b7990d47e8160e523683f3935\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool _approved) external;\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x516a22876c1fab47f49b1bc22b4614491cd05338af8bd2e7b382da090a079990\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"@paulrberg/contracts/math/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\nimport \\\"prb-math/contracts/PRBMath.sol\\\";\\n\",\"keccak256\":\"0x42821345981bc0434a90ba2268a2f5278dfe9e38166981d72fc7f3b776a29495\",\"license\":\"Unlicense\"},\"contracts/JBSingleTokenPaymentTerminalStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\\nimport '@paulrberg/contracts/math/PRBMath.sol';\\nimport './interfaces/IJBController.sol';\\nimport './interfaces/IJBFundingCycleDataSource.sol';\\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\\nimport './libraries/JBConstants.sol';\\nimport './libraries/JBCurrencies.sol';\\nimport './libraries/JBFixedPointNumber.sol';\\nimport './libraries/JBFundingCycleMetadataResolver.sol';\\nimport './structs/JBPayDelegateAllocation.sol';\\nimport './structs/JBPayParamsData.sol';\\n\\n/**\\n @notice\\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\\n\\n @dev\\n Adheres to:\\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n\\n @dev\\n Inherits from -\\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\\n*/\\ncontract JBSingleTokenPaymentTerminalStore is ReentrancyGuard, IJBSingleTokenPaymentTerminalStore {\\n // A library that parses the packed funding cycle metadata into a friendlier format.\\n using JBFundingCycleMetadataResolver for JBFundingCycle;\\n\\n //*********************************************************************//\\n // --------------------------- custom errors ------------------------- //\\n //*********************************************************************//\\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\\n error CURRENCY_MISMATCH();\\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\\n error FUNDING_CYCLE_PAYMENT_PAUSED();\\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\\n error FUNDING_CYCLE_REDEEM_PAUSED();\\n error INADEQUATE_CONTROLLER_ALLOWANCE();\\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\\n error INSUFFICIENT_TOKENS();\\n error INVALID_FUNDING_CYCLE();\\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\\n\\n //*********************************************************************//\\n // -------------------------- private constants ---------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \\n */\\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\\n\\n //*********************************************************************//\\n // ---------------- public immutable stored properties --------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The directory of terminals and controllers for projects.\\n */\\n IJBDirectory public immutable override directory;\\n\\n /**\\n @notice\\n The contract storing all funding cycle configurations.\\n */\\n IJBFundingCycleStore public immutable override fundingCycleStore;\\n\\n /**\\n @notice\\n The contract that exposes price feeds.\\n */\\n IJBPrices public immutable override prices;\\n\\n //*********************************************************************//\\n // --------------------- public stored properties -------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\\n\\n @dev\\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\\n\\n _terminal The terminal to which the balance applies.\\n _projectId The ID of the project to get the balance of.\\n */\\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\\n\\n /**\\n @notice\\n 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.\\n\\n @dev\\n Increases as projects use their preconfigured distribution limits.\\n\\n @dev\\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\\n\\n _terminal The terminal to which the used distribution limit applies.\\n _projectId The ID of the project to get the used distribution limit of.\\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\\n */\\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\\n public\\n override usedDistributionLimitOf;\\n\\n /**\\n @notice\\n 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.\\n\\n @dev\\n Increases as projects use their allowance.\\n\\n @dev\\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\\n\\n _terminal The terminal to which the overflow allowance applies.\\n _projectId The ID of the project to get the used overflow allowance of.\\n _configuration The configuration of the during which the allowance was used.\\n */\\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\\n public\\n override usedOverflowAllowanceOf;\\n\\n //*********************************************************************//\\n // ------------------------- external views -------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Gets the current overflowed amount in a terminal for a specified project.\\n\\n @dev\\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\\n\\n @param _terminal The terminal for which the overflow is being calculated.\\n @param _projectId The ID of the project to get overflow for.\\n\\n @return The current amount of overflow that project has in the specified terminal.\\n */\\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\\n external\\n view\\n override\\n returns (uint256)\\n {\\n // Return the overflow during the project's current funding cycle.\\n return\\n _overflowDuring(\\n _terminal,\\n _projectId,\\n fundingCycleStore.currentOf(_projectId),\\n _terminal.currency()\\n );\\n }\\n\\n /**\\n @notice\\n Gets the current overflowed amount for a specified project across all terminals.\\n\\n @param _projectId The ID of the project to get total overflow for.\\n @param _decimals The number of decimals that the fixed point overflow should include.\\n @param _currency The currency that the total overflow should be in terms of.\\n\\n @return The current total amount of overflow that project has across all terminals.\\n */\\n function currentTotalOverflowOf(\\n uint256 _projectId,\\n uint256 _decimals,\\n uint256 _currency\\n ) external view override returns (uint256) {\\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\\n }\\n\\n /**\\n @notice\\n 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.\\n\\n @dev \\n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\\n\\n @dev\\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\\n\\n @dev\\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\\n\\n @param _terminal The terminal from which the reclaimable amount would come.\\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\\n @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`.\\n\\n @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`.\\n */\\n function currentReclaimableOverflowOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n bool _useTotalOverflow\\n ) external view override returns (uint256) {\\n // Get a reference to the project's current funding cycle.\\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // Get the amount of current overflow.\\n // 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.\\n uint256 _currentOverflow = _useTotalOverflow\\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\\n\\n // If there's no overflow, there's no reclaimable overflow.\\n if (_currentOverflow == 0) return 0;\\n\\n // Get the number of outstanding tokens the project has.\\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\\n\\n // Can't redeem more tokens that is in the supply.\\n if (_tokenCount > _totalSupply) return 0;\\n\\n // Return the reclaimable overflow amount.\\n return\\n _reclaimableOverflowDuring(\\n _projectId,\\n _fundingCycle,\\n _tokenCount,\\n _totalSupply,\\n _currentOverflow\\n );\\n }\\n\\n /**\\n @notice\\n 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.\\n\\n @dev \\n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\\n\\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\\n\\n @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`.\\n */\\n function currentReclaimableOverflowOf(\\n uint256 _projectId,\\n uint256 _tokenCount,\\n uint256 _totalSupply,\\n uint256 _overflow\\n ) external view override returns (uint256) {\\n // If there's no overflow, there's no reclaimable overflow.\\n if (_overflow == 0) return 0;\\n\\n // Can't redeem more tokens that is in the supply.\\n if (_tokenCount > _totalSupply) return 0;\\n\\n // Get a reference to the project's current funding cycle.\\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // Return the reclaimable overflow amount.\\n return\\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\\n }\\n\\n //*********************************************************************//\\n // -------------------------- constructor ---------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @param _directory A contract storing directories of terminals and controllers for each project.\\n @param _fundingCycleStore A contract storing all funding cycle configurations.\\n @param _prices A contract that exposes price feeds.\\n */\\n constructor(\\n IJBDirectory _directory,\\n IJBFundingCycleStore _fundingCycleStore,\\n IJBPrices _prices\\n ) {\\n directory = _directory;\\n fundingCycleStore = _fundingCycleStore;\\n prices = _prices;\\n }\\n\\n //*********************************************************************//\\n // ---------------------- external transactions ---------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Records newly contributed tokens to a project.\\n\\n @dev\\n 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.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\\n\\n @param _payer The original address that sent the payment to the terminal.\\n @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.\\n @param _projectId The ID of the project being paid.\\n @param _baseWeightCurrency The currency to base token issuance on.\\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\\n @param _metadata Bytes to send along to the data source, if one is provided.\\n\\n @return fundingCycle The project's funding cycle during which payment was made.\\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\\n @return memo A memo that should be passed along to the emitted event.\\n */\\n function recordPaymentFrom(\\n address _payer,\\n JBTokenAmount calldata _amount,\\n uint256 _projectId,\\n uint256 _baseWeightCurrency,\\n address _beneficiary,\\n string calldata _memo,\\n bytes memory _metadata\\n )\\n external\\n override\\n nonReentrant\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 tokenCount,\\n JBPayDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n )\\n {\\n // Get a reference to the current funding cycle for the project.\\n fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // The project must have a funding cycle configured.\\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\\n\\n // Must not be paused.\\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\\n\\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\\n uint256 _weight;\\n\\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\\n // Create the params that'll be sent to the data source.\\n JBPayParamsData memory _data = JBPayParamsData(\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n _payer,\\n _amount,\\n _projectId,\\n fundingCycle.configuration,\\n _beneficiary,\\n fundingCycle.weight,\\n fundingCycle.reservedRate(),\\n _memo,\\n _metadata\\n );\\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\\n .payParams(_data);\\n }\\n // Otherwise use the funding cycle's weight\\n else {\\n _weight = fundingCycle.weight;\\n memo = _memo;\\n }\\n\\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\\n {\\n // Keep a reference to the amount that should be added to the project's balance.\\n uint256 _balanceDiff = _amount.value;\\n\\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\\n if (delegateAllocations.length != 0) {\\n for (uint256 _i; _i < delegateAllocations.length; ) {\\n // Get a reference to the amount to be delegated.\\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\\n\\n // Validate if non-zero.\\n if (_delegatedAmount != 0) {\\n // Can't delegate more than was paid.\\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\\n\\n // Decrement the total amount being added to the balance.\\n _balanceDiff = _balanceDiff - _delegatedAmount;\\n }\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n\\n // If there's no amount being recorded, there's nothing left to do.\\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\\n\\n // Add the correct balance difference to the token balance of the project.\\n if (_balanceDiff != 0)\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\\n _balanceDiff;\\n }\\n\\n // If there's no weight, token count must be 0 so there's nothing left to do.\\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\\n\\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\\n uint256 _decimals = _amount.decimals;\\n\\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\\n // 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`.\\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\\n ? 10**_decimals\\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\\n\\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\\n }\\n\\n /**\\n @notice\\n Records newly redeemed tokens of a project.\\n\\n @dev\\n 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.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\\n\\n @param _holder The account that is having its tokens redeemed.\\n @param _projectId The ID of the project to which the tokens being redeemed belong.\\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Bytes to send along to the data source, if one is provided.\\n\\n @return fundingCycle The funding cycle during which the redemption was made.\\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\\n @return memo A memo that should be passed along to the emitted event.\\n */\\n function recordRedemptionFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n string memory _memo,\\n bytes memory _metadata\\n )\\n external\\n override\\n nonReentrant\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 reclaimAmount,\\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n )\\n {\\n // Get a reference to the project's current funding cycle.\\n fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // The current funding cycle must not be paused.\\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\\n\\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\\n {\\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\\n JBTokenAmount memory _reclaimedTokenAmount;\\n uint256 _currentOverflow;\\n uint256 _totalSupply;\\n\\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\\n {\\n // Get a reference to the terminal's tokens.\\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\\n\\n // Get a reference to the terminal's decimals.\\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\\n\\n // Get areference to the terminal's currency.\\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\\n\\n // Get the amount of current overflow.\\n // 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.\\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\\n : _overflowDuring(\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n _projectId,\\n fundingCycle,\\n _currency\\n );\\n\\n // Get the number of outstanding tokens the project has.\\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\\n _projectId,\\n fundingCycle.reservedRate()\\n );\\n\\n // Can't redeem more tokens that is in the supply.\\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\\n\\n if (_currentOverflow != 0)\\n // Calculate reclaim amount using the current overflow amount.\\n reclaimAmount = _reclaimableOverflowDuring(\\n _projectId,\\n fundingCycle,\\n _tokenCount,\\n _totalSupply,\\n _currentOverflow\\n );\\n\\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\\n }\\n\\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\\n {\\n // Get a reference to the ballot state.\\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\\n\\n // Create the params that'll be sent to the data source.\\n JBRedeemParamsData memory _data = JBRedeemParamsData(\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n _holder,\\n _projectId,\\n fundingCycle.configuration,\\n _tokenCount,\\n _totalSupply,\\n _currentOverflow,\\n _reclaimedTokenAmount,\\n fundingCycle.useTotalOverflowForRedemptions(),\\n _state == JBBallotState.Active\\n ? fundingCycle.ballotRedemptionRate()\\n : fundingCycle.redemptionRate(),\\n _memo,\\n _metadata\\n );\\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\\n fundingCycle.dataSource()\\n ).redeemParams(_data);\\n }\\n } else {\\n memo = _memo;\\n }\\n }\\n\\n // Keep a reference to the amount that should be subtracted from the project's balance.\\n uint256 _balanceDiff = reclaimAmount;\\n\\n if (delegateAllocations.length != 0) {\\n // Validate all delegated amounts.\\n for (uint256 _i; _i < delegateAllocations.length; ) {\\n // Get a reference to the amount to be delegated.\\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\\n\\n // Validate if non-zero.\\n if (_delegatedAmount != 0)\\n // Increment the total amount being subtracted from the balance.\\n _balanceDiff = _balanceDiff + _delegatedAmount;\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n\\n // The amount being reclaimed must be within the project's balance.\\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\\n\\n // Remove the reclaimed funds from the project's balance.\\n if (_balanceDiff != 0) {\\n unchecked {\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\\n _balanceDiff;\\n }\\n }\\n }\\n\\n /**\\n @notice\\n Records newly distributed funds for a project.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \\n\\n @param _projectId The ID of the project that is having funds distributed.\\n @param _amount The amount to use from the distribution limit, as a fixed point number.\\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\\n\\n @return fundingCycle The funding cycle during which the distribution was made.\\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\\n */\\n function recordDistributionFor(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n )\\n external\\n override\\n nonReentrant\\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\\n {\\n // Get a reference to the project's current funding cycle.\\n fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // The funding cycle must not be configured to have distributions paused.\\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\\n\\n // The new total amount that has been distributed during this funding cycle.\\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\\n IJBSingleTokenPaymentTerminal(msg.sender)\\n ][_projectId][fundingCycle.number] + _amount;\\n\\n // Amount must be within what is still distributable.\\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\\n directory.controllerOf(_projectId)\\n ).distributionLimitOf(\\n _projectId,\\n fundingCycle.configuration,\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n IJBSingleTokenPaymentTerminal(msg.sender).token()\\n );\\n\\n // Make sure the new used amount is within the distribution limit.\\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\\n\\n // Make sure the currencies match.\\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\\n\\n // Get a reference to the terminal's currency.\\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\\n\\n // Convert the amount to the balance's currency.\\n distributedAmount = (_currency == _balanceCurrency)\\n ? _amount\\n : PRBMath.mulDiv(\\n _amount,\\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\\n );\\n\\n // The amount being distributed must be available.\\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\\n\\n // Store the new amount.\\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\\n fundingCycle.number\\n ] = _newUsedDistributionLimitOf;\\n\\n // Removed the distributed funds from the project's token balance.\\n unchecked {\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\\n distributedAmount;\\n }\\n }\\n\\n /**\\n @notice\\n Records newly used allowance funds of a project.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \\n\\n @param _projectId The ID of the project to use the allowance of.\\n @param _amount The amount to use from the allowance, as a fixed point number. \\n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\\n\\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\\n */\\n function recordUsedAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n )\\n external\\n override\\n nonReentrant\\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\\n {\\n // Get a reference to the project's current funding cycle.\\n fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\\n IJBSingleTokenPaymentTerminal(msg.sender)\\n ][_projectId][fundingCycle.configuration] + _amount;\\n\\n // There must be sufficient allowance available.\\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\\n directory.controllerOf(_projectId)\\n ).overflowAllowanceOf(\\n _projectId,\\n fundingCycle.configuration,\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n IJBSingleTokenPaymentTerminal(msg.sender).token()\\n );\\n\\n // Make sure the new used amount is within the allowance.\\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\\n\\n // Make sure the currencies match.\\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\\n\\n // Get a reference to the terminal's currency.\\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\\n\\n // Convert the amount to this store's terminal's token.\\n usedAmount = (_currency == _balanceCurrency)\\n ? _amount\\n : PRBMath.mulDiv(\\n _amount,\\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\\n );\\n\\n // The amount being distributed must be available in the overflow.\\n if (\\n usedAmount >\\n _overflowDuring(\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n _projectId,\\n fundingCycle,\\n _balanceCurrency\\n )\\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\\n\\n // Store the incremented value.\\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\\n fundingCycle.configuration\\n ] = _newUsedOverflowAllowanceOf;\\n\\n // Update the project's balance.\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\\n usedAmount;\\n }\\n\\n /**\\n @notice\\n Records newly added funds for the project.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \\n\\n @param _projectId The ID of the project to which the funds being added belong.\\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\\n */\\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\\n // Increment the balance.\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\\n _amount;\\n }\\n\\n /**\\n @notice\\n Records the migration of funds from this store.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\\n\\n @param _projectId The ID of the project being migrated.\\n\\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\\n */\\n function recordMigration(uint256 _projectId)\\n external\\n override\\n nonReentrant\\n returns (uint256 balance)\\n {\\n // Get a reference to the project's current funding cycle.\\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // Migration must be allowed.\\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\\n\\n // Return the current balance.\\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\\n\\n // Set the balance to 0.\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\\n }\\n\\n //*********************************************************************//\\n // --------------------- private helper functions -------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\\n\\n @dev \\n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\\n\\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\\n @param _overflow The amount of overflow to make the calculation with.\\n\\n @return The amount of overflowed tokens that can be reclaimed.\\n */\\n function _reclaimableOverflowDuring(\\n uint256 _projectId,\\n JBFundingCycle memory _fundingCycle,\\n uint256 _tokenCount,\\n uint256 _totalSupply,\\n uint256 _overflow\\n ) private view returns (uint256) {\\n // If the amount being redeemed is the total supply, return the rest of the overflow.\\n if (_tokenCount == _totalSupply) return _overflow;\\n\\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\\n JBBallotState.Active\\n ? _fundingCycle.ballotRedemptionRate()\\n : _fundingCycle.redemptionRate();\\n\\n // If the redemption rate is 0, nothing is claimable.\\n if (_redemptionRate == 0) return 0;\\n\\n // Get a reference to the linear proportion.\\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\\n\\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\\n\\n return\\n PRBMath.mulDiv(\\n _base,\\n _redemptionRate +\\n PRBMath.mulDiv(\\n _tokenCount,\\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\\n _totalSupply\\n ),\\n JBConstants.MAX_REDEMPTION_RATE\\n );\\n }\\n\\n /**\\n @notice\\n Gets the amount that is overflowing when measured from the specified funding cycle.\\n\\n @dev\\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\\n\\n @param _terminal The terminal for which the overflow is being calculated.\\n @param _projectId The ID of the project to get overflow for.\\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\\n\\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\\n */\\n function _overflowDuring(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n JBFundingCycle memory _fundingCycle,\\n uint256 _balanceCurrency\\n ) private view returns (uint256) {\\n // Get the current balance of the project.\\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\\n\\n // If there's no balance, there's no overflow.\\n if (_balanceOf == 0) return 0;\\n\\n // Get a reference to the distribution limit during the funding cycle.\\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\\n directory.controllerOf(_projectId)\\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\\n\\n // Get a reference to the amount still distributable during the funding cycle.\\n uint256 _distributionLimitRemaining = _distributionLimit -\\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\\n\\n // Convert the _distributionRemaining to be in terms of the provided currency.\\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\\n _distributionLimitRemaining = PRBMath.mulDiv(\\n _distributionLimitRemaining,\\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\\n );\\n\\n // Overflow is the balance of this project minus the amount that can still be distributed.\\n unchecked {\\n return\\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\\n }\\n }\\n\\n /**\\n @notice\\n Gets the amount that is currently overflowing across all of a project's terminals. \\n\\n @dev\\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\\n\\n @param _projectId The ID of the project to get the total overflow for.\\n @param _decimals The number of decimals that the fixed point overflow should include.\\n @param _currency The currency that the overflow should be in terms of.\\n\\n @return overflow The total overflow of a project's funds.\\n */\\n function _currentTotalOverflowOf(\\n uint256 _projectId,\\n uint256 _decimals,\\n uint256 _currency\\n ) private view returns (uint256) {\\n // Get a reference to the project's terminals.\\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\\n\\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\\n uint256 _ethOverflow;\\n\\n // Add the current ETH overflow for each terminal.\\n for (uint256 _i; _i < _terminals.length; ) {\\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\\n unchecked {\\n ++_i;\\n }\\n }\\n\\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.GAS_CURRENCY\\n ? _ethOverflow\\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.GAS_CURRENCY, _currency, 18));\\n\\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\\n return\\n (_decimals == 18)\\n ? _totalOverflow18Decimal\\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\\n }\\n}\\n\",\"keccak256\":\"0x17c0330168982f5da39eb12537ff22871b2d73220ca1012c1ad59d6999db7dd6\",\"license\":\"MIT\"},\"contracts/enums/JBBallotState.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nenum JBBallotState {\\n Active,\\n Approved,\\n Failed\\n}\\n\",\"keccak256\":\"0x891fcac63470398b3a11239da7feba6b07d640809fcefd2404303b823d7378f8\",\"license\":\"MIT\"},\"contracts/interfaces/IJBController.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBFundAccessConstraints.sol';\\nimport './../structs/JBFundingCycleData.sol';\\nimport './../structs/JBFundingCycleMetadata.sol';\\nimport './../structs/JBGroupedSplits.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBMigratable.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBSplitsStore.sol';\\nimport './IJBTokenStore.sol';\\n\\ninterface IJBController is IERC165 {\\n event LaunchProject(uint256 configuration, uint256 projectId, string memo, address caller);\\n\\n event LaunchFundingCycles(uint256 configuration, uint256 projectId, string memo, address caller);\\n\\n event ReconfigureFundingCycles(\\n uint256 configuration,\\n uint256 projectId,\\n string memo,\\n address caller\\n );\\n\\n event SetFundAccessConstraints(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n JBFundAccessConstraints constraints,\\n address caller\\n );\\n\\n event DistributeReservedTokens(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address beneficiary,\\n uint256 tokenCount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n address caller\\n );\\n\\n event DistributeToReservedTokenSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n uint256 tokenCount,\\n address caller\\n );\\n\\n event MintTokens(\\n address indexed beneficiary,\\n uint256 indexed projectId,\\n uint256 tokenCount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n uint256 reservedRate,\\n address caller\\n );\\n\\n event BurnTokens(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 tokenCount,\\n string memo,\\n address caller\\n );\\n\\n event Migrate(uint256 indexed projectId, IJBMigratable to, address caller);\\n\\n event PrepMigration(uint256 indexed projectId, address from, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function tokenStore() external view returns (IJBTokenStore);\\n\\n function splitsStore() external view returns (IJBSplitsStore);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function reservedTokenBalanceOf(uint256 _projectId, uint256 _reservedRate)\\n external\\n view\\n returns (uint256);\\n\\n function distributionLimitOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n IJBPaymentTerminal _terminal,\\n address _token\\n ) external view returns (uint256 distributionLimit, uint256 distributionLimitCurrency);\\n\\n function overflowAllowanceOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n IJBPaymentTerminal _terminal,\\n address _token\\n ) external view returns (uint256 overflowAllowance, uint256 overflowAllowanceCurrency);\\n\\n function totalOutstandingTokensOf(uint256 _projectId, uint256 _reservedRate)\\n external\\n view\\n returns (uint256);\\n\\n function getFundingCycleOf(uint256 _projectId, uint256 _configuration)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function latestConfiguredFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (\\n JBFundingCycle memory,\\n JBFundingCycleMetadata memory metadata,\\n JBBallotState\\n );\\n\\n function currentFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function queuedFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function launchProjectFor(\\n address _owner,\\n JBProjectMetadata calldata _projectMetadata,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n IJBPaymentTerminal[] memory _terminals,\\n string calldata _memo\\n ) external returns (uint256 projectId);\\n\\n function launchFundingCyclesFor(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n IJBPaymentTerminal[] memory _terminals,\\n string calldata _memo\\n ) external returns (uint256 configuration);\\n\\n function reconfigureFundingCyclesOf(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n string calldata _memo\\n ) external returns (uint256);\\n\\n function mintTokensOf(\\n uint256 _projectId,\\n uint256 _tokenCount,\\n address _beneficiary,\\n string calldata _memo,\\n bool _preferClaimedTokens,\\n bool _useReservedRate\\n ) external returns (uint256 beneficiaryTokenCount);\\n\\n function burnTokensOf(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n string calldata _memo,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function distributeReservedTokensOf(uint256 _projectId, string memory _memo)\\n external\\n returns (uint256);\\n\\n function migrate(uint256 _projectId, IJBMigratable _to) external;\\n}\\n\",\"keccak256\":\"0xb1ee4b41f2a06f28f69c74cb729b8964f2e75f3c545a68f85bd9082b5575bc85\",\"license\":\"MIT\"},\"contracts/interfaces/IJBDirectory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBProjects.sol';\\n\\ninterface IJBDirectory {\\n event SetController(uint256 indexed projectId, address indexed controller, address caller);\\n\\n event AddTerminal(uint256 indexed projectId, IJBPaymentTerminal indexed terminal, address caller);\\n\\n event SetTerminals(uint256 indexed projectId, IJBPaymentTerminal[] terminals, address caller);\\n\\n event SetPrimaryTerminal(\\n uint256 indexed projectId,\\n address indexed token,\\n IJBPaymentTerminal indexed terminal,\\n address caller\\n );\\n\\n event SetIsAllowedToSetFirstController(address indexed addr, bool indexed flag, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function controllerOf(uint256 _projectId) external view returns (address);\\n\\n function isAllowedToSetFirstController(address _address) external view returns (bool);\\n\\n function terminalsOf(uint256 _projectId) external view returns (IJBPaymentTerminal[] memory);\\n\\n function isTerminalOf(uint256 _projectId, IJBPaymentTerminal _terminal)\\n external\\n view\\n returns (bool);\\n\\n function primaryTerminalOf(uint256 _projectId, address _token)\\n external\\n view\\n returns (IJBPaymentTerminal);\\n\\n function setControllerOf(uint256 _projectId, address _controller) external;\\n\\n function setTerminalsOf(uint256 _projectId, IJBPaymentTerminal[] calldata _terminals) external;\\n\\n function setPrimaryTerminalOf(\\n uint256 _projectId,\\n address _token,\\n IJBPaymentTerminal _terminal\\n ) external;\\n\\n function setIsAllowedToSetFirstController(address _address, bool _flag) external;\\n}\\n\",\"keccak256\":\"0x715321646db00514d1355ed43c40cd3f01e94959552fd07797b315d9c49cdb1d\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleBallot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../enums/JBBallotState.sol';\\n\\ninterface IJBFundingCycleBallot is IERC165 {\\n function duration() external view returns (uint256);\\n\\n function stateOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n uint256 _start\\n ) external view returns (JBBallotState);\\n}\\n\",\"keccak256\":\"0x49553a56209237846bc400cf27f260824a6bd06fd8094a7eb5abb9de75779598\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleDataSource.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBPayDelegateAllocation.sol';\\nimport './../structs/JBPayParamsData.sol';\\nimport './../structs/JBRedeemParamsData.sol';\\nimport './../structs/JBRedemptionDelegateAllocation.sol';\\n\\n/**\\n @title\\n Datasource\\n\\n @notice\\n The datasource is called by JBPaymentTerminal on pay and redemption, and provide an extra layer of logic to use \\n a custom weight, a custom memo and/or a pay/redeem delegate\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n*/\\ninterface IJBFundingCycleDataSource is IERC165 {\\n /**\\n @notice\\n The datasource implementation for JBPaymentTerminal.pay(..)\\n\\n @param _data the data passed to the data source in terminal.pay(..), as a JBPayParamsData struct:\\n IJBPaymentTerminal terminal;\\n address payer;\\n JBTokenAmount amount;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n address beneficiary;\\n uint256 weight;\\n uint256 reservedRate;\\n string memo;\\n bytes metadata;\\n\\n @return weight the weight to use to override the funding cycle weight\\n @return memo the memo to override the pay(..) memo\\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\\n */\\n function payParams(JBPayParamsData calldata _data)\\n external\\n returns (\\n uint256 weight,\\n string memory memo,\\n JBPayDelegateAllocation[] memory delegateAllocations\\n );\\n\\n /**\\n @notice\\n The datasource implementation for JBPaymentTerminal.redeemTokensOf(..)\\n\\n @param _data the data passed to the data source in terminal.redeemTokensOf(..), as a JBRedeemParamsData struct:\\n IJBPaymentTerminal terminal;\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 tokenCount;\\n uint256 totalSupply;\\n uint256 overflow;\\n JBTokenAmount reclaimAmount;\\n bool useTotalOverflow;\\n uint256 redemptionRate;\\n uint256 ballotRedemptionRate;\\n string memo;\\n bytes metadata;\\n\\n @return reclaimAmount The amount to claim, overriding the terminal logic.\\n @return memo The memo to override the redeemTokensOf(..) memo.\\n @return delegateAllocations The amount to send to delegates instead of adding to the beneficiary.\\n */\\n function redeemParams(JBRedeemParamsData calldata _data)\\n external\\n returns (\\n uint256 reclaimAmount,\\n string memory memo,\\n JBRedemptionDelegateAllocation[] memory delegateAllocations\\n );\\n}\\n\",\"keccak256\":\"0xa424abc146a61b69db83e511c064492da6fab6d8226e13d1580bc9fbc50d6738\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../enums/JBBallotState.sol';\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBFundingCycleData.sol';\\n\\ninterface IJBFundingCycleStore {\\n event Configure(\\n uint256 indexed configuration,\\n uint256 indexed projectId,\\n JBFundingCycleData data,\\n uint256 metadata,\\n uint256 mustStartAtOrAfter,\\n address caller\\n );\\n\\n event Init(uint256 indexed configuration, uint256 indexed projectId, uint256 indexed basedOn);\\n\\n function latestConfigurationOf(uint256 _projectId) external view returns (uint256);\\n\\n function get(uint256 _projectId, uint256 _configuration)\\n external\\n view\\n returns (JBFundingCycle memory);\\n\\n function latestConfiguredOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBBallotState ballotState);\\n\\n function queuedOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentBallotStateOf(uint256 _projectId) external view returns (JBBallotState);\\n\\n function configureFor(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n uint256 _metadata,\\n uint256 _mustStartAtOrAfter\\n ) external returns (JBFundingCycle memory fundingCycle);\\n}\\n\",\"keccak256\":\"0xaead823851433be0c2ddc8f8086813e6cd647de3a1bc0f7570a5d6b38c378b5a\",\"license\":\"MIT\"},\"contracts/interfaces/IJBMigratable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBMigratable {\\n function prepForMigrationOf(uint256 _projectId, address _from) external;\\n}\\n\",\"keccak256\":\"0xc81053e4b4754fc510aa04fecd3ab1460f01e3e27761e7a8c94f631a978ae127\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPayDelegate.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBDidPayData.sol';\\n\\n/**\\n @title\\n Pay delegate\\n\\n @notice\\n Delegate called after JBTerminal.pay(..) logic completion (if passed by the funding cycle datasource)\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n*/\\ninterface IJBPayDelegate is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.pay(..), after the execution of its logic\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control\\n \\n @param _data the data passed by the terminal, as a JBDidPayData struct:\\n address payer;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n JBTokenAmount amount;\\n JBTokenAmount forwardedAmount;\\n uint256 projectTokenCount;\\n address beneficiary;\\n bool preferClaimedTokens;\\n string memo;\\n bytes metadata;\\n */\\n function didPay(JBDidPayData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0xa797de18b69eceba117e1f0b3810cf3cc2d2791417d580a5bdc510d1b868ab26\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\n\\ninterface IJBPaymentTerminal is IERC165 {\\n function acceptsToken(address _token, uint256 _projectId) external view returns (bool);\\n\\n function currencyForToken(address _token) external view returns (uint256);\\n\\n function decimalsForToken(address _token) external view returns (uint256);\\n\\n // Return value must be a fixed point number with 18 decimals.\\n function currentEthOverflowOf(uint256 _projectId) external view returns (uint256);\\n\\n function pay(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable returns (uint256 beneficiaryTokenCount);\\n\\n function addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable;\\n}\\n\",\"keccak256\":\"0xb7826f5ed609359ce322c09e83236c47ba385df1c3cad3607e56fd0a2e00eee2\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPriceFeed.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBPriceFeed {\\n function currentPrice(uint256 _targetDecimals) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x57c71282fec1b34b00cf991ffed2e36031c393e35bfa7ca5d723eb6572fb7122\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPrices.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBPriceFeed.sol';\\n\\ninterface IJBPrices {\\n event AddFeed(uint256 indexed currency, uint256 indexed base, IJBPriceFeed feed);\\n\\n function feedFor(uint256 _currency, uint256 _base) external view returns (IJBPriceFeed);\\n\\n function priceFor(\\n uint256 _currency,\\n uint256 _base,\\n uint256 _decimals\\n ) external view returns (uint256);\\n\\n function addFeedFor(\\n uint256 _currency,\\n uint256 _base,\\n IJBPriceFeed _priceFeed\\n ) external;\\n}\\n\",\"keccak256\":\"0x82a175b1f4b95b506c98406576cd59cbe04615e3df24f9cf3587b61b8ee323b1\",\"license\":\"MIT\"},\"contracts/interfaces/IJBProjects.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBTokenUriResolver.sol';\\n\\ninterface IJBProjects is IERC721 {\\n event Create(\\n uint256 indexed projectId,\\n address indexed owner,\\n JBProjectMetadata metadata,\\n address caller\\n );\\n\\n event SetMetadata(uint256 indexed projectId, JBProjectMetadata metadata, address caller);\\n\\n event SetTokenUriResolver(IJBTokenUriResolver indexed resolver, address caller);\\n\\n function count() external view returns (uint256);\\n\\n function metadataContentOf(uint256 _projectId, uint256 _domain)\\n external\\n view\\n returns (string memory);\\n\\n function tokenUriResolver() external view returns (IJBTokenUriResolver);\\n\\n function createFor(address _owner, JBProjectMetadata calldata _metadata)\\n external\\n returns (uint256 projectId);\\n\\n function setMetadataOf(uint256 _projectId, JBProjectMetadata calldata _metadata) external;\\n\\n function setTokenUriResolver(IJBTokenUriResolver _newResolver) external;\\n}\\n\",\"keccak256\":\"0x7cfc021d0bd7e73b1ba8f4845d7d35e3419d6a14d3d25ca3a8010e7f91062fe4\",\"license\":\"MIT\"},\"contracts/interfaces/IJBRedemptionDelegate.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBDidRedeemData.sol';\\n\\n/**\\n @title\\n Redemption delegate\\n\\n @notice\\n Delegate called after JBTerminal.redeemTokensOf(..) logic completion (if passed by the funding cycle datasource)\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n*/\\ninterface IJBRedemptionDelegate is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.redeemTokensOf(..), after the execution of its logic\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control\\n \\n @param _data the data passed by the terminal, as a JBDidRedeemData struct:\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 projectTokenCount;\\n JBTokenAmount reclaimedAmount;\\n JBTokenAmount forwardedAmount;\\n address payable beneficiary;\\n string memo;\\n bytes metadata;\\n */\\n function didRedeem(JBDidRedeemData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0x172d2c0be65e72e54f71ae521907067f0fa30e8ca05c4f88826903208aa437e2\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSingleTokenPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBPaymentTerminal.sol';\\n\\ninterface IJBSingleTokenPaymentTerminal is IJBPaymentTerminal {\\n function token() external view returns (address);\\n\\n function currency() external view returns (uint256);\\n\\n function decimals() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xf6e78323caa9af7bbf024f44b2032a83fed0394e0b3a242a6346e73c85b2e46f\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSingleTokenPaymentTerminalStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBPayDelegateAllocation.sol';\\nimport './../structs/JBRedemptionDelegateAllocation.sol';\\nimport './../structs/JBTokenAmount.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBPrices.sol';\\nimport './IJBSingleTokenPaymentTerminal.sol';\\n\\ninterface IJBSingleTokenPaymentTerminalStore {\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function prices() external view returns (IJBPrices);\\n\\n function balanceOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\\n external\\n view\\n returns (uint256);\\n\\n function usedDistributionLimitOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _fundingCycleNumber\\n ) external view returns (uint256);\\n\\n function usedOverflowAllowanceOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _fundingCycleConfiguration\\n ) external view returns (uint256);\\n\\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\\n external\\n view\\n returns (uint256);\\n\\n function currentTotalOverflowOf(\\n uint256 _projectId,\\n uint256 _decimals,\\n uint256 _currency\\n ) external view returns (uint256);\\n\\n function currentReclaimableOverflowOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n bool _useTotalOverflow\\n ) external view returns (uint256);\\n\\n function currentReclaimableOverflowOf(\\n uint256 _projectId,\\n uint256 _tokenCount,\\n uint256 _totalSupply,\\n uint256 _overflow\\n ) external view returns (uint256);\\n\\n function recordPaymentFrom(\\n address _payer,\\n JBTokenAmount memory _amount,\\n uint256 _projectId,\\n uint256 _baseWeightCurrency,\\n address _beneficiary,\\n string calldata _memo,\\n bytes calldata _metadata\\n )\\n external\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 tokenCount,\\n JBPayDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n );\\n\\n function recordRedemptionFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n string calldata _memo,\\n bytes calldata _metadata\\n )\\n external\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 reclaimAmount,\\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n );\\n\\n function recordDistributionFor(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n ) external returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount);\\n\\n function recordUsedAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n ) external returns (JBFundingCycle memory fundingCycle, uint256 withdrawnAmount);\\n\\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external;\\n\\n function recordMigration(uint256 _projectId) external returns (uint256 balance);\\n}\\n\",\"keccak256\":\"0xd78929c9371fd7895b829ef5e4ad4b3786523c3580ac3f6f5f25d2b5941c0dd3\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSplitAllocator.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport '../structs/JBSplitAllocationData.sol';\\n\\n/**\\n @title\\n Split allocator\\n\\n @notice\\n Provide a way to process a single split with extra logic\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n\\n @dev\\n The contract address should be set as an allocator in the adequate split\\n*/\\ninterface IJBSplitAllocator is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.distributePayoutOf(..), during the processing of the split including it\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control. The token and/or eth are optimistically transfered\\n to the allocator for its logic.\\n \\n @param _data the data passed by the terminal, as a JBSplitAllocationData struct:\\n address token;\\n uint256 amount;\\n uint256 decimals;\\n uint256 projectId;\\n uint256 group;\\n JBSplit split;\\n */\\n function allocate(JBSplitAllocationData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0x5efb6f51fc161f42ff58989386ad99028e4039a0ba897d66f358c3dfcf686105\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSplitsStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBGroupedSplits.sol';\\nimport './../structs/JBSplit.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBProjects.sol';\\n\\ninterface IJBSplitsStore {\\n event SetSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n address caller\\n );\\n\\n function projects() external view returns (IJBProjects);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function splitsOf(\\n uint256 _projectId,\\n uint256 _domain,\\n uint256 _group\\n ) external view returns (JBSplit[] memory);\\n\\n function set(\\n uint256 _projectId,\\n uint256 _domain,\\n JBGroupedSplits[] memory _groupedSplits\\n ) external;\\n}\\n\",\"keccak256\":\"0x66dab3dd394e318b850401ca92c2963b906cc0ad5562fa5d4f6f850175d1c77a\",\"license\":\"MIT\"},\"contracts/interfaces/IJBToken.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBToken {\\n function projectId() external view returns (uint256);\\n\\n function decimals() external view returns (uint8);\\n\\n function totalSupply(uint256 _projectId) external view returns (uint256);\\n\\n function balanceOf(address _account, uint256 _projectId) external view returns (uint256);\\n\\n function mint(\\n uint256 _projectId,\\n address _account,\\n uint256 _amount\\n ) external;\\n\\n function burn(\\n uint256 _projectId,\\n address _account,\\n uint256 _amount\\n ) external;\\n\\n function approve(\\n uint256,\\n address _spender,\\n uint256 _amount\\n ) external;\\n\\n function transfer(\\n uint256 _projectId,\\n address _to,\\n uint256 _amount\\n ) external;\\n\\n function transferFrom(\\n uint256 _projectId,\\n address _from,\\n address _to,\\n uint256 _amount\\n ) external;\\n}\\n\",\"keccak256\":\"0xe8969210417736c85d71101bf1c0bd8ebbf9d1e62a93e758148bd5709a6c7097\",\"license\":\"MIT\"},\"contracts/interfaces/IJBTokenStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBProjects.sol';\\nimport './IJBToken.sol';\\n\\ninterface IJBTokenStore {\\n event Issue(\\n uint256 indexed projectId,\\n IJBToken indexed token,\\n string name,\\n string symbol,\\n address caller\\n );\\n\\n event Mint(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 amount,\\n bool tokensWereClaimed,\\n bool preferClaimedTokens,\\n address caller\\n );\\n\\n event Burn(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 amount,\\n uint256 initialUnclaimedBalance,\\n uint256 initialClaimedBalance,\\n bool preferClaimedTokens,\\n address caller\\n );\\n\\n event Claim(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 initialUnclaimedBalance,\\n uint256 amount,\\n address caller\\n );\\n\\n event Set(uint256 indexed projectId, IJBToken indexed newToken, address caller);\\n\\n event Transfer(\\n address indexed holder,\\n uint256 indexed projectId,\\n address indexed recipient,\\n uint256 amount,\\n address caller\\n );\\n\\n function tokenOf(uint256 _projectId) external view returns (IJBToken);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function unclaimedBalanceOf(address _holder, uint256 _projectId) external view returns (uint256);\\n\\n function unclaimedTotalSupplyOf(uint256 _projectId) external view returns (uint256);\\n\\n function totalSupplyOf(uint256 _projectId) external view returns (uint256);\\n\\n function balanceOf(address _holder, uint256 _projectId) external view returns (uint256 _result);\\n\\n function issueFor(\\n uint256 _projectId,\\n string calldata _name,\\n string calldata _symbol\\n ) external returns (IJBToken token);\\n\\n function setFor(uint256 _projectId, IJBToken _token) external;\\n\\n function burnFrom(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function mintFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function claimFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount\\n ) external;\\n\\n function transferFrom(\\n address _holder,\\n uint256 _projectId,\\n address _recipient,\\n uint256 _amount\\n ) external;\\n}\\n\",\"keccak256\":\"0x98459e3af050d41dfeffdc97f1c93330207ba450f8ff3613224b49a89eeca9c6\",\"license\":\"MIT\"},\"contracts/interfaces/IJBTokenUriResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBTokenUriResolver {\\n function getUri(uint256 _projectId) external view returns (string memory tokenUri);\\n}\\n\",\"keccak256\":\"0xd267fd8ca7c21c2c71794acdb9a98314c33a35fc559e0bf0897a6686d196d174\",\"license\":\"MIT\"},\"contracts/libraries/JBConstants.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/**\\n @notice\\n Global constants used across Juicebox contracts.\\n*/\\nlibrary JBConstants {\\n uint256 public constant MAX_RESERVED_RATE = 10_000;\\n uint256 public constant MAX_REDEMPTION_RATE = 10_000;\\n uint256 public constant MAX_DISCOUNT_RATE = 1_000_000_000;\\n uint256 public constant SPLITS_TOTAL_PERCENT = 1_000_000_000;\\n uint256 public constant MAX_FEE = 1_000_000_000;\\n uint256 public constant MAX_FEE_DISCOUNT = 1_000_000_000;\\n}\\n\",\"keccak256\":\"0x34362846a1cd428a8bdedf4ab6857e11402f345cb87b994b2e7fb6d2474b808d\",\"license\":\"MIT\"},\"contracts/libraries/JBCurrencies.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBCurrencies {\\n uint256 public constant ETH = 1;\\n uint256 public constant USD = 2;\\n}\\n\",\"keccak256\":\"0x7e417ff25c173608ee4fe6d9fc3dcd5e1458c78c889af12bac47b1189a436076\",\"license\":\"MIT\"},\"contracts/libraries/JBFixedPointNumber.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nlibrary JBFixedPointNumber {\\n function adjustDecimals(\\n uint256 _value,\\n uint256 _decimals,\\n uint256 _targetDecimals\\n ) internal pure returns (uint256) {\\n // If decimals need adjusting, multiply or divide the price by the decimal adjuster to get the normalized result.\\n if (_targetDecimals == _decimals) return _value;\\n else if (_targetDecimals > _decimals) return _value * 10**(_targetDecimals - _decimals);\\n else return _value / 10**(_decimals - _targetDecimals);\\n }\\n}\\n\",\"keccak256\":\"0x18efac48269f3a3bd7e9a1c770776f950e0afa86769e6f8b128002c3b8c6742c\",\"license\":\"MIT\"},\"contracts/libraries/JBFundingCycleMetadataResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBFundingCycleMetadata.sol';\\nimport './../structs/JBGlobalFundingCycleMetadata.sol';\\nimport './JBConstants.sol';\\nimport './JBGlobalFundingCycleMetadataResolver.sol';\\n\\nlibrary JBFundingCycleMetadataResolver {\\n function global(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (JBGlobalFundingCycleMetadata memory)\\n {\\n return JBGlobalFundingCycleMetadataResolver.expandMetadata(uint8(_fundingCycle.metadata >> 8));\\n }\\n\\n function reservedRate(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n return uint256(uint16(_fundingCycle.metadata >> 24));\\n }\\n\\n function redemptionRate(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n // Redemption rate is a number 0-10000. It's inverse was stored so the most common case of 100% results in no storage needs.\\n return JBConstants.MAX_REDEMPTION_RATE - uint256(uint16(_fundingCycle.metadata >> 40));\\n }\\n\\n function ballotRedemptionRate(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (uint256)\\n {\\n // Redemption rate is a number 0-10000. It's inverse was stored so the most common case of 100% results in no storage needs.\\n return JBConstants.MAX_REDEMPTION_RATE - uint256(uint16(_fundingCycle.metadata >> 56));\\n }\\n\\n function payPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 72) & 1) == 1;\\n }\\n\\n function distributionsPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 73) & 1) == 1;\\n }\\n\\n function redeemPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 74) & 1) == 1;\\n }\\n\\n function burnPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 75) & 1) == 1;\\n }\\n\\n function mintingAllowed(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 76) & 1) == 1;\\n }\\n\\n function terminalMigrationAllowed(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 77) & 1) == 1;\\n }\\n\\n function controllerMigrationAllowed(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 78) & 1) == 1;\\n }\\n\\n function shouldHoldFees(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 79) & 1) == 1;\\n }\\n\\n function preferClaimedTokenOverride(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 80) & 1) == 1;\\n }\\n\\n function useTotalOverflowForRedemptions(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 81) & 1) == 1;\\n }\\n\\n function useDataSourceForPay(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return (_fundingCycle.metadata >> 82) & 1 == 1;\\n }\\n\\n function useDataSourceForRedeem(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return (_fundingCycle.metadata >> 83) & 1 == 1;\\n }\\n\\n function dataSource(JBFundingCycle memory _fundingCycle) internal pure returns (address) {\\n return address(uint160(_fundingCycle.metadata >> 84));\\n }\\n\\n function metadata(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n return uint256(uint8(_fundingCycle.metadata >> 244));\\n }\\n\\n /**\\n @notice\\n Pack the funding cycle metadata.\\n\\n @param _metadata The metadata to validate and pack.\\n\\n @return packed The packed uint256 of all metadata params. The first 8 bits specify the version.\\n */\\n function packFundingCycleMetadata(JBFundingCycleMetadata memory _metadata)\\n internal\\n pure\\n returns (uint256 packed)\\n {\\n // version 1 in the bits 0-7 (8 bits).\\n packed = 1;\\n // global metadta in bits 8-23 (16 bits).\\n packed |=\\n JBGlobalFundingCycleMetadataResolver.packFundingCycleGlobalMetadata(_metadata.global) <<\\n 8;\\n // reserved rate in bits 24-39 (16 bits).\\n packed |= _metadata.reservedRate << 24;\\n // redemption rate in bits 40-55 (16 bits).\\n // redemption rate is a number 0-10000. Store the reverse so the most common case of 100% results in no storage needs.\\n packed |= (JBConstants.MAX_REDEMPTION_RATE - _metadata.redemptionRate) << 40;\\n // ballot redemption rate rate in bits 56-71 (16 bits).\\n // ballot redemption rate is a number 0-10000. Store the reverse so the most common case of 100% results in no storage needs.\\n packed |= (JBConstants.MAX_REDEMPTION_RATE - _metadata.ballotRedemptionRate) << 56;\\n // pause pay in bit 72.\\n if (_metadata.pausePay) packed |= 1 << 72;\\n // pause tap in bit 73.\\n if (_metadata.pauseDistributions) packed |= 1 << 73;\\n // pause redeem in bit 74.\\n if (_metadata.pauseRedeem) packed |= 1 << 74;\\n // pause burn in bit 75.\\n if (_metadata.pauseBurn) packed |= 1 << 75;\\n // allow minting in bit 76.\\n if (_metadata.allowMinting) packed |= 1 << 76;\\n // allow terminal migration in bit 77.\\n if (_metadata.allowTerminalMigration) packed |= 1 << 77;\\n // allow controller migration in bit 78.\\n if (_metadata.allowControllerMigration) packed |= 1 << 78;\\n // hold fees in bit 79.\\n if (_metadata.holdFees) packed |= 1 << 79;\\n // prefer claimed token override in bit 80.\\n if (_metadata.preferClaimedTokenOverride) packed |= 1 << 80;\\n // useTotalOverflowForRedemptions in bit 81.\\n if (_metadata.useTotalOverflowForRedemptions) packed |= 1 << 81;\\n // use pay data source in bit 82.\\n if (_metadata.useDataSourceForPay) packed |= 1 << 82;\\n // use redeem data source in bit 83.\\n if (_metadata.useDataSourceForRedeem) packed |= 1 << 83;\\n // data source address in bits 84-243.\\n packed |= uint256(uint160(address(_metadata.dataSource))) << 84;\\n // metadata in bits 244-252 (8 bits).\\n packed |= _metadata.metadata << 244;\\n }\\n\\n /**\\n @notice\\n Expand the funding cycle metadata.\\n\\n @param _fundingCycle The funding cycle having its metadata expanded.\\n\\n @return metadata The metadata object.\\n */\\n function expandMetadata(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (JBFundingCycleMetadata memory)\\n {\\n return\\n JBFundingCycleMetadata(\\n global(_fundingCycle),\\n reservedRate(_fundingCycle),\\n redemptionRate(_fundingCycle),\\n ballotRedemptionRate(_fundingCycle),\\n payPaused(_fundingCycle),\\n distributionsPaused(_fundingCycle),\\n redeemPaused(_fundingCycle),\\n burnPaused(_fundingCycle),\\n mintingAllowed(_fundingCycle),\\n terminalMigrationAllowed(_fundingCycle),\\n controllerMigrationAllowed(_fundingCycle),\\n shouldHoldFees(_fundingCycle),\\n preferClaimedTokenOverride(_fundingCycle),\\n useTotalOverflowForRedemptions(_fundingCycle),\\n useDataSourceForPay(_fundingCycle),\\n useDataSourceForRedeem(_fundingCycle),\\n dataSource(_fundingCycle),\\n metadata(_fundingCycle)\\n );\\n }\\n}\\n\",\"keccak256\":\"0x3d045c38593102cfb6ac67f3ddf2232e1ff5518d6d021423ae2681387599fbd3\",\"license\":\"MIT\"},\"contracts/libraries/JBGlobalFundingCycleMetadataResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport './../structs/JBFundingCycleMetadata.sol';\\n\\nlibrary JBGlobalFundingCycleMetadataResolver {\\n function setTerminalsAllowed(uint8 _data) internal pure returns (bool) {\\n return (_data & 1) == 1;\\n }\\n\\n function setControllerAllowed(uint8 _data) internal pure returns (bool) {\\n return ((_data >> 1) & 1) == 1;\\n }\\n\\n function transfersPaused(uint8 _data) internal pure returns (bool) {\\n return ((_data >> 2) & 1) == 1;\\n }\\n\\n /**\\n @notice\\n Pack the global funding cycle metadata.\\n\\n @param _metadata The metadata to validate and pack.\\n\\n @return packed The packed uint256 of all global metadata params. The first 8 bits specify the version.\\n */\\n function packFundingCycleGlobalMetadata(JBGlobalFundingCycleMetadata memory _metadata)\\n internal\\n pure\\n returns (uint256 packed)\\n {\\n // allow set terminals in bit 0.\\n if (_metadata.allowSetTerminals) packed |= 1;\\n // allow set controller in bit 1.\\n if (_metadata.allowSetController) packed |= 1 << 1;\\n // pause transfers in bit 2.\\n if (_metadata.pauseTransfers) packed |= 1 << 2;\\n }\\n\\n /**\\n @notice\\n Expand the global funding cycle metadata.\\n\\n @param _packedMetadata The packed metadata to expand.\\n\\n @return metadata The global metadata object.\\n */\\n function expandMetadata(uint8 _packedMetadata)\\n internal\\n pure\\n returns (JBGlobalFundingCycleMetadata memory metadata)\\n {\\n return\\n JBGlobalFundingCycleMetadata(\\n setTerminalsAllowed(_packedMetadata),\\n setControllerAllowed(_packedMetadata),\\n transfersPaused(_packedMetadata)\\n );\\n }\\n}\\n\",\"keccak256\":\"0x0d998f938026edeb755987a79421267cf860801161b5f171206a200b60f1061f\",\"license\":\"MIT\"},\"contracts/structs/JBDidPayData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member payer The address from which the payment originated.\\n @member projectId The ID of the project for which the payment was made.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the payment is being made.\\n @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.\\n @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.\\n @member projectTokenCount The number of project tokens minted for the beneficiary.\\n @member beneficiary The address to which the tokens were minted.\\n @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.\\n @member memo The memo that is being emitted alongside the payment.\\n @member metadata Extra data to send to the delegate.\\n*/\\nstruct JBDidPayData {\\n address payer;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n JBTokenAmount amount;\\n JBTokenAmount forwardedAmount;\\n uint256 projectTokenCount;\\n address beneficiary;\\n bool preferClaimedTokens;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0xf3c664309b37790f16047ae97b0459889ae0242dfcde7fc8902c8d10c7f8e6b6\",\"license\":\"MIT\"},\"contracts/structs/JBDidRedeemData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member holder The holder of the tokens being redeemed.\\n @member projectId The ID of the project with which the redeemed tokens are associated.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the redemption is being made.\\n @member projectTokenCount The number of project tokens being redeemed.\\n @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.\\n @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.\\n @member beneficiary The address to which the reclaimed amount will be sent.\\n @member memo The memo that is being emitted alongside the redemption.\\n @member metadata Extra data to send to the delegate.\\n*/\\nstruct JBDidRedeemData {\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 projectTokenCount;\\n JBTokenAmount reclaimedAmount;\\n JBTokenAmount forwardedAmount;\\n address payable beneficiary;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0xe2c401f39723a7ce915b8bef328744c66daaf57460843964b941456c2258a412\",\"license\":\"MIT\"},\"contracts/structs/JBFundAccessConstraints.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBPaymentTerminal.sol';\\n\\n/** \\n @member terminal The terminal within which the distribution limit and the overflow allowance applies.\\n @member token The token for which the fund access constraints apply.\\n @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.\\n @member distributionLimitCurrency The currency of the distribution limit.\\n @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.\\n @member overflowAllowanceCurrency The currency of the overflow allowance.\\n*/\\nstruct JBFundAccessConstraints {\\n IJBPaymentTerminal terminal;\\n address token;\\n uint256 distributionLimit;\\n uint256 distributionLimitCurrency;\\n uint256 overflowAllowance;\\n uint256 overflowAllowanceCurrency;\\n}\\n\",\"keccak256\":\"0x85ebaa57b788cbdedc7a3d0eec4892eda5d79db7c1a6103797f10d0d989775b2\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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.\\n @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.\\n @member basedOn The `configuration` of the funding cycle that was active when this cycle was created.\\n @member start The timestamp marking the moment from which the funding cycle is considered active. It is a unix timestamp measured in seconds.\\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n @member metadata Extra data that can be associated with a funding cycle.\\n*/\\nstruct JBFundingCycle {\\n uint256 number;\\n uint256 configuration;\\n uint256 basedOn;\\n uint256 start;\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n uint256 metadata;\\n}\\n\",\"keccak256\":\"0xcdd3ac9b6fa67e62ada88d09b73bc35ade1cd77d43db712289266a788928b4c2\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycleData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n*/\\nstruct JBFundingCycleData {\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n}\\n\",\"keccak256\":\"0x2aa6368bf4dfc5797e8b02a978293de0c777fae2658de2c825a103587240f3b0\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycleMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBGlobalFundingCycleMetadata.sol';\\n\\n/** \\n @member global Data used globally in non-migratable ecosystem contracts.\\n @member reservedRate The reserved rate of the funding cycle. This number is a percentage calculated out of `JBConstants.MAX_RESERVED_RATE`.\\n @member redemptionRate The redemption rate of the funding cycle. This number is a percentage calculated out of `JBConstants.MAX_REDEMPTION_RATE`.\\n @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`.\\n @member pausePay A flag indicating if the pay functionality should be paused during the funding cycle.\\n @member pauseDistributions A flag indicating if the distribute functionality should be paused during the funding cycle.\\n @member pauseRedeem A flag indicating if the redeem functionality should be paused during the funding cycle.\\n @member pauseBurn A flag indicating if the burn functionality should be paused during the funding cycle.\\n @member allowMinting A flag indicating if minting tokens should be allowed during this funding cycle.\\n @member allowTerminalMigration A flag indicating if migrating terminals should be allowed during this funding cycle.\\n @member allowControllerMigration A flag indicating if migrating controllers should be allowed during this funding cycle.\\n @member holdFees A flag indicating if fees should be held during this funding cycle.\\n @member preferClaimedTokenOverride A flag indicating if claimed tokens should always be prefered to unclaimed tokens when minting.\\n @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.\\n @member useDataSourceForPay A flag indicating if the data source should be used for pay transactions during this funding cycle.\\n @member useDataSourceForRedeem A flag indicating if the data source should be used for redeem transactions during this funding cycle.\\n @member dataSource The data source to use during this funding cycle.\\n @member metadata Metadata of the metadata, up to uint8 in size.\\n*/\\nstruct JBFundingCycleMetadata {\\n JBGlobalFundingCycleMetadata global;\\n uint256 reservedRate;\\n uint256 redemptionRate;\\n uint256 ballotRedemptionRate;\\n bool pausePay;\\n bool pauseDistributions;\\n bool pauseRedeem;\\n bool pauseBurn;\\n bool allowMinting;\\n bool allowTerminalMigration;\\n bool allowControllerMigration;\\n bool holdFees;\\n bool preferClaimedTokenOverride;\\n bool useTotalOverflowForRedemptions;\\n bool useDataSourceForPay;\\n bool useDataSourceForRedeem;\\n address dataSource;\\n uint256 metadata;\\n}\\n\",\"keccak256\":\"0x783604440cac8d176332eab28166f188ee5c230378c08cfc95fea4f7187dc77d\",\"license\":\"MIT\"},\"contracts/structs/JBGlobalFundingCycleMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member allowSetTerminals A flag indicating if setting terminals should be allowed during this funding cycle.\\n @member allowSetController A flag indicating if setting a new controller should be allowed during this funding cycle.\\n @member pauseTransfers A flag indicating if the project token transfer functionality should be paused during the funding cycle.\\n*/\\nstruct JBGlobalFundingCycleMetadata {\\n bool allowSetTerminals;\\n bool allowSetController;\\n bool pauseTransfers;\\n}\\n\",\"keccak256\":\"0x05d85530305fec6d6eca54cdbc2cd9110cbda0146598032b0203aa4b622944ff\",\"license\":\"MIT\"},\"contracts/structs/JBGroupedSplits.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBSplit.sol';\\n\\n/** \\n @member group The group indentifier.\\n @member splits The splits to associate with the group.\\n*/\\nstruct JBGroupedSplits {\\n uint256 group;\\n JBSplit[] splits;\\n}\\n\",\"keccak256\":\"0x80be1b220da4ac04851ea540ebb94c1ec2b0442ec5bd1e88fdf78a56becd8b5a\",\"license\":\"MIT\"},\"contracts/structs/JBPayDelegateAllocation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '../interfaces/IJBPayDelegate.sol';\\n\\n/** \\n @member delegate A delegate contract to use for subsequent calls.\\n @member amount The amount to send to the delegate.\\n*/\\nstruct JBPayDelegateAllocation {\\n IJBPayDelegate delegate;\\n uint256 amount;\\n}\\n\",\"keccak256\":\"0xb4e558dc62231d89e9b48998012577d22c3e52b58e23401f22d9096827f6ea0c\",\"license\":\"MIT\"},\"contracts/structs/JBPayParamsData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBPaymentTerminal.sol';\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member terminal The terminal that is facilitating the payment.\\n @member payer The address from which the payment originated.\\n @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.\\n @member projectId The ID of the project being paid.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the payment is being made.\\n @member beneficiary The specified address that should be the beneficiary of anything that results from the payment.\\n @member weight The weight of the funding cycle during which the payment is being made.\\n @member reservedRate The reserved rate of the funding cycle during which the payment is being made.\\n @member memo The memo that was sent alongside the payment.\\n @member metadata Extra data provided by the payer.\\n*/\\nstruct JBPayParamsData {\\n IJBPaymentTerminal terminal;\\n address payer;\\n JBTokenAmount amount;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n address beneficiary;\\n uint256 weight;\\n uint256 reservedRate;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0x05007b26feb5d9a026b883c6d734a341b5a49ef7b8215fb40507882e2c14e24d\",\"license\":\"MIT\"},\"contracts/structs/JBProjectMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member content The metadata content.\\n @member domain The domain within which the metadata applies.\\n*/\\nstruct JBProjectMetadata {\\n string content;\\n uint256 domain;\\n}\\n\",\"keccak256\":\"0x90ad7b1014c0a9f945fe7a2efde9d5de41e40574fa27969070b1d2ff52033ea0\",\"license\":\"MIT\"},\"contracts/structs/JBRedeemParamsData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBPaymentTerminal.sol';\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member terminal The terminal that is facilitating the redemption.\\n @member holder The holder of the tokens being redeemed.\\n @member projectId The ID of the project whos tokens are being redeemed.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the redemption is being made.\\n @member tokenCount The proposed number of tokens being redeemed, as a fixed point number with 18 decimals.\\n @member totalSupply The total supply of tokens used in the calculation, as a fixed point number with 18 decimals.\\n @member overflow The amount of overflow used in the reclaim amount calculation.\\n @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.\\n @member useTotalOverflow If overflow across all of a project's terminals is being used when making redemptions.\\n @member redemptionRate The redemption rate of the funding cycle during which the redemption is being made.\\n @member memo The proposed memo that is being emitted alongside the redemption.\\n @member metadata Extra data provided by the redeemer.\\n*/\\nstruct JBRedeemParamsData {\\n IJBPaymentTerminal terminal;\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 tokenCount;\\n uint256 totalSupply;\\n uint256 overflow;\\n JBTokenAmount reclaimAmount;\\n bool useTotalOverflow;\\n uint256 redemptionRate;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0x5065a824ebb34952f016c6dfa47e8a7ac28427b719470e74a41022c11ace7788\",\"license\":\"MIT\"},\"contracts/structs/JBRedemptionDelegateAllocation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '../interfaces/IJBRedemptionDelegate.sol';\\n\\n/** \\n @member delegate A delegate contract to use for subsequent calls.\\n @member amount The amount to send to the delegate.\\n*/\\nstruct JBRedemptionDelegateAllocation {\\n IJBRedemptionDelegate delegate;\\n uint256 amount;\\n}\\n\",\"keccak256\":\"0x10c29d33dd0d875a0d4692a2b9a9355c2ebf433cc06a9a60253d4366b60d4d31\",\"license\":\"MIT\"},\"contracts/structs/JBSplit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBSplitAllocator.sol';\\n\\n/** \\n @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.\\n @member preferAddToBalance A flag indicating if a distribution to a project should prefer triggering it's addToBalance function instead of its pay function.\\n @member percent The percent of the whole group that this split occupies. This number is out of `JBConstants.SPLITS_TOTAL_PERCENT`.\\n @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.\\n @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.\\n @member lockedUntil Specifies if the split should be unchangeable until the specified time, with the exception of extending the locked period.\\n @member allocator If an allocator is specified, funds will be sent to the allocator contract along with all properties of this split.\\n*/\\nstruct JBSplit {\\n bool preferClaimed;\\n bool preferAddToBalance;\\n uint256 percent;\\n uint256 projectId;\\n address payable beneficiary;\\n uint256 lockedUntil;\\n IJBSplitAllocator allocator;\\n}\\n\",\"keccak256\":\"0xc80a16606da8abf76d0f73abc38aee041e24f29342c1939018f70c286e89f105\",\"license\":\"MIT\"},\"contracts/structs/JBSplitAllocationData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBSplit.sol';\\n\\n/** \\n @member token The token being sent to the split allocator.\\n @member amount The amount being sent to the split allocator, as a fixed point number.\\n @member decimals The number of decimals in the amount.\\n @member projectId The project to which the split belongs.\\n @member group The group to which the split belongs.\\n @member split The split that caused the allocation.\\n*/\\nstruct JBSplitAllocationData {\\n address token;\\n uint256 amount;\\n uint256 decimals;\\n uint256 projectId;\\n uint256 group;\\n JBSplit split;\\n}\\n\",\"keccak256\":\"0x39f5c41bd31d36774744698ac94484b6cab62d7038df2f29d947668959782e63\",\"license\":\"MIT\"},\"contracts/structs/JBTokenAmount.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/* \\n @member token The token the payment was made in.\\n @member value The amount of tokens that was paid, as a fixed point number.\\n @member decimals The number of decimals included in the value fixed point number.\\n @member currency The expected currency of the value.\\n**/\\nstruct JBTokenAmount {\\n address token;\\n uint256 value;\\n uint256 decimals;\\n uint256 currency;\\n}\\n\",\"keccak256\":\"0x4a778e779ba257ba5638c5469e07a4d21b55a3128d56db5a0fdfacb1f3301c51\",\"license\":\"MIT\"},\"prb-math/contracts/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivFixedPointOverflow(uint256 prod1);\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivOverflow(uint256 prod1, uint256 denominator);\\n\\n/// @notice Emitted when one of the inputs is type(int256).min.\\nerror PRBMath__MulDivSignedInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows int256.\\nerror PRBMath__MulDivSignedOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is MIN_SD59x18.\\nerror PRBMathSD59x18__AbsInputTooSmall();\\n\\n/// @notice Emitted when ceiling a number overflows SD59x18.\\nerror PRBMathSD59x18__CeilOverflow(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__DivInputTooSmall();\\n\\n/// @notice Emitted when one of the intermediary unsigned results overflows SD59x18.\\nerror PRBMathSD59x18__DivOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathSD59x18__ExpInputTooBig(int256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathSD59x18__Exp2InputTooBig(int256 x);\\n\\n/// @notice Emitted when flooring a number underflows SD59x18.\\nerror PRBMathSD59x18__FloorUnderflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format overflows SD59x18.\\nerror PRBMathSD59x18__FromIntOverflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format underflows SD59x18.\\nerror PRBMathSD59x18__FromIntUnderflow(int256 x);\\n\\n/// @notice Emitted when the product of the inputs is negative.\\nerror PRBMathSD59x18__GmNegativeProduct(int256 x, int256 y);\\n\\n/// @notice Emitted when multiplying the inputs overflows SD59x18.\\nerror PRBMathSD59x18__GmOverflow(int256 x, int256 y);\\n\\n/// @notice Emitted when the input is less than or equal to zero.\\nerror PRBMathSD59x18__LogInputTooSmall(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__MulInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__MulOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__PowuOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is negative.\\nerror PRBMathSD59x18__SqrtNegativeInput(int256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows SD59x18.\\nerror PRBMathSD59x18__SqrtOverflow(int256 x);\\n\\n/// @notice Emitted when addition overflows UD60x18.\\nerror PRBMathUD60x18__AddOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when ceiling a number overflows UD60x18.\\nerror PRBMathUD60x18__CeilOverflow(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathUD60x18__ExpInputTooBig(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathUD60x18__Exp2InputTooBig(uint256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format format overflows UD60x18.\\nerror PRBMathUD60x18__FromUintOverflow(uint256 x);\\n\\n/// @notice Emitted when multiplying the inputs overflows UD60x18.\\nerror PRBMathUD60x18__GmOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when the input is less than 1.\\nerror PRBMathUD60x18__LogInputTooSmall(uint256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows UD60x18.\\nerror PRBMathUD60x18__SqrtOverflow(uint256 x);\\n\\n/// @notice Emitted when subtraction underflows UD60x18.\\nerror PRBMathUD60x18__SubUnderflow(uint256 x, uint256 y);\\n\\n/// @dev Common mathematical functions used in both PRBMathSD59x18 and PRBMathUD60x18. Note that this shared library\\n/// does not always assume the signed 59.18-decimal fixed-point or the unsigned 60.18-decimal fixed-point\\n/// representation. When it does not, it is explicitly mentioned in the NatSpec documentation.\\nlibrary PRBMath {\\n /// STRUCTS ///\\n\\n struct SD59x18 {\\n int256 value;\\n }\\n\\n struct UD60x18 {\\n uint256 value;\\n }\\n\\n /// STORAGE ///\\n\\n /// @dev How many trailing decimals can be represented.\\n uint256 internal constant SCALE = 1e18;\\n\\n /// @dev Largest power of two divisor of SCALE.\\n uint256 internal constant SCALE_LPOTD = 262144;\\n\\n /// @dev SCALE inverted mod 2^256.\\n uint256 internal constant SCALE_INVERSE =\\n 78156646155174841979727994598816262306175212592076161876661_508869554232690281;\\n\\n /// FUNCTIONS ///\\n\\n /// @notice Calculates the binary exponent of x using the binary fraction method.\\n /// @dev Has to use 192.64-bit fixed-point numbers.\\n /// See https://ethereum.stackexchange.com/a/96594/24693.\\n /// @param x The exponent as an unsigned 192.64-bit fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp2(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n // Start from 0.5 in the 192.64-bit fixed-point format.\\n result = 0x800000000000000000000000000000000000000000000000;\\n\\n // Multiply the result by root(2, 2^-i) when the bit at position i is 1. None of the intermediary results overflows\\n // because the initial result is 2^191 and all magic factors are less than 2^65.\\n if (x & 0x8000000000000000 > 0) {\\n result = (result * 0x16A09E667F3BCC909) >> 64;\\n }\\n if (x & 0x4000000000000000 > 0) {\\n result = (result * 0x1306FE0A31B7152DF) >> 64;\\n }\\n if (x & 0x2000000000000000 > 0) {\\n result = (result * 0x1172B83C7D517ADCE) >> 64;\\n }\\n if (x & 0x1000000000000000 > 0) {\\n result = (result * 0x10B5586CF9890F62A) >> 64;\\n }\\n if (x & 0x800000000000000 > 0) {\\n result = (result * 0x1059B0D31585743AE) >> 64;\\n }\\n if (x & 0x400000000000000 > 0) {\\n result = (result * 0x102C9A3E778060EE7) >> 64;\\n }\\n if (x & 0x200000000000000 > 0) {\\n result = (result * 0x10163DA9FB33356D8) >> 64;\\n }\\n if (x & 0x100000000000000 > 0) {\\n result = (result * 0x100B1AFA5ABCBED61) >> 64;\\n }\\n if (x & 0x80000000000000 > 0) {\\n result = (result * 0x10058C86DA1C09EA2) >> 64;\\n }\\n if (x & 0x40000000000000 > 0) {\\n result = (result * 0x1002C605E2E8CEC50) >> 64;\\n }\\n if (x & 0x20000000000000 > 0) {\\n result = (result * 0x100162F3904051FA1) >> 64;\\n }\\n if (x & 0x10000000000000 > 0) {\\n result = (result * 0x1000B175EFFDC76BA) >> 64;\\n }\\n if (x & 0x8000000000000 > 0) {\\n result = (result * 0x100058BA01FB9F96D) >> 64;\\n }\\n if (x & 0x4000000000000 > 0) {\\n result = (result * 0x10002C5CC37DA9492) >> 64;\\n }\\n if (x & 0x2000000000000 > 0) {\\n result = (result * 0x1000162E525EE0547) >> 64;\\n }\\n if (x & 0x1000000000000 > 0) {\\n result = (result * 0x10000B17255775C04) >> 64;\\n }\\n if (x & 0x800000000000 > 0) {\\n result = (result * 0x1000058B91B5BC9AE) >> 64;\\n }\\n if (x & 0x400000000000 > 0) {\\n result = (result * 0x100002C5C89D5EC6D) >> 64;\\n }\\n if (x & 0x200000000000 > 0) {\\n result = (result * 0x10000162E43F4F831) >> 64;\\n }\\n if (x & 0x100000000000 > 0) {\\n result = (result * 0x100000B1721BCFC9A) >> 64;\\n }\\n if (x & 0x80000000000 > 0) {\\n result = (result * 0x10000058B90CF1E6E) >> 64;\\n }\\n if (x & 0x40000000000 > 0) {\\n result = (result * 0x1000002C5C863B73F) >> 64;\\n }\\n if (x & 0x20000000000 > 0) {\\n result = (result * 0x100000162E430E5A2) >> 64;\\n }\\n if (x & 0x10000000000 > 0) {\\n result = (result * 0x1000000B172183551) >> 64;\\n }\\n if (x & 0x8000000000 > 0) {\\n result = (result * 0x100000058B90C0B49) >> 64;\\n }\\n if (x & 0x4000000000 > 0) {\\n result = (result * 0x10000002C5C8601CC) >> 64;\\n }\\n if (x & 0x2000000000 > 0) {\\n result = (result * 0x1000000162E42FFF0) >> 64;\\n }\\n if (x & 0x1000000000 > 0) {\\n result = (result * 0x10000000B17217FBB) >> 64;\\n }\\n if (x & 0x800000000 > 0) {\\n result = (result * 0x1000000058B90BFCE) >> 64;\\n }\\n if (x & 0x400000000 > 0) {\\n result = (result * 0x100000002C5C85FE3) >> 64;\\n }\\n if (x & 0x200000000 > 0) {\\n result = (result * 0x10000000162E42FF1) >> 64;\\n }\\n if (x & 0x100000000 > 0) {\\n result = (result * 0x100000000B17217F8) >> 64;\\n }\\n if (x & 0x80000000 > 0) {\\n result = (result * 0x10000000058B90BFC) >> 64;\\n }\\n if (x & 0x40000000 > 0) {\\n result = (result * 0x1000000002C5C85FE) >> 64;\\n }\\n if (x & 0x20000000 > 0) {\\n result = (result * 0x100000000162E42FF) >> 64;\\n }\\n if (x & 0x10000000 > 0) {\\n result = (result * 0x1000000000B17217F) >> 64;\\n }\\n if (x & 0x8000000 > 0) {\\n result = (result * 0x100000000058B90C0) >> 64;\\n }\\n if (x & 0x4000000 > 0) {\\n result = (result * 0x10000000002C5C860) >> 64;\\n }\\n if (x & 0x2000000 > 0) {\\n result = (result * 0x1000000000162E430) >> 64;\\n }\\n if (x & 0x1000000 > 0) {\\n result = (result * 0x10000000000B17218) >> 64;\\n }\\n if (x & 0x800000 > 0) {\\n result = (result * 0x1000000000058B90C) >> 64;\\n }\\n if (x & 0x400000 > 0) {\\n result = (result * 0x100000000002C5C86) >> 64;\\n }\\n if (x & 0x200000 > 0) {\\n result = (result * 0x10000000000162E43) >> 64;\\n }\\n if (x & 0x100000 > 0) {\\n result = (result * 0x100000000000B1721) >> 64;\\n }\\n if (x & 0x80000 > 0) {\\n result = (result * 0x10000000000058B91) >> 64;\\n }\\n if (x & 0x40000 > 0) {\\n result = (result * 0x1000000000002C5C8) >> 64;\\n }\\n if (x & 0x20000 > 0) {\\n result = (result * 0x100000000000162E4) >> 64;\\n }\\n if (x & 0x10000 > 0) {\\n result = (result * 0x1000000000000B172) >> 64;\\n }\\n if (x & 0x8000 > 0) {\\n result = (result * 0x100000000000058B9) >> 64;\\n }\\n if (x & 0x4000 > 0) {\\n result = (result * 0x10000000000002C5D) >> 64;\\n }\\n if (x & 0x2000 > 0) {\\n result = (result * 0x1000000000000162E) >> 64;\\n }\\n if (x & 0x1000 > 0) {\\n result = (result * 0x10000000000000B17) >> 64;\\n }\\n if (x & 0x800 > 0) {\\n result = (result * 0x1000000000000058C) >> 64;\\n }\\n if (x & 0x400 > 0) {\\n result = (result * 0x100000000000002C6) >> 64;\\n }\\n if (x & 0x200 > 0) {\\n result = (result * 0x10000000000000163) >> 64;\\n }\\n if (x & 0x100 > 0) {\\n result = (result * 0x100000000000000B1) >> 64;\\n }\\n if (x & 0x80 > 0) {\\n result = (result * 0x10000000000000059) >> 64;\\n }\\n if (x & 0x40 > 0) {\\n result = (result * 0x1000000000000002C) >> 64;\\n }\\n if (x & 0x20 > 0) {\\n result = (result * 0x10000000000000016) >> 64;\\n }\\n if (x & 0x10 > 0) {\\n result = (result * 0x1000000000000000B) >> 64;\\n }\\n if (x & 0x8 > 0) {\\n result = (result * 0x10000000000000006) >> 64;\\n }\\n if (x & 0x4 > 0) {\\n result = (result * 0x10000000000000003) >> 64;\\n }\\n if (x & 0x2 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n if (x & 0x1 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n\\n // We're doing two things at the same time:\\n //\\n // 1. Multiply the result by 2^n + 1, where \\\"2^n\\\" is the integer part and the one is added to account for\\n // the fact that we initially set the result to 0.5. This is accomplished by subtracting from 191\\n // rather than 192.\\n // 2. Convert the result to the unsigned 60.18-decimal fixed-point format.\\n //\\n // This works because 2^(191-ip) = 2^ip / 2^191, where \\\"ip\\\" is the integer part \\\"2^n\\\".\\n result *= SCALE;\\n result >>= (191 - (x >> 64));\\n }\\n }\\n\\n /// @notice Finds the zero-based index of the first one in the binary representation of x.\\n /// @dev See the note on msb in the \\\"Find First Set\\\" Wikipedia article https://en.wikipedia.org/wiki/Find_first_set\\n /// @param x The uint256 number for which to find the index of the most significant bit.\\n /// @return msb The index of the most significant bit as an uint256.\\n function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\\n if (x >= 2**128) {\\n x >>= 128;\\n msb += 128;\\n }\\n if (x >= 2**64) {\\n x >>= 64;\\n msb += 64;\\n }\\n if (x >= 2**32) {\\n x >>= 32;\\n msb += 32;\\n }\\n if (x >= 2**16) {\\n x >>= 16;\\n msb += 16;\\n }\\n if (x >= 2**8) {\\n x >>= 8;\\n msb += 8;\\n }\\n if (x >= 2**4) {\\n x >>= 4;\\n msb += 4;\\n }\\n if (x >= 2**2) {\\n x >>= 2;\\n msb += 2;\\n }\\n if (x >= 2**1) {\\n // No need to shift x any more.\\n msb += 1;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.\\n ///\\n /// Requirements:\\n /// - The denominator cannot be zero.\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The multiplicand as an uint256.\\n /// @param y The multiplier as an uint256.\\n /// @param denominator The divisor as an uint256.\\n /// @return result The result as an uint256.\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n unchecked {\\n result = prod0 / denominator;\\n }\\n return result;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n if (prod1 >= denominator) {\\n revert PRBMath__MulDivOverflow(prod1, denominator);\\n }\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n unchecked {\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 lpotdod = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by lpotdod.\\n denominator := div(denominator, lpotdod)\\n\\n // Divide [prod1 prod0] by lpotdod.\\n prod0 := div(prod0, lpotdod)\\n\\n // Flip lpotdod such that it is 2^256 / lpotdod. If lpotdod is zero, then it becomes one.\\n lpotdod := add(div(sub(0, lpotdod), lpotdod), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * lpotdod;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f71e18) with full precision.\\n ///\\n /// @dev Variant of \\\"mulDiv\\\" with constant folding, i.e. in which the denominator is always 1e18. Before returning the\\n /// final result, we add 1 if (x * y) % SCALE >= HALF_SCALE. Without this, 6.6e-19 would be truncated to 0 instead of\\n /// being rounded to 1e-18. See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717.\\n ///\\n /// Requirements:\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - The body is purposely left uncommented; see the NatSpec comments in \\\"PRBMath.mulDiv\\\" to understand how this works.\\n /// - It is assumed that the result can never be type(uint256).max when x and y solve the following two equations:\\n /// 1. x * y = type(uint256).max * SCALE\\n /// 2. (x * y) % SCALE >= SCALE / 2\\n ///\\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function mulDivFixedPoint(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n uint256 prod0;\\n uint256 prod1;\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n if (prod1 >= SCALE) {\\n revert PRBMath__MulDivFixedPointOverflow(prod1);\\n }\\n\\n uint256 remainder;\\n uint256 roundUpUnit;\\n assembly {\\n remainder := mulmod(x, y, SCALE)\\n roundUpUnit := gt(remainder, 499999999999999999)\\n }\\n\\n if (prod1 == 0) {\\n unchecked {\\n result = (prod0 / SCALE) + roundUpUnit;\\n return result;\\n }\\n }\\n\\n assembly {\\n result := add(\\n mul(\\n or(\\n div(sub(prod0, remainder), SCALE_LPOTD),\\n mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, SCALE_LPOTD), SCALE_LPOTD), 1))\\n ),\\n SCALE_INVERSE\\n ),\\n roundUpUnit\\n )\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev An extension of \\\"mulDiv\\\" for signed numbers. Works by computing the signs and the absolute values separately.\\n ///\\n /// Requirements:\\n /// - None of the inputs can be type(int256).min.\\n /// - The result must fit within int256.\\n ///\\n /// @param x The multiplicand as an int256.\\n /// @param y The multiplier as an int256.\\n /// @param denominator The divisor as an int256.\\n /// @return result The result as an int256.\\n function mulDivSigned(\\n int256 x,\\n int256 y,\\n int256 denominator\\n ) internal pure returns (int256 result) {\\n if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {\\n revert PRBMath__MulDivSignedInputTooSmall();\\n }\\n\\n // Get hold of the absolute values of x, y and the denominator.\\n uint256 ax;\\n uint256 ay;\\n uint256 ad;\\n unchecked {\\n ax = x < 0 ? uint256(-x) : uint256(x);\\n ay = y < 0 ? uint256(-y) : uint256(y);\\n ad = denominator < 0 ? uint256(-denominator) : uint256(denominator);\\n }\\n\\n // Compute the absolute value of (x*y)\\u00f7denominator. The result must fit within int256.\\n uint256 rAbs = mulDiv(ax, ay, ad);\\n if (rAbs > uint256(type(int256).max)) {\\n revert PRBMath__MulDivSignedOverflow(rAbs);\\n }\\n\\n // Get the signs of x, y and the denominator.\\n uint256 sx;\\n uint256 sy;\\n uint256 sd;\\n assembly {\\n sx := sgt(x, sub(0, 1))\\n sy := sgt(y, sub(0, 1))\\n sd := sgt(denominator, sub(0, 1))\\n }\\n\\n // XOR over sx, sy and sd. This is checking whether there are one or three negative signs in the inputs.\\n // If yes, the result should be negative.\\n result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs);\\n }\\n\\n /// @notice Calculates the square root of x, rounding down.\\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The uint256 number for which to calculate the square root.\\n /// @return result The result as an uint256.\\n function sqrt(uint256 x) internal pure returns (uint256 result) {\\n if (x == 0) {\\n return 0;\\n }\\n\\n // Set the initial guess to the closest power of two that is higher than x.\\n uint256 xAux = uint256(x);\\n result = 1;\\n if (xAux >= 0x100000000000000000000000000000000) {\\n xAux >>= 128;\\n result <<= 64;\\n }\\n if (xAux >= 0x10000000000000000) {\\n xAux >>= 64;\\n result <<= 32;\\n }\\n if (xAux >= 0x100000000) {\\n xAux >>= 32;\\n result <<= 16;\\n }\\n if (xAux >= 0x10000) {\\n xAux >>= 16;\\n result <<= 8;\\n }\\n if (xAux >= 0x100) {\\n xAux >>= 8;\\n result <<= 4;\\n }\\n if (xAux >= 0x10) {\\n xAux >>= 4;\\n result <<= 2;\\n }\\n if (xAux >= 0x8) {\\n result <<= 1;\\n }\\n\\n // The operations can never overflow because the result is max 2^127 when it enters this block.\\n unchecked {\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1; // Seven iterations should be enough\\n uint256 roundedDownResult = x / result;\\n return result >= roundedDownResult ? roundedDownResult : result;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x62cbabae4910e168e99b9c2c3e3b5c9c7ad5e7abd961dcc63b7ea3d83d8ea87e\",\"license\":\"Unlicense\"}},\"version\":1}", "bytecode": "0x60e06040523480156200001157600080fd5b5060405162003b6838038062003b68833981016040819052620000349162000070565b60016000556001600160a01b0392831660805290821660a0521660c052620000c4565b6001600160a01b03811681146200006d57600080fd5b50565b6000806000606084860312156200008657600080fd5b8351620000938162000057565b6020850151909350620000a68162000057565b6040850151909250620000b98162000057565b809150509250925092565b60805160a05160c0516139e862000180600039600081816102630152818161079101528181610e0b015281816126ac01526128bb01526000818161018b0152818161040e015281816109ca01528181610f580152818161113a015281816115ab015281816118a70152818161198901528181611dc201528181612201015261295b015260008181610229015281816104be0152818161139301528181611b8401528181611eb401528181612494015261274101526139e86000f3fe608060405234801561001057600080fd5b50600436106100ff5760003560e01c8063c294b2f411610097578063d49031c011610066578063d49031c014610285578063d4c3a8d214610298578063e7c8e3e3146102c9578063e8ba563a146102de57600080fd5b8063c294b2f414610211578063c41c2f2414610224578063c66445971461024b578063d3419bf31461025e57600080fd5b80636bb6a5ad116100d35780636bb6a5ad146101c5578063a2df1f95146101d8578063a57c7f59146101eb578063b753d7e9146101fe57600080fd5b8062fdd58e1461010457806325386715146101425780632fa1b39114610163578063557e715514610186575b600080fd5b61012f610112366004612b19565b600160209081526000928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b610155610150366004612b45565b61030f565b604051610139929190612b71565b610176610171366004612d68565b6108cd565b6040516101399493929190612e79565b6101ad7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610139565b61012f6101d3366004612f56565b610eb4565b6101766101e6366004612f6f565b61103d565b61012f6101f9366004613010565b611853565b61012f61020c366004612b45565b611936565b61012f61021f366004613042565b61194d565b6101ad7f000000000000000000000000000000000000000000000000000000000000000081565b610155610259366004612b45565b611cc8565b6101ad7f000000000000000000000000000000000000000000000000000000000000000081565b61012f610293366004612b19565b6121f8565b61012f6102a6366004613091565b600360209081526000938452604080852082529284528284209052825290205481565b6102dc6102d73660046130c6565b6122d6565b005b61012f6102ec366004613091565b600260209081526000938452604080852082529284528284209052825290205481565b6103676040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b60006002600054036103da576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b60026000556040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018690527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa15801561045e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061048291906130f8565b3360009081526003602090815260408083208984528252808320828501518452909152812054919350906104b79086906131a7565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635dd8f6aa896040518263ffffffff1660e01b815260040161050a91815260200190565b602060405180830381865afa158015610527573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061054b91906131ba565b6001600160a01b0316637a81b56289876020015133336001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561059e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105c291906131ba565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e087901b168152600481019490945260248401929092526001600160a01b0390811660448401521660648201526084016040805180830381865afa158015610633573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065791906131d7565b9150915081831180610667575081155b1561069e576040517fb6ecab1200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8086146106d7576040517fe56ea4e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000336001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610717573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061073b91906131fb565b905080871461080f5761080a886107546012600a613334565b6040517fa4d0caf2000000000000000000000000000000000000000000000000000000008152600481018b905260248101859052601260448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a4d0caf2906064015b602060405180830381865afa1580156107e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061080591906131fb565b61231f565b610811565b875b945061081f338a8884612423565b851115610858576040517f2fca7ece00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360008181526003602090815260408083208d845282528083208a83015184528252808320889055928252600181528282208c83529052205461089c908690613340565b3360009081526001602081815260408084209d84529c90529a81209190915598909855509296919550909350505050565b6109256040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b6000606080600260005403610996576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103d1565b60026000556040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018b90527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa158015610a1a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3e91906130f8565b8051909450600003610a7c576040517f2e96671a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61010084015160481c600190811603610ac1576040517fa3bb913300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61010084015160009060521c6001908116148015610af757506000610aeb86610100015160541c90565b6001600160a01b031614155b15610c49576000604051806101400160405280336001600160a01b031681526020018f6001600160a01b031681526020018e803603810190610b399190613353565b815260208082018f905288015160408201526001600160a01b038c16606082015260a080890151608083015261010089015191019060181c61ffff1681526020018a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050908252506020018890529050610bca86610100015160541c90565b6001600160a01b031663d46cf171826040518263ffffffff1660e01b8152600401610bf591906133c2565b6000604051808303816000875af1158015610c14573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610c3c9190810190613530565b955093509150610c8a9050565b8460a00151905087878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294505050505b825160208d01359015610d1f5760005b8451811015610d1d576000858281518110610cb757610cb7613621565b602002602001015160200151905080600014610d145782811115610d07576040517f6d51b52600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d118184613340565b92505b50600101610c9a565b505b8c60200135600003610d37575060009350610e9d9050565b8015610d9e573360009081526001602090815260408083208f8452909152902054610d639082906131a7565b60016000336001600160a01b03166001600160a01b0316815260200190815260200160002060008e8152602001908152602001600020819055505b5080600003610db1575060009250610e9d565b60408c0135600060608e01358c14610e7b576040517fa4d0caf200000000000000000000000000000000000000000000000000000000815260608f01356004820152602481018d9052604481018390526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a4d0caf290606401602060405180830381865afa158015610e52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7691906131fb565b610e86565b610e8682600a613334565b9050610e978e60200135848361231f565b95505050505b600160008190555098509850985098945050505050565b6000600260005403610f22576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103d1565b600260009081556040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa158015610fa8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fcc91906130f8565b610100810151909150604d1c600190811614611014576040517fe7c9e0be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505033600090815260016020818152604080842094845293905291812080549082905591905590565b6110956040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b6000606080600260005403611106576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103d1565b60026000556040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa15801561118a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ae91906130f8565b610100810151909450604a1c6001908116036111f6576040517fa97cf58f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61122a604051806080016040528060006001600160a01b031681526020016000815260200160008152602001600081525090565b6000806000336001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561126d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061129191906131ba565b90506000336001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f791906131fb565b90506000336001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611339573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061135d91906131fb565b6101008b015190915060511c6001908116146113845761137f338f8c84612423565b61138f565b61138f8e8383612705565b94507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635dd8f6aa8f6040518263ffffffff1660e01b81526004016113df91815260200190565b602060405180830381865afa1580156113fc573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061142091906131ba565b6001600160a01b031663b5f1e34d8f6114458d610100015161ffff60189190911c1690565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815260048101929092526024820152604401602060405180830381865afa15801561149e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114c291906131fb565b9350838d11156114fe576040517fb8af220000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8415611514576115118e8b8f8789612919565b98505b604080516080810182526001600160a01b03949094168452602084018a9052830191909152606082015261010088015190935060531c60019081161480156115745750600061156888610100015160541c90565b6001600160a01b031614155b15611764576040517fc55f571c000000000000000000000000000000000000000000000000000000008152600481018c90526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c55f571c90602401602060405180830381865afa1580156115fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061161e9190613650565b90506000604051806101800160405280336001600160a01b031681526020018f6001600160a01b031681526020018e81526020018a6020015181526020018d815260200184815260200185815260200186815260200161168b8b6101000151600160519190911c81161490565b1515815260200160008460028111156116a6576116a6613671565b146116b9576116b48b612a6a565b6116c2565b6116c28b612a87565b81526020018c81526020018b81525090506116e289610100015160541c90565b6001600160a01b031663a51cfd18826040518263ffffffff1660e01b815260040161170d91906136a0565b6000604051808303816000875af115801561172c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611754919081019061379b565b9199509097509550611768915050565b8893505b50508251849150156117c25760005b83518110156117c057600084828151811061179457611794613621565b6020026020010151602001519050806000146117b7576117b481846131a7565b92505b50600101611777565b505b3360009081526001602090815260408083208c8452909152902054811115611816576040517f2fca7ece00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b801561183e573360009081526001602090815260408083208c84529091529020805482900390555b50600160008190555095509550955095915050565b6000816000036118655750600061192e565b828411156118755750600061192e565b6040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018690526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa1580156118f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061191b91906130f8565b905061192a8682878787612919565b9150505b949350505050565b6000611943848484612705565b90505b9392505050565b6040517f43a266c20000000000000000000000000000000000000000000000000000000081526004810184905260009081906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906343a266c29060240161012060405180830381865afa1580156119d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119f591906130f8565b9050600083611a7057611a6b8787848a6001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a6691906131fb565b612423565b611b3d565b611b3d86886001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ab2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ad691906131fb565b896001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b3891906131fb565b612705565b905080600003611b525760009250505061192e565b6040517f5dd8f6aa000000000000000000000000000000000000000000000000000000008152600481018790526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635dd8f6aa90602401602060405180830381865afa158015611bd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bf791906131ba565b6001600160a01b031663b5f1e34d88611c1c86610100015161ffff60189190911c1690565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815260048101929092526024820152604401602060405180830381865afa158015611c75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c9991906131fb565b905080861115611caf576000935050505061192e565b611cbc8784888486612919565b98975050505050505050565b611d206040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b6000600260005403611d8e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103d1565b60026000556040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018690527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa158015611e12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3691906130f8565b61010081015190925060491c600190811603611e7e576040517f861e9dcd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152600260209081526040808320888452825280832085518452909152812054611ead9086906131a7565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635dd8f6aa896040518263ffffffff1660e01b8152600401611f0091815260200190565b602060405180830381865afa158015611f1d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f4191906131ba565b6001600160a01b031663e8db213089876020015133336001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f94573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fb891906131ba565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e087901b168152600481019490945260248401929092526001600160a01b0390811660448401521660648201526084016040805180830381865afa158015612029573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204d91906131d7565b915091508183118061205d575081155b15612094576040517f08dae4ac00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8086146120cd576040517fe56ea4e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000336001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561210d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061213191906131fb565b905080871461214f5761214a886107546012600a613334565b612151565b875b3360009081526001602090815260408083208d84529091529020549095508511156121a8576040517f2fca7ece00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50503360008181526002602090815260408083208b845282528083208851845282528083209590955591815260018083528482209982529890915291822080548490039055509490945593915050565b60006122cd83837f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166343a266c2866040518263ffffffff1660e01b815260040161224d91815260200190565b61012060405180830381865afa15801561226b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061228f91906130f8565b866001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a42573d6000803e3d6000fd5b90505b92915050565b3360009081526001602090815260408083208584529091529020546122fc9082906131a7565b336000908152600160209081526040808320958352949052929092209190915550565b600080807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff858709858702925082811083820303915050806000036123775783828161236d5761236d61387c565b0492505050611946565b8381106123ba576040517f773cc18c00000000000000000000000000000000000000000000000000000000815260048101829052602481018590526044016103d1565b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b6001600160a01b038416600090815260016020908152604080832086845290915281205480820361245857600091505061192e565b6040517f5dd8f6aa0000000000000000000000000000000000000000000000000000000081526004810186905260009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690635dd8f6aa90602401602060405180830381865afa1580156124db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124ff91906131ba565b6001600160a01b031663e8db21308888602001518b8c6001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612552573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061257691906131ba565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e087901b168152600481019490945260248401929092526001600160a01b0390811660448401521660648201526084016040805180830381865afa1580156125e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061260b91906131d7565b6001600160a01b038a1660009081526002602090815260408083208c845282528083208b518452909152812054929450909250906126499084613340565b9050801580159061265a5750858214155b156126e6576126e38161266f6012600a613334565b6040517fa4d0caf200000000000000000000000000000000000000000000000000000000815260048101869052602481018a9052601260448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a4d0caf2906064016107c4565b90505b8084116126f45760006126f8565b8084035b9998505050505050505050565b6040517fd17541530000000000000000000000000000000000000000000000000000000081526004810184905260009081906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063d175415390602401600060405180830381865afa158015612788573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526127b091908101906138ab565b90506000805b825181101561285b578281815181106127d1576127d1613621565b60200260200101516001600160a01b031663a32e1e96886040518263ffffffff1660e01b815260040161280691815260200190565b602060405180830381865afa158015612823573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061284791906131fb565b61285190836131a7565b91506001016127b6565b506000600185146128ef576040517fa4d0caf20000000000000000000000000000000000000000000000000000000081526001600482015260248101869052601260448201526128ea908390670de0b6b3a7640000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a4d0caf2906064016107c4565b6128f1565b815b90508560121461290c5761290781601288612aa4565b61290e565b805b979650505050505050565b6000828403612929575080612a61565b6000806040517fc55f571c000000000000000000000000000000000000000000000000000000008152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c55f571c90602401602060405180830381865afa1580156129aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129ce9190613650565b60028111156129df576129df613671565b146129f2576129ed86612a6a565b6129fb565b6129fb86612a87565b905080600003612a0f576000915050612a61565b6000612a1c84878761231f565b90506127108203612a30579150612a619050565b612a5c81612a4a88612a4486612710613340565b8961231f565b612a5490856131a7565b61271061231f565b925050505b95945050505050565b60006028826101000151901c61ffff166127106122d09190613340565b60006038826101000151901c61ffff166127106122d09190613340565b6000828203612ab4575082611946565b82821115612ae257612ac68383613340565b612ad190600a613334565b612adb908561393a565b9050611946565b612aec8284613340565b612af790600a613334565b612adb9085613977565b6001600160a01b0381168114612b1657600080fd5b50565b60008060408385031215612b2c57600080fd5b8235612b3781612b01565b946020939093013593505050565b600080600060608486031215612b5a57600080fd5b505081359360208301359350604090920135919050565b6101408101612bde8285805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c08301526001600160a01b0360e08201511660e08301526101008082015181840152505050565b826101208301529392505050565b60008083601f840112612bfe57600080fd5b50813567ffffffffffffffff811115612c1657600080fd5b602083019150836020828501011115612c2e57600080fd5b9250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff81118282101715612c8857612c88612c35565b60405290565b6040805190810167ffffffffffffffff81118282101715612c8857612c88612c35565b604051601f8201601f1916810167ffffffffffffffff81118282101715612cda57612cda612c35565b604052919050565b600067ffffffffffffffff821115612cfc57612cfc612c35565b50601f01601f191660200190565b6000612d1d612d1884612ce2565b612cb1565b9050828152838383011115612d3157600080fd5b828260208301376000602084830101529392505050565b600082601f830112612d5957600080fd5b6122cd83833560208501612d0a565b600080600080600080600080888a03610140811215612d8657600080fd5b8935612d9181612b01565b98506080601f1982011215612da557600080fd5b5060208901965060a0890135955060c0890135945060e0890135612dc881612b01565b935061010089013567ffffffffffffffff80821115612de657600080fd5b612df28c838d01612bec565b90955093506101208b0135915080821115612e0c57600080fd5b50612e198b828c01612d48565b9150509295985092959890939650565b60005b83811015612e44578181015183820152602001612e2c565b50506000910152565b60008151808452612e65816020860160208601612e29565b601f01601f19169290920160200192915050565b6000610180808301612ee98489805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c08301526001600160a01b0360e08201511660e08301526101008082015181840152505050565b61012084018790526101408401919091528451908190526101a083019060209081870160005b82811015612f3f57815180516001600160a01b031686528401518486015260409094019390830190600101612f0f565b5050505082810361016084015261290e8185612e4d565b600060208284031215612f6857600080fd5b5035919050565b600080600080600060a08688031215612f8757600080fd5b8535612f9281612b01565b94506020860135935060408601359250606086013567ffffffffffffffff80821115612fbd57600080fd5b818801915088601f830112612fd157600080fd5b612fe089833560208501612d0a565b93506080880135915080821115612ff657600080fd5b5061300388828901612d48565b9150509295509295909350565b6000806000806080858703121561302657600080fd5b5050823594602084013594506040840135936060013592509050565b6000806000806080858703121561305857600080fd5b843561306381612b01565b935060208501359250604085013591506060850135801515811461308657600080fd5b939692955090935050565b6000806000606084860312156130a657600080fd5b83356130b181612b01565b95602085013595506040909401359392505050565b600080604083850312156130d957600080fd5b50508035926020909101359150565b80516130f381612b01565b919050565b6000610120828403121561310b57600080fd5b613113612c64565b825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015261315f60e084016130e8565b60e0820152610100928301519281019290925250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156122d0576122d0613178565b6000602082840312156131cc57600080fd5b815161194681612b01565b600080604083850312156131ea57600080fd5b505080516020909101519092909150565b60006020828403121561320d57600080fd5b5051919050565b600181815b8085111561326d57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561325357613253613178565b8085161561326057918102915b93841c9390800290613219565b509250929050565b600082613284575060016122d0565b81613291575060006122d0565b81600181146132a757600281146132b1576132cd565b60019150506122d0565b60ff8411156132c2576132c2613178565b50506001821b6122d0565b5060208310610133831016604e8410600b84101617156132f0575081810a6122d0565b6132fa8383613214565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561332c5761332c613178565b029392505050565b60006122cd8383613275565b818103818111156122d0576122d0613178565b60006080828403121561336557600080fd5b6040516080810181811067ffffffffffffffff8211171561338857613388612c35565b604052823561339681612b01565b808252506020830135602082015260408301356040820152606083013560608201528091505092915050565b602081526133dc6020820183516001600160a01b03169052565b600060208301516133f860408401826001600160a01b03169052565b50604083015161343560608401826001600160a01b0381511682526020810151602083015260408101516040830152606081015160608301525050565b50606083015160e08301526080830151610100818185015260a0850151915061012061346b818601846001600160a01b03169052565b60c086015161014086015260e08601516101608601528186015192506101a09150816101808601526134a16101c0860184612e4d565b90860151858203601f1901838701529092506134bd8382612e4d565b9695505050505050565b600082601f8301126134d857600080fd5b81516134e6612d1882612ce2565b8181528460208386010111156134fb57600080fd5b61192e826020830160208701612e29565b600067ffffffffffffffff82111561352657613526612c35565b5060051b60200190565b60008060006060848603121561354557600080fd5b8351925060208085015167ffffffffffffffff8082111561356557600080fd5b613571888389016134c7565b945060409150818701518181111561358857600080fd5b87019050601f8101881361359b57600080fd5b80516135a9612d188261350c565b81815260069190911b8201840190848101908a8311156135c857600080fd5b928501925b828410156136115784848c0312156135e55760008081fd5b6135ed612c8e565b84516135f881612b01565b81528487015187820152825292840192908501906135cd565b8096505050505050509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561366257600080fd5b81516003811061194657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b602081526136ba6020820183516001600160a01b03169052565b600060208301516136d660408401826001600160a01b03169052565b506040830151606083015260608301516080830152608083015160a083015260a083015160c083015260c083015160e083015260e0830151610100613747818501836001600160a01b0381511682526020810151602083015260408101516040830152606081015160608301525050565b8401511515610180840152506101208301516101a08301526101408301516101e06101c0840181905261377e610200850183612e4d565b9150610160850151601f1985840301828601526134bd8382612e4d565b6000806000606084860312156137b057600080fd5b8351925060208085015167ffffffffffffffff808211156137d057600080fd5b6137dc888389016134c7565b94506040915081870151818111156137f357600080fd5b87019050601f8101881361380657600080fd5b8051613814612d188261350c565b81815260069190911b8201840190848101908a83111561383357600080fd5b928501925b828410156136115784848c0312156138505760008081fd5b613858612c8e565b845161386381612b01565b8152848701518782015282529284019290850190613838565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600060208083850312156138be57600080fd5b825167ffffffffffffffff8111156138d557600080fd5b8301601f810185136138e657600080fd5b80516138f4612d188261350c565b81815260059190911b8201830190838101908783111561391357600080fd5b928401925b8284101561290e57835161392b81612b01565b82529284019290840190613918565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561397257613972613178565b500290565b6000826139ad577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b50049056fea2646970667358221220496c9f50e79f6514ca61a35b21fe271a2d4fe217f051df7336af8ae92911191e64736f6c63430008100033", "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100ff5760003560e01c8063c294b2f411610097578063d49031c011610066578063d49031c014610285578063d4c3a8d214610298578063e7c8e3e3146102c9578063e8ba563a146102de57600080fd5b8063c294b2f414610211578063c41c2f2414610224578063c66445971461024b578063d3419bf31461025e57600080fd5b80636bb6a5ad116100d35780636bb6a5ad146101c5578063a2df1f95146101d8578063a57c7f59146101eb578063b753d7e9146101fe57600080fd5b8062fdd58e1461010457806325386715146101425780632fa1b39114610163578063557e715514610186575b600080fd5b61012f610112366004612b19565b600160209081526000928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b610155610150366004612b45565b61030f565b604051610139929190612b71565b610176610171366004612d68565b6108cd565b6040516101399493929190612e79565b6101ad7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610139565b61012f6101d3366004612f56565b610eb4565b6101766101e6366004612f6f565b61103d565b61012f6101f9366004613010565b611853565b61012f61020c366004612b45565b611936565b61012f61021f366004613042565b61194d565b6101ad7f000000000000000000000000000000000000000000000000000000000000000081565b610155610259366004612b45565b611cc8565b6101ad7f000000000000000000000000000000000000000000000000000000000000000081565b61012f610293366004612b19565b6121f8565b61012f6102a6366004613091565b600360209081526000938452604080852082529284528284209052825290205481565b6102dc6102d73660046130c6565b6122d6565b005b61012f6102ec366004613091565b600260209081526000938452604080852082529284528284209052825290205481565b6103676040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b60006002600054036103da576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064015b60405180910390fd5b60026000556040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018690527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa15801561045e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061048291906130f8565b3360009081526003602090815260408083208984528252808320828501518452909152812054919350906104b79086906131a7565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635dd8f6aa896040518263ffffffff1660e01b815260040161050a91815260200190565b602060405180830381865afa158015610527573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061054b91906131ba565b6001600160a01b0316637a81b56289876020015133336001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561059e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105c291906131ba565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e087901b168152600481019490945260248401929092526001600160a01b0390811660448401521660648201526084016040805180830381865afa158015610633573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061065791906131d7565b9150915081831180610667575081155b1561069e576040517fb6ecab1200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8086146106d7576040517fe56ea4e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000336001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610717573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061073b91906131fb565b905080871461080f5761080a886107546012600a613334565b6040517fa4d0caf2000000000000000000000000000000000000000000000000000000008152600481018b905260248101859052601260448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a4d0caf2906064015b602060405180830381865afa1580156107e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061080591906131fb565b61231f565b610811565b875b945061081f338a8884612423565b851115610858576040517f2fca7ece00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3360008181526003602090815260408083208d845282528083208a83015184528252808320889055928252600181528282208c83529052205461089c908690613340565b3360009081526001602081815260408084209d84529c90529a81209190915598909855509296919550909350505050565b6109256040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b6000606080600260005403610996576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103d1565b60026000556040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018b90527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa158015610a1a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a3e91906130f8565b8051909450600003610a7c576040517f2e96671a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61010084015160481c600190811603610ac1576040517fa3bb913300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61010084015160009060521c6001908116148015610af757506000610aeb86610100015160541c90565b6001600160a01b031614155b15610c49576000604051806101400160405280336001600160a01b031681526020018f6001600160a01b031681526020018e803603810190610b399190613353565b815260208082018f905288015160408201526001600160a01b038c16606082015260a080890151608083015261010089015191019060181c61ffff1681526020018a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050908252506020018890529050610bca86610100015160541c90565b6001600160a01b031663d46cf171826040518263ffffffff1660e01b8152600401610bf591906133c2565b6000604051808303816000875af1158015610c14573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610c3c9190810190613530565b955093509150610c8a9050565b8460a00151905087878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294505050505b825160208d01359015610d1f5760005b8451811015610d1d576000858281518110610cb757610cb7613621565b602002602001015160200151905080600014610d145782811115610d07576040517f6d51b52600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610d118184613340565b92505b50600101610c9a565b505b8c60200135600003610d37575060009350610e9d9050565b8015610d9e573360009081526001602090815260408083208f8452909152902054610d639082906131a7565b60016000336001600160a01b03166001600160a01b0316815260200190815260200160002060008e8152602001908152602001600020819055505b5080600003610db1575060009250610e9d565b60408c0135600060608e01358c14610e7b576040517fa4d0caf200000000000000000000000000000000000000000000000000000000815260608f01356004820152602481018d9052604481018390526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a4d0caf290606401602060405180830381865afa158015610e52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7691906131fb565b610e86565b610e8682600a613334565b9050610e978e60200135848361231f565b95505050505b600160008190555098509850985098945050505050565b6000600260005403610f22576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103d1565b600260009081556040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa158015610fa8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fcc91906130f8565b610100810151909150604d1c600190811614611014576040517fe7c9e0be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505033600090815260016020818152604080842094845293905291812080549082905591905590565b6110956040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b6000606080600260005403611106576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103d1565b60026000556040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa15801561118a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ae91906130f8565b610100810151909450604a1c6001908116036111f6576040517fa97cf58f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61122a604051806080016040528060006001600160a01b031681526020016000815260200160008152602001600081525090565b6000806000336001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561126d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061129191906131ba565b90506000336001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f791906131fb565b90506000336001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611339573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061135d91906131fb565b6101008b015190915060511c6001908116146113845761137f338f8c84612423565b61138f565b61138f8e8383612705565b94507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635dd8f6aa8f6040518263ffffffff1660e01b81526004016113df91815260200190565b602060405180830381865afa1580156113fc573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061142091906131ba565b6001600160a01b031663b5f1e34d8f6114458d610100015161ffff60189190911c1690565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815260048101929092526024820152604401602060405180830381865afa15801561149e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114c291906131fb565b9350838d11156114fe576040517fb8af220000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8415611514576115118e8b8f8789612919565b98505b604080516080810182526001600160a01b03949094168452602084018a9052830191909152606082015261010088015190935060531c60019081161480156115745750600061156888610100015160541c90565b6001600160a01b031614155b15611764576040517fc55f571c000000000000000000000000000000000000000000000000000000008152600481018c90526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c55f571c90602401602060405180830381865afa1580156115fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061161e9190613650565b90506000604051806101800160405280336001600160a01b031681526020018f6001600160a01b031681526020018e81526020018a6020015181526020018d815260200184815260200185815260200186815260200161168b8b6101000151600160519190911c81161490565b1515815260200160008460028111156116a6576116a6613671565b146116b9576116b48b612a6a565b6116c2565b6116c28b612a87565b81526020018c81526020018b81525090506116e289610100015160541c90565b6001600160a01b031663a51cfd18826040518263ffffffff1660e01b815260040161170d91906136a0565b6000604051808303816000875af115801561172c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611754919081019061379b565b9199509097509550611768915050565b8893505b50508251849150156117c25760005b83518110156117c057600084828151811061179457611794613621565b6020026020010151602001519050806000146117b7576117b481846131a7565b92505b50600101611777565b505b3360009081526001602090815260408083208c8452909152902054811115611816576040517f2fca7ece00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b801561183e573360009081526001602090815260408083208c84529091529020805482900390555b50600160008190555095509550955095915050565b6000816000036118655750600061192e565b828411156118755750600061192e565b6040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018690526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa1580156118f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061191b91906130f8565b905061192a8682878787612919565b9150505b949350505050565b6000611943848484612705565b90505b9392505050565b6040517f43a266c20000000000000000000000000000000000000000000000000000000081526004810184905260009081906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906343a266c29060240161012060405180830381865afa1580156119d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119f591906130f8565b9050600083611a7057611a6b8787848a6001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a6691906131fb565b612423565b611b3d565b611b3d86886001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ab2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ad691906131fb565b896001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b3891906131fb565b612705565b905080600003611b525760009250505061192e565b6040517f5dd8f6aa000000000000000000000000000000000000000000000000000000008152600481018790526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635dd8f6aa90602401602060405180830381865afa158015611bd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bf791906131ba565b6001600160a01b031663b5f1e34d88611c1c86610100015161ffff60189190911c1690565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815260048101929092526024820152604401602060405180830381865afa158015611c75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c9991906131fb565b905080861115611caf576000935050505061192e565b611cbc8784888486612919565b98975050505050505050565b611d206040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b6000600260005403611d8e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016103d1565b60026000556040517f43a266c2000000000000000000000000000000000000000000000000000000008152600481018690527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa158015611e12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3691906130f8565b61010081015190925060491c600190811603611e7e576040517f861e9dcd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152600260209081526040808320888452825280832085518452909152812054611ead9086906131a7565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635dd8f6aa896040518263ffffffff1660e01b8152600401611f0091815260200190565b602060405180830381865afa158015611f1d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f4191906131ba565b6001600160a01b031663e8db213089876020015133336001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f94573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fb891906131ba565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e087901b168152600481019490945260248401929092526001600160a01b0390811660448401521660648201526084016040805180830381865afa158015612029573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204d91906131d7565b915091508183118061205d575081155b15612094576040517f08dae4ac00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8086146120cd576040517fe56ea4e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000336001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561210d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061213191906131fb565b905080871461214f5761214a886107546012600a613334565b612151565b875b3360009081526001602090815260408083208d84529091529020549095508511156121a8576040517f2fca7ece00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50503360008181526002602090815260408083208b845282528083208851845282528083209590955591815260018083528482209982529890915291822080548490039055509490945593915050565b60006122cd83837f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166343a266c2866040518263ffffffff1660e01b815260040161224d91815260200190565b61012060405180830381865afa15801561226b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061228f91906130f8565b866001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a42573d6000803e3d6000fd5b90505b92915050565b3360009081526001602090815260408083208584529091529020546122fc9082906131a7565b336000908152600160209081526040808320958352949052929092209190915550565b600080807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff858709858702925082811083820303915050806000036123775783828161236d5761236d61387c565b0492505050611946565b8381106123ba576040517f773cc18c00000000000000000000000000000000000000000000000000000000815260048101829052602481018590526044016103d1565b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b6001600160a01b038416600090815260016020908152604080832086845290915281205480820361245857600091505061192e565b6040517f5dd8f6aa0000000000000000000000000000000000000000000000000000000081526004810186905260009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690635dd8f6aa90602401602060405180830381865afa1580156124db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124ff91906131ba565b6001600160a01b031663e8db21308888602001518b8c6001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612552573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061257691906131ba565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e087901b168152600481019490945260248401929092526001600160a01b0390811660448401521660648201526084016040805180830381865afa1580156125e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061260b91906131d7565b6001600160a01b038a1660009081526002602090815260408083208c845282528083208b518452909152812054929450909250906126499084613340565b9050801580159061265a5750858214155b156126e6576126e38161266f6012600a613334565b6040517fa4d0caf200000000000000000000000000000000000000000000000000000000815260048101869052602481018a9052601260448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a4d0caf2906064016107c4565b90505b8084116126f45760006126f8565b8084035b9998505050505050505050565b6040517fd17541530000000000000000000000000000000000000000000000000000000081526004810184905260009081906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063d175415390602401600060405180830381865afa158015612788573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526127b091908101906138ab565b90506000805b825181101561285b578281815181106127d1576127d1613621565b60200260200101516001600160a01b031663a32e1e96886040518263ffffffff1660e01b815260040161280691815260200190565b602060405180830381865afa158015612823573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061284791906131fb565b61285190836131a7565b91506001016127b6565b506000600185146128ef576040517fa4d0caf20000000000000000000000000000000000000000000000000000000081526001600482015260248101869052601260448201526128ea908390670de0b6b3a7640000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a4d0caf2906064016107c4565b6128f1565b815b90508560121461290c5761290781601288612aa4565b61290e565b805b979650505050505050565b6000828403612929575080612a61565b6000806040517fc55f571c000000000000000000000000000000000000000000000000000000008152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c55f571c90602401602060405180830381865afa1580156129aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129ce9190613650565b60028111156129df576129df613671565b146129f2576129ed86612a6a565b6129fb565b6129fb86612a87565b905080600003612a0f576000915050612a61565b6000612a1c84878761231f565b90506127108203612a30579150612a619050565b612a5c81612a4a88612a4486612710613340565b8961231f565b612a5490856131a7565b61271061231f565b925050505b95945050505050565b60006028826101000151901c61ffff166127106122d09190613340565b60006038826101000151901c61ffff166127106122d09190613340565b6000828203612ab4575082611946565b82821115612ae257612ac68383613340565b612ad190600a613334565b612adb908561393a565b9050611946565b612aec8284613340565b612af790600a613334565b612adb9085613977565b6001600160a01b0381168114612b1657600080fd5b50565b60008060408385031215612b2c57600080fd5b8235612b3781612b01565b946020939093013593505050565b600080600060608486031215612b5a57600080fd5b505081359360208301359350604090920135919050565b6101408101612bde8285805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c08301526001600160a01b0360e08201511660e08301526101008082015181840152505050565b826101208301529392505050565b60008083601f840112612bfe57600080fd5b50813567ffffffffffffffff811115612c1657600080fd5b602083019150836020828501011115612c2e57600080fd5b9250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff81118282101715612c8857612c88612c35565b60405290565b6040805190810167ffffffffffffffff81118282101715612c8857612c88612c35565b604051601f8201601f1916810167ffffffffffffffff81118282101715612cda57612cda612c35565b604052919050565b600067ffffffffffffffff821115612cfc57612cfc612c35565b50601f01601f191660200190565b6000612d1d612d1884612ce2565b612cb1565b9050828152838383011115612d3157600080fd5b828260208301376000602084830101529392505050565b600082601f830112612d5957600080fd5b6122cd83833560208501612d0a565b600080600080600080600080888a03610140811215612d8657600080fd5b8935612d9181612b01565b98506080601f1982011215612da557600080fd5b5060208901965060a0890135955060c0890135945060e0890135612dc881612b01565b935061010089013567ffffffffffffffff80821115612de657600080fd5b612df28c838d01612bec565b90955093506101208b0135915080821115612e0c57600080fd5b50612e198b828c01612d48565b9150509295985092959890939650565b60005b83811015612e44578181015183820152602001612e2c565b50506000910152565b60008151808452612e65816020860160208601612e29565b601f01601f19169290920160200192915050565b6000610180808301612ee98489805182526020810151602083015260408101516040830152606081015160608301526080810151608083015260a081015160a083015260c081015160c08301526001600160a01b0360e08201511660e08301526101008082015181840152505050565b61012084018790526101408401919091528451908190526101a083019060209081870160005b82811015612f3f57815180516001600160a01b031686528401518486015260409094019390830190600101612f0f565b5050505082810361016084015261290e8185612e4d565b600060208284031215612f6857600080fd5b5035919050565b600080600080600060a08688031215612f8757600080fd5b8535612f9281612b01565b94506020860135935060408601359250606086013567ffffffffffffffff80821115612fbd57600080fd5b818801915088601f830112612fd157600080fd5b612fe089833560208501612d0a565b93506080880135915080821115612ff657600080fd5b5061300388828901612d48565b9150509295509295909350565b6000806000806080858703121561302657600080fd5b5050823594602084013594506040840135936060013592509050565b6000806000806080858703121561305857600080fd5b843561306381612b01565b935060208501359250604085013591506060850135801515811461308657600080fd5b939692955090935050565b6000806000606084860312156130a657600080fd5b83356130b181612b01565b95602085013595506040909401359392505050565b600080604083850312156130d957600080fd5b50508035926020909101359150565b80516130f381612b01565b919050565b6000610120828403121561310b57600080fd5b613113612c64565b825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015261315f60e084016130e8565b60e0820152610100928301519281019290925250919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156122d0576122d0613178565b6000602082840312156131cc57600080fd5b815161194681612b01565b600080604083850312156131ea57600080fd5b505080516020909101519092909150565b60006020828403121561320d57600080fd5b5051919050565b600181815b8085111561326d57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561325357613253613178565b8085161561326057918102915b93841c9390800290613219565b509250929050565b600082613284575060016122d0565b81613291575060006122d0565b81600181146132a757600281146132b1576132cd565b60019150506122d0565b60ff8411156132c2576132c2613178565b50506001821b6122d0565b5060208310610133831016604e8410600b84101617156132f0575081810a6122d0565b6132fa8383613214565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561332c5761332c613178565b029392505050565b60006122cd8383613275565b818103818111156122d0576122d0613178565b60006080828403121561336557600080fd5b6040516080810181811067ffffffffffffffff8211171561338857613388612c35565b604052823561339681612b01565b808252506020830135602082015260408301356040820152606083013560608201528091505092915050565b602081526133dc6020820183516001600160a01b03169052565b600060208301516133f860408401826001600160a01b03169052565b50604083015161343560608401826001600160a01b0381511682526020810151602083015260408101516040830152606081015160608301525050565b50606083015160e08301526080830151610100818185015260a0850151915061012061346b818601846001600160a01b03169052565b60c086015161014086015260e08601516101608601528186015192506101a09150816101808601526134a16101c0860184612e4d565b90860151858203601f1901838701529092506134bd8382612e4d565b9695505050505050565b600082601f8301126134d857600080fd5b81516134e6612d1882612ce2565b8181528460208386010111156134fb57600080fd5b61192e826020830160208701612e29565b600067ffffffffffffffff82111561352657613526612c35565b5060051b60200190565b60008060006060848603121561354557600080fd5b8351925060208085015167ffffffffffffffff8082111561356557600080fd5b613571888389016134c7565b945060409150818701518181111561358857600080fd5b87019050601f8101881361359b57600080fd5b80516135a9612d188261350c565b81815260069190911b8201840190848101908a8311156135c857600080fd5b928501925b828410156136115784848c0312156135e55760008081fd5b6135ed612c8e565b84516135f881612b01565b81528487015187820152825292840192908501906135cd565b8096505050505050509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561366257600080fd5b81516003811061194657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b602081526136ba6020820183516001600160a01b03169052565b600060208301516136d660408401826001600160a01b03169052565b506040830151606083015260608301516080830152608083015160a083015260a083015160c083015260c083015160e083015260e0830151610100613747818501836001600160a01b0381511682526020810151602083015260408101516040830152606081015160608301525050565b8401511515610180840152506101208301516101a08301526101408301516101e06101c0840181905261377e610200850183612e4d565b9150610160850151601f1985840301828601526134bd8382612e4d565b6000806000606084860312156137b057600080fd5b8351925060208085015167ffffffffffffffff808211156137d057600080fd5b6137dc888389016134c7565b94506040915081870151818111156137f357600080fd5b87019050601f8101881361380657600080fd5b8051613814612d188261350c565b81815260069190911b8201840190848101908a83111561383357600080fd5b928501925b828410156136115784848c0312156138505760008081fd5b613858612c8e565b845161386381612b01565b8152848701518782015282529284019290850190613838565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600060208083850312156138be57600080fd5b825167ffffffffffffffff8111156138d557600080fd5b8301601f810185136138e657600080fd5b80516138f4612d188261350c565b81815260059190911b8201830190838101908783111561391357600080fd5b928401925b8284101561290e57835161392b81612b01565b82529284019290840190613918565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561397257613972613178565b500290565b6000826139ad577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b50049056fea2646970667358221220496c9f50e79f6514ca61a35b21fe271a2d4fe217f051df7336af8ae92911191e64736f6c63430008100033", "devdoc": { diff --git a/deployments/mainnet/JBSingleTokenPaymentTerminalStore3_1.json b/deployments/mainnet/JBSingleTokenPaymentTerminalStore3_1.json index 676aae578..053878adb 100644 --- a/deployments/mainnet/JBSingleTokenPaymentTerminalStore3_1.json +++ b/deployments/mainnet/JBSingleTokenPaymentTerminalStore3_1.json @@ -816,7 +816,7 @@ ], "numDeployments": 1, "solcInputHash": "60cd95dca5edde649565e9f7f43720b6", - "metadata": "{\"compiler\":{\"version\":\"0.8.16+commit.07a7930e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IJBDirectory\",\"name\":\"_directory\",\"type\":\"address\"},{\"internalType\":\"contract IJBFundingCycleStore\",\"name\":\"_fundingCycleStore\",\"type\":\"address\"},{\"internalType\":\"contract IJBPrices\",\"name\":\"_prices\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CURRENCY_MISMATCH\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DISTRIBUTION_AMOUNT_LIMIT_REACHED\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FUNDING_CYCLE_DISTRIBUTION_PAUSED\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FUNDING_CYCLE_PAYMENT_PAUSED\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FUNDING_CYCLE_REDEEM_PAUSED\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INADEQUATE_CONTROLLER_ALLOWANCE\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INSUFFICIENT_TOKENS\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INVALID_AMOUNT_TO_SEND_DELEGATE\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INVALID_FUNDING_CYCLE\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"prod1\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"denominator\",\"type\":\"uint256\"}],\"name\":\"PRBMath__MulDivOverflow\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminal\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminal\",\"name\":\"_terminal\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"}],\"name\":\"currentOverflowOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_tokenCount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_overflow\",\"type\":\"uint256\"}],\"name\":\"currentReclaimableOverflowOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminal\",\"name\":\"_terminal\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_tokenCount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"_useTotalOverflow\",\"type\":\"bool\"}],\"name\":\"currentReclaimableOverflowOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_decimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_currency\",\"type\":\"uint256\"}],\"name\":\"currentTotalOverflowOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"directory\",\"outputs\":[{\"internalType\":\"contract IJBDirectory\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fundingCycleStore\",\"outputs\":[{\"internalType\":\"contract IJBFundingCycleStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"prices\",\"outputs\":[{\"internalType\":\"contract IJBPrices\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"recordAddedBalanceFor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_currency\",\"type\":\"uint256\"}],\"name\":\"recordDistributionFor\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"configuration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"basedOn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"discountRate\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBFundingCycleBallot\",\"name\":\"ballot\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"metadata\",\"type\":\"uint256\"}],\"internalType\":\"struct JBFundingCycle\",\"name\":\"fundingCycle\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"distributedAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"}],\"name\":\"recordMigration\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_payer\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"decimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"currency\",\"type\":\"uint256\"}],\"internalType\":\"struct JBTokenAmount\",\"name\":\"_amount\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_baseWeightCurrency\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"recordPaymentFrom\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"configuration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"basedOn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"discountRate\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBFundingCycleBallot\",\"name\":\"ballot\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"metadata\",\"type\":\"uint256\"}],\"internalType\":\"struct JBFundingCycle\",\"name\":\"fundingCycle\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"tokenCount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"contract IJBPayDelegate\",\"name\":\"delegate\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"struct JBPayDelegateAllocation[]\",\"name\":\"delegateAllocations\",\"type\":\"tuple[]\"},{\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_holder\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_tokenCount\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"recordRedemptionFor\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"configuration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"basedOn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"discountRate\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBFundingCycleBallot\",\"name\":\"ballot\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"metadata\",\"type\":\"uint256\"}],\"internalType\":\"struct JBFundingCycle\",\"name\":\"fundingCycle\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"reclaimAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"contract IJBRedemptionDelegate\",\"name\":\"delegate\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"struct JBRedemptionDelegateAllocation[]\",\"name\":\"delegateAllocations\",\"type\":\"tuple[]\"},{\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_currency\",\"type\":\"uint256\"}],\"name\":\"recordUsedAllowanceOf\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"configuration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"basedOn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"discountRate\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBFundingCycleBallot\",\"name\":\"ballot\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"metadata\",\"type\":\"uint256\"}],\"internalType\":\"struct JBFundingCycle\",\"name\":\"fundingCycle\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"usedAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminal\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"usedDistributionLimitOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminal\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"usedOverflowAllowanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Adheres to: IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.Inherits from - ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.This Store expects a project's controller to be an IJBController3_1. This is the only difference between this version and the original.\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_directory\":\"A contract storing directories of terminals and controllers for each project.\",\"_fundingCycleStore\":\"A contract storing all funding cycle configurations.\",\"_prices\":\"A contract that exposes price feeds.\"}},\"currentOverflowOf(address,uint256)\":{\"details\":\"The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\",\"params\":{\"_projectId\":\"The ID of the project to get overflow for.\",\"_terminal\":\"The terminal for which the overflow is being calculated.\"},\"returns\":{\"_0\":\"The current amount of overflow that project has in the specified terminal.\"}},\"currentReclaimableOverflowOf(address,uint256,uint256,bool)\":{\"details\":\" If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.The current reclaimable overflow is returned in terms of the specified terminal's currency.The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\",\"params\":{\"_projectId\":\"The ID of the project to get the reclaimable overflow amount for.\",\"_terminal\":\"The terminal from which the reclaimable amount would come.\",\"_tokenCount\":\"The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\",\"_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`.\"},\"returns\":{\"_0\":\"The amount of overflowed tokens that can be reclaimed, as a fixed point number with the same number of decimals as the provided `_terminal`.\"}},\"currentReclaimableOverflowOf(uint256,uint256,uint256,uint256)\":{\"details\":\" If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\",\"params\":{\"_overflow\":\"The amount of overflow to make the calculation with, as a fixed point number.\",\"_projectId\":\"The ID of the project to get the reclaimable overflow amount for.\",\"_tokenCount\":\"The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\",\"_totalSupply\":\"The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\"},\"returns\":{\"_0\":\"The amount of overflowed tokens that can be reclaimed, as a fixed point number with the same number of decimals as the provided `_overflow`.\"}},\"currentTotalOverflowOf(uint256,uint256,uint256)\":{\"params\":{\"_currency\":\"The currency that the total overflow should be in terms of.\",\"_decimals\":\"The number of decimals that the fixed point overflow should include.\",\"_projectId\":\"The ID of the project to get total overflow for.\"},\"returns\":{\"_0\":\"The current total amount of overflow that project has across all terminals.\"}},\"recordAddedBalanceFor(uint256,uint256)\":{\"details\":\"The msg.sender must be an IJBSingleTokenPaymentTerminal. \",\"params\":{\"_amount\":\"The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\",\"_projectId\":\"The ID of the project to which the funds being added belong.\"}},\"recordDistributionFor(uint256,uint256,uint256)\":{\"details\":\"The msg.sender must be an IJBSingleTokenPaymentTerminal. \",\"params\":{\"_amount\":\"The amount to use from the distribution limit, as a fixed point number.\",\"_currency\":\"The currency of the `_amount`. This must match the project's current funding cycle's currency.\",\"_projectId\":\"The ID of the project that is having funds distributed.\"},\"returns\":{\"distributedAmount\":\"The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\",\"fundingCycle\":\"The funding cycle during which the distribution was made.\"}},\"recordMigration(uint256)\":{\"details\":\"The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\",\"params\":{\"_projectId\":\"The ID of the project being migrated.\"},\"returns\":{\"balance\":\"The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\"}},\"recordPaymentFrom(address,(address,uint256,uint256,uint256),uint256,uint256,address,string,bytes)\":{\"details\":\"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.The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\",\"params\":{\"_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.\",\"_baseWeightCurrency\":\"The currency to base token issuance on.\",\"_beneficiary\":\"The specified address that should be the beneficiary of anything that results from the payment.\",\"_memo\":\"A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\",\"_metadata\":\"Bytes to send along to the data source, if one is provided.\",\"_payer\":\"The original address that sent the payment to the terminal.\",\"_projectId\":\"The ID of the project being paid.\"},\"returns\":{\"delegateAllocations\":\"The amount to send to delegates instead of adding to the local balance.\",\"fundingCycle\":\"The project's funding cycle during which payment was made.\",\"memo\":\"A memo that should be passed along to the emitted event.\",\"tokenCount\":\"The number of project tokens that were minted, as a fixed point number with 18 decimals.\"}},\"recordRedemptionFor(address,uint256,uint256,string,bytes)\":{\"details\":\"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.The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\",\"params\":{\"_holder\":\"The account that is having its tokens redeemed.\",\"_memo\":\"A memo to pass along to the emitted event.\",\"_metadata\":\"Bytes to send along to the data source, if one is provided.\",\"_projectId\":\"The ID of the project to which the tokens being redeemed belong.\",\"_tokenCount\":\"The number of project tokens to redeem, as a fixed point number with 18 decimals.\"},\"returns\":{\"delegateAllocations\":\"The amount to send to delegates instead of sending to the beneficiary.\",\"fundingCycle\":\"The funding cycle during which the redemption was made.\",\"memo\":\"A memo that should be passed along to the emitted event.\",\"reclaimAmount\":\"The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\"}},\"recordUsedAllowanceOf(uint256,uint256,uint256)\":{\"details\":\"The msg.sender must be an IJBSingleTokenPaymentTerminal. \",\"params\":{\"_amount\":\"The amount to use from the allowance, as a fixed point number. \",\"_currency\":\"The currency of the `_amount`. Must match the currency of the overflow allowance.\",\"_projectId\":\"The ID of the project to use the allowance of.\"},\"returns\":{\"fundingCycle\":\"The funding cycle during which the overflow allowance is being used.\",\"usedAmount\":\"The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\"}}},\"stateVariables\":{\"balanceOf\":{\"details\":\"The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal. _terminal The terminal to which the balance applies. _projectId The ID of the project to get the balance of.\"},\"usedDistributionLimitOf\":{\"details\":\"Increases as projects use their preconfigured distribution limits.The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal. _terminal The terminal to which the used distribution limit applies. _projectId The ID of the project to get the used distribution limit of. _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\"},\"usedOverflowAllowanceOf\":{\"details\":\"Increases as projects use their allowance.The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal. _terminal The terminal to which the overflow allowance applies. _projectId The ID of the project to get the used overflow allowance of. _configuration The configuration of the during which the allowance was used.\"}},\"version\":1},\"userdoc\":{\"errors\":{\"PRBMath__MulDivOverflow(uint256,uint256)\":[{\"notice\":\"Emitted when the result overflows uint256.\"}]},\"kind\":\"user\",\"methods\":{\"balanceOf(address,uint256)\":{\"notice\":\"The amount of tokens that each project has for each terminal, in terms of the terminal's token.\"},\"currentOverflowOf(address,uint256)\":{\"notice\":\"Gets the current overflowed amount in a terminal for a specified project.\"},\"currentReclaimableOverflowOf(address,uint256,uint256,bool)\":{\"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.\"},\"currentReclaimableOverflowOf(uint256,uint256,uint256,uint256)\":{\"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.\"},\"currentTotalOverflowOf(uint256,uint256,uint256)\":{\"notice\":\"Gets the current overflowed amount for a specified project across all terminals.\"},\"directory()\":{\"notice\":\"The directory of terminals and controllers for projects.\"},\"fundingCycleStore()\":{\"notice\":\"The contract storing all funding cycle configurations.\"},\"prices()\":{\"notice\":\"The contract that exposes price feeds.\"},\"recordAddedBalanceFor(uint256,uint256)\":{\"notice\":\"Records newly added funds for the project.\"},\"recordDistributionFor(uint256,uint256,uint256)\":{\"notice\":\"Records newly distributed funds for a project.\"},\"recordMigration(uint256)\":{\"notice\":\"Records the migration of funds from this store.\"},\"recordPaymentFrom(address,(address,uint256,uint256,uint256),uint256,uint256,address,string,bytes)\":{\"notice\":\"Records newly contributed tokens to a project.\"},\"recordRedemptionFor(address,uint256,uint256,string,bytes)\":{\"notice\":\"Records newly redeemed tokens of a project.\"},\"recordUsedAllowanceOf(uint256,uint256,uint256)\":{\"notice\":\"Records newly used allowance funds of a project.\"},\"usedDistributionLimitOf(address,uint256,uint256)\":{\"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.\"},\"usedOverflowAllowanceOf(address,uint256,uint256)\":{\"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.\"}},\"notice\":\"Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/JBSingleTokenPaymentTerminalStore3_1.sol\":\"JBSingleTokenPaymentTerminalStore3_1\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/security/ReentrancyGuard.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuard {\\n // Booleans are more expensive than uint256 or any type that takes up a full\\n // word because each write operation emits an extra SLOAD to first read the\\n // slot's contents, replace the bits taken up by the boolean, and then write\\n // back. This is the compiler's defense against contract upgrades and\\n // pointer aliasing, and it cannot be disabled.\\n\\n // The values being non-zero value makes deployment a bit more expensive,\\n // but in exchange the refund on every call to nonReentrant will be lower in\\n // amount. Since refunds are capped to a percentage of the total\\n // transaction's gas, it is best to keep them low in cases like this one, to\\n // increase the likelihood of the full refund coming into effect.\\n uint256 private constant _NOT_ENTERED = 1;\\n uint256 private constant _ENTERED = 2;\\n\\n uint256 private _status;\\n\\n constructor() {\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and making it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n // On the first call to nonReentrant, _notEntered will be true\\n require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n _status = _ENTERED;\\n\\n _;\\n\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n _status = _NOT_ENTERED;\\n }\\n}\\n\",\"keccak256\":\"0x0e9621f60b2faabe65549f7ed0f24e8853a45c1b7990d47e8160e523683f3935\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool _approved) external;\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x516a22876c1fab47f49b1bc22b4614491cd05338af8bd2e7b382da090a079990\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"@paulrberg/contracts/math/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\nimport \\\"prb-math/contracts/PRBMath.sol\\\";\\n\",\"keccak256\":\"0x42821345981bc0434a90ba2268a2f5278dfe9e38166981d72fc7f3b776a29495\",\"license\":\"Unlicense\"},\"contracts/JBSingleTokenPaymentTerminalStore3_1.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\\nimport '@paulrberg/contracts/math/PRBMath.sol';\\nimport './interfaces/IJBController3_1.sol';\\nimport './interfaces/IJBFundingCycleDataSource.sol';\\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\\nimport './libraries/JBConstants.sol';\\nimport './libraries/JBCurrencies.sol';\\nimport './libraries/JBFixedPointNumber.sol';\\nimport './libraries/JBFundingCycleMetadataResolver.sol';\\nimport './structs/JBPayDelegateAllocation.sol';\\nimport './structs/JBPayParamsData.sol';\\n\\n/**\\n @notice\\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\\n\\n @dev\\n Adheres to:\\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n\\n @dev\\n Inherits from -\\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\\n\\n @dev\\n This Store expects a project's controller to be an IJBController3_1. This is the only difference between this version and the original.\\n*/\\ncontract JBSingleTokenPaymentTerminalStore3_1 is\\n ReentrancyGuard,\\n IJBSingleTokenPaymentTerminalStore\\n{\\n // A library that parses the packed funding cycle metadata into a friendlier format.\\n using JBFundingCycleMetadataResolver for JBFundingCycle;\\n\\n //*********************************************************************//\\n // --------------------------- custom errors ------------------------- //\\n //*********************************************************************//\\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\\n error CURRENCY_MISMATCH();\\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\\n error FUNDING_CYCLE_PAYMENT_PAUSED();\\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\\n error FUNDING_CYCLE_REDEEM_PAUSED();\\n error INADEQUATE_CONTROLLER_ALLOWANCE();\\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\\n error INSUFFICIENT_TOKENS();\\n error INVALID_FUNDING_CYCLE();\\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\\n\\n //*********************************************************************//\\n // -------------------------- private constants ---------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \\n */\\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\\n\\n //*********************************************************************//\\n // ---------------- public immutable stored properties --------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The directory of terminals and controllers for projects.\\n */\\n IJBDirectory public immutable override directory;\\n\\n /**\\n @notice\\n The contract storing all funding cycle configurations.\\n */\\n IJBFundingCycleStore public immutable override fundingCycleStore;\\n\\n /**\\n @notice\\n The contract that exposes price feeds.\\n */\\n IJBPrices public immutable override prices;\\n\\n //*********************************************************************//\\n // --------------------- public stored properties -------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\\n\\n @dev\\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\\n\\n _terminal The terminal to which the balance applies.\\n _projectId The ID of the project to get the balance of.\\n */\\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\\n\\n /**\\n @notice\\n 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.\\n\\n @dev\\n Increases as projects use their preconfigured distribution limits.\\n\\n @dev\\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\\n\\n _terminal The terminal to which the used distribution limit applies.\\n _projectId The ID of the project to get the used distribution limit of.\\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\\n */\\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\\n public\\n override usedDistributionLimitOf;\\n\\n /**\\n @notice\\n 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.\\n\\n @dev\\n Increases as projects use their allowance.\\n\\n @dev\\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\\n\\n _terminal The terminal to which the overflow allowance applies.\\n _projectId The ID of the project to get the used overflow allowance of.\\n _configuration The configuration of the during which the allowance was used.\\n */\\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\\n public\\n override usedOverflowAllowanceOf;\\n\\n //*********************************************************************//\\n // ------------------------- external views -------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Gets the current overflowed amount in a terminal for a specified project.\\n\\n @dev\\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\\n\\n @param _terminal The terminal for which the overflow is being calculated.\\n @param _projectId The ID of the project to get overflow for.\\n\\n @return The current amount of overflow that project has in the specified terminal.\\n */\\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\\n external\\n view\\n override\\n returns (uint256)\\n {\\n // Return the overflow during the project's current funding cycle.\\n return\\n _overflowDuring(\\n _terminal,\\n _projectId,\\n fundingCycleStore.currentOf(_projectId),\\n _terminal.currency()\\n );\\n }\\n\\n /**\\n @notice\\n Gets the current overflowed amount for a specified project across all terminals.\\n\\n @param _projectId The ID of the project to get total overflow for.\\n @param _decimals The number of decimals that the fixed point overflow should include.\\n @param _currency The currency that the total overflow should be in terms of.\\n\\n @return The current total amount of overflow that project has across all terminals.\\n */\\n function currentTotalOverflowOf(\\n uint256 _projectId,\\n uint256 _decimals,\\n uint256 _currency\\n ) external view override returns (uint256) {\\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\\n }\\n\\n /**\\n @notice\\n 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.\\n\\n @dev \\n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\\n\\n @dev\\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\\n\\n @dev\\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\\n\\n @param _terminal The terminal from which the reclaimable amount would come.\\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\\n @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`.\\n\\n @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`.\\n */\\n function currentReclaimableOverflowOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n bool _useTotalOverflow\\n ) external view override returns (uint256) {\\n // Get a reference to the project's current funding cycle.\\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // Get the amount of current overflow.\\n // 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.\\n uint256 _currentOverflow = _useTotalOverflow\\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\\n\\n // If there's no overflow, there's no reclaimable overflow.\\n if (_currentOverflow == 0) return 0;\\n\\n // Get the number of outstanding tokens the project has.\\n uint256 _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\\n .totalOutstandingTokensOf(_projectId);\\n\\n // Can't redeem more tokens that is in the supply.\\n if (_tokenCount > _totalSupply) return 0;\\n\\n // Return the reclaimable overflow amount.\\n return\\n _reclaimableOverflowDuring(\\n _projectId,\\n _fundingCycle,\\n _tokenCount,\\n _totalSupply,\\n _currentOverflow\\n );\\n }\\n\\n /**\\n @notice\\n 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.\\n\\n @dev \\n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\\n\\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\\n\\n @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`.\\n */\\n function currentReclaimableOverflowOf(\\n uint256 _projectId,\\n uint256 _tokenCount,\\n uint256 _totalSupply,\\n uint256 _overflow\\n ) external view override returns (uint256) {\\n // If there's no overflow, there's no reclaimable overflow.\\n if (_overflow == 0) return 0;\\n\\n // Can't redeem more tokens that is in the supply.\\n if (_tokenCount > _totalSupply) return 0;\\n\\n // Get a reference to the project's current funding cycle.\\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // Return the reclaimable overflow amount.\\n return\\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\\n }\\n\\n //*********************************************************************//\\n // -------------------------- constructor ---------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @param _directory A contract storing directories of terminals and controllers for each project.\\n @param _fundingCycleStore A contract storing all funding cycle configurations.\\n @param _prices A contract that exposes price feeds.\\n */\\n constructor(\\n IJBDirectory _directory,\\n IJBFundingCycleStore _fundingCycleStore,\\n IJBPrices _prices\\n ) {\\n directory = _directory;\\n fundingCycleStore = _fundingCycleStore;\\n prices = _prices;\\n }\\n\\n //*********************************************************************//\\n // ---------------------- external transactions ---------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Records newly contributed tokens to a project.\\n\\n @dev\\n 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.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\\n\\n @param _payer The original address that sent the payment to the terminal.\\n @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.\\n @param _projectId The ID of the project being paid.\\n @param _baseWeightCurrency The currency to base token issuance on.\\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\\n @param _metadata Bytes to send along to the data source, if one is provided.\\n\\n @return fundingCycle The project's funding cycle during which payment was made.\\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\\n @return memo A memo that should be passed along to the emitted event.\\n */\\n function recordPaymentFrom(\\n address _payer,\\n JBTokenAmount calldata _amount,\\n uint256 _projectId,\\n uint256 _baseWeightCurrency,\\n address _beneficiary,\\n string calldata _memo,\\n bytes memory _metadata\\n )\\n external\\n override\\n nonReentrant\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 tokenCount,\\n JBPayDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n )\\n {\\n // Get a reference to the current funding cycle for the project.\\n fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // The project must have a funding cycle configured.\\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\\n\\n // Must not be paused.\\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\\n\\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\\n uint256 _weight;\\n\\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\\n // Create the params that'll be sent to the data source.\\n JBPayParamsData memory _data = JBPayParamsData(\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n _payer,\\n _amount,\\n _projectId,\\n fundingCycle.configuration,\\n _beneficiary,\\n fundingCycle.weight,\\n fundingCycle.reservedRate(),\\n _memo,\\n _metadata\\n );\\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\\n .payParams(_data);\\n }\\n // Otherwise use the funding cycle's weight\\n else {\\n _weight = fundingCycle.weight;\\n memo = _memo;\\n }\\n\\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\\n {\\n // Keep a reference to the amount that should be added to the project's balance.\\n uint256 _balanceDiff = _amount.value;\\n\\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\\n if (delegateAllocations.length != 0) {\\n for (uint256 _i; _i < delegateAllocations.length; ) {\\n // Get a reference to the amount to be delegated.\\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\\n\\n // Validate if non-zero.\\n if (_delegatedAmount != 0) {\\n // Can't delegate more than was paid.\\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\\n\\n // Decrement the total amount being added to the balance.\\n _balanceDiff = _balanceDiff - _delegatedAmount;\\n }\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n\\n // If there's no amount being recorded, there's nothing left to do.\\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\\n\\n // Add the correct balance difference to the token balance of the project.\\n if (_balanceDiff != 0)\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\\n _balanceDiff;\\n }\\n\\n // If there's no weight, token count must be 0 so there's nothing left to do.\\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\\n\\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\\n uint256 _decimals = _amount.decimals;\\n\\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\\n // 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`.\\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\\n ? 10**_decimals\\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\\n\\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\\n }\\n\\n /**\\n @notice\\n Records newly redeemed tokens of a project.\\n\\n @dev\\n 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.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\\n\\n @param _holder The account that is having its tokens redeemed.\\n @param _projectId The ID of the project to which the tokens being redeemed belong.\\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Bytes to send along to the data source, if one is provided.\\n\\n @return fundingCycle The funding cycle during which the redemption was made.\\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\\n @return memo A memo that should be passed along to the emitted event.\\n */\\n function recordRedemptionFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n string memory _memo,\\n bytes memory _metadata\\n )\\n external\\n override\\n nonReentrant\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 reclaimAmount,\\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n )\\n {\\n // Get a reference to the project's current funding cycle.\\n fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // The current funding cycle must not be paused.\\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\\n\\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\\n {\\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\\n JBTokenAmount memory _reclaimedTokenAmount;\\n uint256 _currentOverflow;\\n uint256 _totalSupply;\\n\\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\\n {\\n // Get a reference to the terminal's tokens.\\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\\n\\n // Get a reference to the terminal's decimals.\\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\\n\\n // Get areference to the terminal's currency.\\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\\n\\n // Get the amount of current overflow.\\n // 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.\\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\\n : _overflowDuring(\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n _projectId,\\n fundingCycle,\\n _currency\\n );\\n\\n // Get the number of outstanding tokens the project has.\\n _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\\n .totalOutstandingTokensOf(_projectId);\\n\\n // Can't redeem more tokens that is in the supply.\\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\\n\\n if (_currentOverflow != 0)\\n // Calculate reclaim amount using the current overflow amount.\\n reclaimAmount = _reclaimableOverflowDuring(\\n _projectId,\\n fundingCycle,\\n _tokenCount,\\n _totalSupply,\\n _currentOverflow\\n );\\n\\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\\n }\\n\\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\\n {\\n // Get a reference to the ballot state.\\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\\n\\n // Create the params that'll be sent to the data source.\\n JBRedeemParamsData memory _data = JBRedeemParamsData(\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n _holder,\\n _projectId,\\n fundingCycle.configuration,\\n _tokenCount,\\n _totalSupply,\\n _currentOverflow,\\n _reclaimedTokenAmount,\\n fundingCycle.useTotalOverflowForRedemptions(),\\n _state == JBBallotState.Active\\n ? fundingCycle.ballotRedemptionRate()\\n : fundingCycle.redemptionRate(),\\n _memo,\\n _metadata\\n );\\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\\n fundingCycle.dataSource()\\n ).redeemParams(_data);\\n }\\n } else {\\n memo = _memo;\\n }\\n }\\n\\n // Keep a reference to the amount that should be subtracted from the project's balance.\\n uint256 _balanceDiff = reclaimAmount;\\n\\n if (delegateAllocations.length != 0) {\\n // Validate all delegated amounts.\\n for (uint256 _i; _i < delegateAllocations.length; ) {\\n // Get a reference to the amount to be delegated.\\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\\n\\n // Validate if non-zero.\\n if (_delegatedAmount != 0)\\n // Increment the total amount being subtracted from the balance.\\n _balanceDiff = _balanceDiff + _delegatedAmount;\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n\\n // The amount being reclaimed must be within the project's balance.\\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\\n\\n // Remove the reclaimed funds from the project's balance.\\n if (_balanceDiff != 0) {\\n unchecked {\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\\n _balanceDiff;\\n }\\n }\\n }\\n\\n /**\\n @notice\\n Records newly distributed funds for a project.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \\n\\n @param _projectId The ID of the project that is having funds distributed.\\n @param _amount The amount to use from the distribution limit, as a fixed point number.\\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\\n\\n @return fundingCycle The funding cycle during which the distribution was made.\\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\\n */\\n function recordDistributionFor(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n )\\n external\\n override\\n nonReentrant\\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\\n {\\n // Get a reference to the project's current funding cycle.\\n fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // The funding cycle must not be configured to have distributions paused.\\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\\n\\n // The new total amount that has been distributed during this funding cycle.\\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\\n IJBSingleTokenPaymentTerminal(msg.sender)\\n ][_projectId][fundingCycle.number] + _amount;\\n\\n // Amount must be within what is still distributable.\\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController3_1(\\n directory.controllerOf(_projectId)\\n ).fundAccessConstraintsStore().distributionLimitOf(\\n _projectId,\\n fundingCycle.configuration,\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n IJBSingleTokenPaymentTerminal(msg.sender).token()\\n );\\n\\n // Make sure the new used amount is within the distribution limit.\\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\\n\\n // Make sure the currencies match.\\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\\n\\n // Get a reference to the terminal's currency.\\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\\n\\n // Convert the amount to the balance's currency.\\n distributedAmount = (_currency == _balanceCurrency)\\n ? _amount\\n : PRBMath.mulDiv(\\n _amount,\\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\\n );\\n\\n // The amount being distributed must be available.\\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\\n\\n // Store the new amount.\\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\\n fundingCycle.number\\n ] = _newUsedDistributionLimitOf;\\n\\n // Removed the distributed funds from the project's token balance.\\n unchecked {\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\\n distributedAmount;\\n }\\n }\\n\\n /**\\n @notice\\n Records newly used allowance funds of a project.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \\n\\n @param _projectId The ID of the project to use the allowance of.\\n @param _amount The amount to use from the allowance, as a fixed point number. \\n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\\n\\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\\n */\\n function recordUsedAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n )\\n external\\n override\\n nonReentrant\\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\\n {\\n // Get a reference to the project's current funding cycle.\\n fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\\n IJBSingleTokenPaymentTerminal(msg.sender)\\n ][_projectId][fundingCycle.configuration] + _amount;\\n\\n // There must be sufficient allowance available.\\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController3_1(\\n directory.controllerOf(_projectId)\\n ).fundAccessConstraintsStore().overflowAllowanceOf(\\n _projectId,\\n fundingCycle.configuration,\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n IJBSingleTokenPaymentTerminal(msg.sender).token()\\n );\\n\\n // Make sure the new used amount is within the allowance.\\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\\n\\n // Make sure the currencies match.\\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\\n\\n // Get a reference to the terminal's currency.\\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\\n\\n // Convert the amount to this store's terminal's token.\\n usedAmount = (_currency == _balanceCurrency)\\n ? _amount\\n : PRBMath.mulDiv(\\n _amount,\\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\\n );\\n\\n // The amount being distributed must be available in the overflow.\\n if (\\n usedAmount >\\n _overflowDuring(\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n _projectId,\\n fundingCycle,\\n _balanceCurrency\\n )\\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\\n\\n // Store the incremented value.\\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\\n fundingCycle.configuration\\n ] = _newUsedOverflowAllowanceOf;\\n\\n // Update the project's balance.\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\\n usedAmount;\\n }\\n\\n /**\\n @notice\\n Records newly added funds for the project.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \\n\\n @param _projectId The ID of the project to which the funds being added belong.\\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\\n */\\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\\n // Increment the balance.\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\\n _amount;\\n }\\n\\n /**\\n @notice\\n Records the migration of funds from this store.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\\n\\n @param _projectId The ID of the project being migrated.\\n\\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\\n */\\n function recordMigration(uint256 _projectId)\\n external\\n override\\n nonReentrant\\n returns (uint256 balance)\\n {\\n // Get a reference to the project's current funding cycle.\\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // Migration must be allowed.\\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\\n\\n // Return the current balance.\\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\\n\\n // Set the balance to 0.\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\\n }\\n\\n //*********************************************************************//\\n // --------------------- private helper functions -------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\\n\\n @dev \\n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\\n\\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\\n @param _overflow The amount of overflow to make the calculation with.\\n\\n @return The amount of overflowed tokens that can be reclaimed.\\n */\\n function _reclaimableOverflowDuring(\\n uint256 _projectId,\\n JBFundingCycle memory _fundingCycle,\\n uint256 _tokenCount,\\n uint256 _totalSupply,\\n uint256 _overflow\\n ) private view returns (uint256) {\\n // If the amount being redeemed is the total supply, return the rest of the overflow.\\n if (_tokenCount == _totalSupply) return _overflow;\\n\\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\\n JBBallotState.Active\\n ? _fundingCycle.ballotRedemptionRate()\\n : _fundingCycle.redemptionRate();\\n\\n // If the redemption rate is 0, nothing is claimable.\\n if (_redemptionRate == 0) return 0;\\n\\n // Get a reference to the linear proportion.\\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\\n\\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\\n\\n return\\n PRBMath.mulDiv(\\n _base,\\n _redemptionRate +\\n PRBMath.mulDiv(\\n _tokenCount,\\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\\n _totalSupply\\n ),\\n JBConstants.MAX_REDEMPTION_RATE\\n );\\n }\\n\\n /**\\n @notice\\n Gets the amount that is overflowing when measured from the specified funding cycle.\\n\\n @dev\\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\\n\\n @param _terminal The terminal for which the overflow is being calculated.\\n @param _projectId The ID of the project to get overflow for.\\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\\n\\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\\n */\\n function _overflowDuring(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n JBFundingCycle memory _fundingCycle,\\n uint256 _balanceCurrency\\n ) private view returns (uint256) {\\n // Get the current balance of the project.\\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\\n\\n // If there's no balance, there's no overflow.\\n if (_balanceOf == 0) return 0;\\n\\n // Get a reference to the distribution limit during the funding cycle.\\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController3_1(\\n directory.controllerOf(_projectId)\\n ).fundAccessConstraintsStore().distributionLimitOf(\\n _projectId,\\n _fundingCycle.configuration,\\n _terminal,\\n _terminal.token()\\n );\\n\\n // Get a reference to the amount still distributable during the funding cycle.\\n uint256 _distributionLimitRemaining = _distributionLimit -\\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\\n\\n // Convert the _distributionRemaining to be in terms of the provided currency.\\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\\n _distributionLimitRemaining = PRBMath.mulDiv(\\n _distributionLimitRemaining,\\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\\n );\\n\\n // Overflow is the balance of this project minus the amount that can still be distributed.\\n unchecked {\\n return\\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\\n }\\n }\\n\\n /**\\n @notice\\n Gets the amount that is currently overflowing across all of a project's terminals. \\n\\n @dev\\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\\n\\n @param _projectId The ID of the project to get the total overflow for.\\n @param _decimals The number of decimals that the fixed point overflow should include.\\n @param _currency The currency that the overflow should be in terms of.\\n\\n @return overflow The total overflow of a project's funds.\\n */\\n function _currentTotalOverflowOf(\\n uint256 _projectId,\\n uint256 _decimals,\\n uint256 _currency\\n ) private view returns (uint256) {\\n // Get a reference to the project's terminals.\\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\\n\\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\\n uint256 _ethOverflow;\\n\\n // Add the current ETH overflow for each terminal.\\n for (uint256 _i; _i < _terminals.length; ) {\\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\\n unchecked {\\n ++_i;\\n }\\n }\\n\\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.ETH\\n ? _ethOverflow\\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.ETH, _currency, 18));\\n\\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\\n return\\n (_decimals == 18)\\n ? _totalOverflow18Decimal\\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\\n }\\n}\\n\",\"keccak256\":\"0x7fc9e05a77c0d37c10709df6f479562d73d684b9aec28d0227e83beffa4d2a01\",\"license\":\"MIT\"},\"contracts/enums/JBBallotState.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nenum JBBallotState {\\n Active,\\n Approved,\\n Failed\\n}\\n\",\"keccak256\":\"0x891fcac63470398b3a11239da7feba6b07d640809fcefd2404303b823d7378f8\",\"license\":\"MIT\"},\"contracts/interfaces/IJBController.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBFundAccessConstraints.sol';\\nimport './../structs/JBFundingCycleData.sol';\\nimport './../structs/JBFundingCycleMetadata.sol';\\nimport './../structs/JBGroupedSplits.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBMigratable.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBSplitsStore.sol';\\nimport './IJBTokenStore.sol';\\n\\ninterface IJBController is IERC165 {\\n event LaunchProject(uint256 configuration, uint256 projectId, string memo, address caller);\\n\\n event LaunchFundingCycles(uint256 configuration, uint256 projectId, string memo, address caller);\\n\\n event ReconfigureFundingCycles(\\n uint256 configuration,\\n uint256 projectId,\\n string memo,\\n address caller\\n );\\n\\n event SetFundAccessConstraints(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n JBFundAccessConstraints constraints,\\n address caller\\n );\\n\\n event DistributeReservedTokens(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address beneficiary,\\n uint256 tokenCount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n address caller\\n );\\n\\n event DistributeToReservedTokenSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n uint256 tokenCount,\\n address caller\\n );\\n\\n event MintTokens(\\n address indexed beneficiary,\\n uint256 indexed projectId,\\n uint256 tokenCount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n uint256 reservedRate,\\n address caller\\n );\\n\\n event BurnTokens(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 tokenCount,\\n string memo,\\n address caller\\n );\\n\\n event Migrate(uint256 indexed projectId, IJBMigratable to, address caller);\\n\\n event PrepMigration(uint256 indexed projectId, address from, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function tokenStore() external view returns (IJBTokenStore);\\n\\n function splitsStore() external view returns (IJBSplitsStore);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function reservedTokenBalanceOf(uint256 _projectId, uint256 _reservedRate)\\n external\\n view\\n returns (uint256);\\n\\n function distributionLimitOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n IJBPaymentTerminal _terminal,\\n address _token\\n ) external view returns (uint256 distributionLimit, uint256 distributionLimitCurrency);\\n\\n function overflowAllowanceOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n IJBPaymentTerminal _terminal,\\n address _token\\n ) external view returns (uint256 overflowAllowance, uint256 overflowAllowanceCurrency);\\n\\n function totalOutstandingTokensOf(uint256 _projectId, uint256 _reservedRate)\\n external\\n view\\n returns (uint256);\\n\\n function getFundingCycleOf(uint256 _projectId, uint256 _configuration)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function latestConfiguredFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (\\n JBFundingCycle memory,\\n JBFundingCycleMetadata memory metadata,\\n JBBallotState\\n );\\n\\n function currentFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function queuedFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function launchProjectFor(\\n address _owner,\\n JBProjectMetadata calldata _projectMetadata,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n IJBPaymentTerminal[] memory _terminals,\\n string calldata _memo\\n ) external returns (uint256 projectId);\\n\\n function launchFundingCyclesFor(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n IJBPaymentTerminal[] memory _terminals,\\n string calldata _memo\\n ) external returns (uint256 configuration);\\n\\n function reconfigureFundingCyclesOf(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n string calldata _memo\\n ) external returns (uint256);\\n\\n function mintTokensOf(\\n uint256 _projectId,\\n uint256 _tokenCount,\\n address _beneficiary,\\n string calldata _memo,\\n bool _preferClaimedTokens,\\n bool _useReservedRate\\n ) external returns (uint256 beneficiaryTokenCount);\\n\\n function burnTokensOf(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n string calldata _memo,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function distributeReservedTokensOf(uint256 _projectId, string memory _memo)\\n external\\n returns (uint256);\\n\\n function migrate(uint256 _projectId, IJBMigratable _to) external;\\n}\\n\",\"keccak256\":\"0xb1ee4b41f2a06f28f69c74cb729b8964f2e75f3c545a68f85bd9082b5575bc85\",\"license\":\"MIT\"},\"contracts/interfaces/IJBController3_0_1.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBFundAccessConstraints.sol';\\nimport './../structs/JBFundingCycleData.sol';\\nimport './../structs/JBFundingCycleMetadata.sol';\\nimport './../structs/JBGroupedSplits.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBController.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBMigratable.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBSplitsStore.sol';\\nimport './IJBTokenStore.sol';\\n\\ninterface IJBController3_0_1 {\\n function reservedTokenBalanceOf(uint256 _projectId) external view returns (uint256);\\n function totalOutstandingTokensOf(uint256 _projectId) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xf853badd9b8c149b7e1cd01b1123a949bc64036cfcc9e4b6d237b6911eccb058\",\"license\":\"MIT\"},\"contracts/interfaces/IJBController3_1.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBFundAccessConstraints.sol';\\nimport './../structs/JBFundingCycleData.sol';\\nimport './../structs/JBFundingCycleMetadata.sol';\\nimport './../structs/JBGroupedSplits.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBController3_0_1.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFundAccessConstraintsStore.sol';\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBMigratable.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBSplitsStore.sol';\\nimport './IJBTokenStore.sol';\\n\\ninterface IJBController3_1 is IJBController3_0_1, IERC165 {\\n event LaunchProject(uint256 configuration, uint256 projectId, string memo, address caller);\\n\\n event LaunchFundingCycles(uint256 configuration, uint256 projectId, string memo, address caller);\\n\\n event ReconfigureFundingCycles(\\n uint256 configuration,\\n uint256 projectId,\\n string memo,\\n address caller\\n );\\n\\n event DistributeReservedTokens(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address beneficiary,\\n uint256 tokenCount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n address caller\\n );\\n\\n event DistributeToReservedTokenSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n uint256 tokenCount,\\n address caller\\n );\\n\\n event MintTokens(\\n address indexed beneficiary,\\n uint256 indexed projectId,\\n uint256 tokenCount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n uint256 reservedRate,\\n address caller\\n );\\n\\n event BurnTokens(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 tokenCount,\\n string memo,\\n address caller\\n );\\n\\n event Migrate(uint256 indexed projectId, IJBMigratable to, address caller);\\n\\n event PrepMigration(uint256 indexed projectId, address from, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function tokenStore() external view returns (IJBTokenStore);\\n\\n function splitsStore() external view returns (IJBSplitsStore);\\n\\n function fundAccessConstraintsStore() external view returns (IJBFundAccessConstraintsStore);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function reservedTokenBalanceOf(uint256 _projectId) external view returns (uint256);\\n\\n function totalOutstandingTokensOf(uint256 _projectId) external view returns (uint256);\\n\\n function getFundingCycleOf(uint256 _projectId, uint256 _configuration)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function latestConfiguredFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (\\n JBFundingCycle memory,\\n JBFundingCycleMetadata memory metadata,\\n JBBallotState\\n );\\n\\n function currentFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function queuedFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function launchProjectFor(\\n address _owner,\\n JBProjectMetadata calldata _projectMetadata,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n IJBPaymentTerminal[] memory _terminals,\\n string calldata _memo\\n ) external returns (uint256 projectId);\\n\\n function launchFundingCyclesFor(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n IJBPaymentTerminal[] memory _terminals,\\n string calldata _memo\\n ) external returns (uint256 configuration);\\n\\n function reconfigureFundingCyclesOf(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n string calldata _memo\\n ) external returns (uint256);\\n\\n function mintTokensOf(\\n uint256 _projectId,\\n uint256 _tokenCount,\\n address _beneficiary,\\n string calldata _memo,\\n bool _preferClaimedTokens,\\n bool _useReservedRate\\n ) external returns (uint256 beneficiaryTokenCount);\\n\\n function burnTokensOf(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n string calldata _memo,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function distributeReservedTokensOf(uint256 _projectId, string memory _memo)\\n external\\n returns (uint256);\\n\\n function migrate(uint256 _projectId, IJBMigratable _to) external;\\n}\\n\",\"keccak256\":\"0x9aea97f1a77f48d313aee6c9ea97dffdfdb4f50c1cfd94f0b360a8ce6e383f4c\",\"license\":\"MIT\"},\"contracts/interfaces/IJBDirectory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBProjects.sol';\\n\\ninterface IJBDirectory {\\n event SetController(uint256 indexed projectId, address indexed controller, address caller);\\n\\n event AddTerminal(uint256 indexed projectId, IJBPaymentTerminal indexed terminal, address caller);\\n\\n event SetTerminals(uint256 indexed projectId, IJBPaymentTerminal[] terminals, address caller);\\n\\n event SetPrimaryTerminal(\\n uint256 indexed projectId,\\n address indexed token,\\n IJBPaymentTerminal indexed terminal,\\n address caller\\n );\\n\\n event SetIsAllowedToSetFirstController(address indexed addr, bool indexed flag, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function controllerOf(uint256 _projectId) external view returns (address);\\n\\n function isAllowedToSetFirstController(address _address) external view returns (bool);\\n\\n function terminalsOf(uint256 _projectId) external view returns (IJBPaymentTerminal[] memory);\\n\\n function isTerminalOf(uint256 _projectId, IJBPaymentTerminal _terminal)\\n external\\n view\\n returns (bool);\\n\\n function primaryTerminalOf(uint256 _projectId, address _token)\\n external\\n view\\n returns (IJBPaymentTerminal);\\n\\n function setControllerOf(uint256 _projectId, address _controller) external;\\n\\n function setTerminalsOf(uint256 _projectId, IJBPaymentTerminal[] calldata _terminals) external;\\n\\n function setPrimaryTerminalOf(\\n uint256 _projectId,\\n address _token,\\n IJBPaymentTerminal _terminal\\n ) external;\\n\\n function setIsAllowedToSetFirstController(address _address, bool _flag) external;\\n}\\n\",\"keccak256\":\"0x715321646db00514d1355ed43c40cd3f01e94959552fd07797b315d9c49cdb1d\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundAccessConstraintsStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBFundAccessConstraints.sol';\\nimport './IJBPaymentTerminal.sol';\\n\\ninterface IJBFundAccessConstraintsStore is IERC165 {\\n event SetFundAccessConstraints(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed projectId,\\n JBFundAccessConstraints constraints,\\n address caller\\n );\\n\\n function distributionLimitOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n IJBPaymentTerminal _terminal,\\n address _token\\n ) external view returns (uint256 distributionLimit, uint256 distributionLimitCurrency);\\n\\n function overflowAllowanceOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n IJBPaymentTerminal _terminal,\\n address _token\\n ) external view returns (uint256 overflowAllowance, uint256 overflowAllowanceCurrency);\\n\\n function setFor(\\n uint256 _projectId,\\n uint256 _configuration,\\n JBFundAccessConstraints[] memory _fundAccessConstaints\\n ) external;\\n}\\n\",\"keccak256\":\"0x3158c6cab1b81827a5a2d90a5936a0c7f8ba0d1bcdb05ae8b8a1ac7f03d0c999\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleBallot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../enums/JBBallotState.sol';\\n\\ninterface IJBFundingCycleBallot is IERC165 {\\n function duration() external view returns (uint256);\\n\\n function stateOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n uint256 _start\\n ) external view returns (JBBallotState);\\n}\\n\",\"keccak256\":\"0x49553a56209237846bc400cf27f260824a6bd06fd8094a7eb5abb9de75779598\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleDataSource.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBPayDelegateAllocation.sol';\\nimport './../structs/JBPayParamsData.sol';\\nimport './../structs/JBRedeemParamsData.sol';\\nimport './../structs/JBRedemptionDelegateAllocation.sol';\\n\\n/**\\n @title\\n Datasource\\n\\n @notice\\n The datasource is called by JBPaymentTerminal on pay and redemption, and provide an extra layer of logic to use \\n a custom weight, a custom memo and/or a pay/redeem delegate\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n*/\\ninterface IJBFundingCycleDataSource is IERC165 {\\n /**\\n @notice\\n The datasource implementation for JBPaymentTerminal.pay(..)\\n\\n @param _data the data passed to the data source in terminal.pay(..), as a JBPayParamsData struct:\\n IJBPaymentTerminal terminal;\\n address payer;\\n JBTokenAmount amount;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n address beneficiary;\\n uint256 weight;\\n uint256 reservedRate;\\n string memo;\\n bytes metadata;\\n\\n @return weight the weight to use to override the funding cycle weight\\n @return memo the memo to override the pay(..) memo\\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\\n */\\n function payParams(JBPayParamsData calldata _data)\\n external\\n returns (\\n uint256 weight,\\n string memory memo,\\n JBPayDelegateAllocation[] memory delegateAllocations\\n );\\n\\n /**\\n @notice\\n The datasource implementation for JBPaymentTerminal.redeemTokensOf(..)\\n\\n @param _data the data passed to the data source in terminal.redeemTokensOf(..), as a JBRedeemParamsData struct:\\n IJBPaymentTerminal terminal;\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 tokenCount;\\n uint256 totalSupply;\\n uint256 overflow;\\n JBTokenAmount reclaimAmount;\\n bool useTotalOverflow;\\n uint256 redemptionRate;\\n uint256 ballotRedemptionRate;\\n string memo;\\n bytes metadata;\\n\\n @return reclaimAmount The amount to claim, overriding the terminal logic.\\n @return memo The memo to override the redeemTokensOf(..) memo.\\n @return delegateAllocations The amount to send to delegates instead of adding to the beneficiary.\\n */\\n function redeemParams(JBRedeemParamsData calldata _data)\\n external\\n returns (\\n uint256 reclaimAmount,\\n string memory memo,\\n JBRedemptionDelegateAllocation[] memory delegateAllocations\\n );\\n}\\n\",\"keccak256\":\"0xa424abc146a61b69db83e511c064492da6fab6d8226e13d1580bc9fbc50d6738\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../enums/JBBallotState.sol';\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBFundingCycleData.sol';\\n\\ninterface IJBFundingCycleStore {\\n event Configure(\\n uint256 indexed configuration,\\n uint256 indexed projectId,\\n JBFundingCycleData data,\\n uint256 metadata,\\n uint256 mustStartAtOrAfter,\\n address caller\\n );\\n\\n event Init(uint256 indexed configuration, uint256 indexed projectId, uint256 indexed basedOn);\\n\\n function latestConfigurationOf(uint256 _projectId) external view returns (uint256);\\n\\n function get(uint256 _projectId, uint256 _configuration)\\n external\\n view\\n returns (JBFundingCycle memory);\\n\\n function latestConfiguredOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBBallotState ballotState);\\n\\n function queuedOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentBallotStateOf(uint256 _projectId) external view returns (JBBallotState);\\n\\n function configureFor(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n uint256 _metadata,\\n uint256 _mustStartAtOrAfter\\n ) external returns (JBFundingCycle memory fundingCycle);\\n}\\n\",\"keccak256\":\"0xaead823851433be0c2ddc8f8086813e6cd647de3a1bc0f7570a5d6b38c378b5a\",\"license\":\"MIT\"},\"contracts/interfaces/IJBMigratable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBMigratable {\\n function prepForMigrationOf(uint256 _projectId, address _from) external;\\n}\\n\",\"keccak256\":\"0xc81053e4b4754fc510aa04fecd3ab1460f01e3e27761e7a8c94f631a978ae127\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPayDelegate.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBDidPayData.sol';\\n\\n/**\\n @title\\n Pay delegate\\n\\n @notice\\n Delegate called after JBTerminal.pay(..) logic completion (if passed by the funding cycle datasource)\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n*/\\ninterface IJBPayDelegate is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.pay(..), after the execution of its logic\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control\\n \\n @param _data the data passed by the terminal, as a JBDidPayData struct:\\n address payer;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n JBTokenAmount amount;\\n JBTokenAmount forwardedAmount;\\n uint256 projectTokenCount;\\n address beneficiary;\\n bool preferClaimedTokens;\\n string memo;\\n bytes metadata;\\n */\\n function didPay(JBDidPayData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0xa797de18b69eceba117e1f0b3810cf3cc2d2791417d580a5bdc510d1b868ab26\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\n\\ninterface IJBPaymentTerminal is IERC165 {\\n function acceptsToken(address _token, uint256 _projectId) external view returns (bool);\\n\\n function currencyForToken(address _token) external view returns (uint256);\\n\\n function decimalsForToken(address _token) external view returns (uint256);\\n\\n // Return value must be a fixed point number with 18 decimals.\\n function currentEthOverflowOf(uint256 _projectId) external view returns (uint256);\\n\\n function pay(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable returns (uint256 beneficiaryTokenCount);\\n\\n function addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable;\\n}\\n\",\"keccak256\":\"0xb7826f5ed609359ce322c09e83236c47ba385df1c3cad3607e56fd0a2e00eee2\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPriceFeed.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBPriceFeed {\\n function currentPrice(uint256 _targetDecimals) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x57c71282fec1b34b00cf991ffed2e36031c393e35bfa7ca5d723eb6572fb7122\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPrices.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBPriceFeed.sol';\\n\\ninterface IJBPrices {\\n event AddFeed(uint256 indexed currency, uint256 indexed base, IJBPriceFeed feed);\\n\\n function feedFor(uint256 _currency, uint256 _base) external view returns (IJBPriceFeed);\\n\\n function priceFor(\\n uint256 _currency,\\n uint256 _base,\\n uint256 _decimals\\n ) external view returns (uint256);\\n\\n function addFeedFor(\\n uint256 _currency,\\n uint256 _base,\\n IJBPriceFeed _priceFeed\\n ) external;\\n}\\n\",\"keccak256\":\"0x82a175b1f4b95b506c98406576cd59cbe04615e3df24f9cf3587b61b8ee323b1\",\"license\":\"MIT\"},\"contracts/interfaces/IJBProjects.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBTokenUriResolver.sol';\\n\\ninterface IJBProjects is IERC721 {\\n event Create(\\n uint256 indexed projectId,\\n address indexed owner,\\n JBProjectMetadata metadata,\\n address caller\\n );\\n\\n event SetMetadata(uint256 indexed projectId, JBProjectMetadata metadata, address caller);\\n\\n event SetTokenUriResolver(IJBTokenUriResolver indexed resolver, address caller);\\n\\n function count() external view returns (uint256);\\n\\n function metadataContentOf(uint256 _projectId, uint256 _domain)\\n external\\n view\\n returns (string memory);\\n\\n function tokenUriResolver() external view returns (IJBTokenUriResolver);\\n\\n function createFor(address _owner, JBProjectMetadata calldata _metadata)\\n external\\n returns (uint256 projectId);\\n\\n function setMetadataOf(uint256 _projectId, JBProjectMetadata calldata _metadata) external;\\n\\n function setTokenUriResolver(IJBTokenUriResolver _newResolver) external;\\n}\\n\",\"keccak256\":\"0x7cfc021d0bd7e73b1ba8f4845d7d35e3419d6a14d3d25ca3a8010e7f91062fe4\",\"license\":\"MIT\"},\"contracts/interfaces/IJBRedemptionDelegate.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBDidRedeemData.sol';\\n\\n/**\\n @title\\n Redemption delegate\\n\\n @notice\\n Delegate called after JBTerminal.redeemTokensOf(..) logic completion (if passed by the funding cycle datasource)\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n*/\\ninterface IJBRedemptionDelegate is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.redeemTokensOf(..), after the execution of its logic\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control\\n \\n @param _data the data passed by the terminal, as a JBDidRedeemData struct:\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 projectTokenCount;\\n JBTokenAmount reclaimedAmount;\\n JBTokenAmount forwardedAmount;\\n address payable beneficiary;\\n string memo;\\n bytes metadata;\\n */\\n function didRedeem(JBDidRedeemData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0x172d2c0be65e72e54f71ae521907067f0fa30e8ca05c4f88826903208aa437e2\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSingleTokenPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBPaymentTerminal.sol';\\n\\ninterface IJBSingleTokenPaymentTerminal is IJBPaymentTerminal {\\n function token() external view returns (address);\\n\\n function currency() external view returns (uint256);\\n\\n function decimals() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xf6e78323caa9af7bbf024f44b2032a83fed0394e0b3a242a6346e73c85b2e46f\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSingleTokenPaymentTerminalStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBPayDelegateAllocation.sol';\\nimport './../structs/JBRedemptionDelegateAllocation.sol';\\nimport './../structs/JBTokenAmount.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBPrices.sol';\\nimport './IJBSingleTokenPaymentTerminal.sol';\\n\\ninterface IJBSingleTokenPaymentTerminalStore {\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function prices() external view returns (IJBPrices);\\n\\n function balanceOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\\n external\\n view\\n returns (uint256);\\n\\n function usedDistributionLimitOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _fundingCycleNumber\\n ) external view returns (uint256);\\n\\n function usedOverflowAllowanceOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _fundingCycleConfiguration\\n ) external view returns (uint256);\\n\\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\\n external\\n view\\n returns (uint256);\\n\\n function currentTotalOverflowOf(\\n uint256 _projectId,\\n uint256 _decimals,\\n uint256 _currency\\n ) external view returns (uint256);\\n\\n function currentReclaimableOverflowOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n bool _useTotalOverflow\\n ) external view returns (uint256);\\n\\n function currentReclaimableOverflowOf(\\n uint256 _projectId,\\n uint256 _tokenCount,\\n uint256 _totalSupply,\\n uint256 _overflow\\n ) external view returns (uint256);\\n\\n function recordPaymentFrom(\\n address _payer,\\n JBTokenAmount memory _amount,\\n uint256 _projectId,\\n uint256 _baseWeightCurrency,\\n address _beneficiary,\\n string calldata _memo,\\n bytes calldata _metadata\\n )\\n external\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 tokenCount,\\n JBPayDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n );\\n\\n function recordRedemptionFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n string calldata _memo,\\n bytes calldata _metadata\\n )\\n external\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 reclaimAmount,\\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n );\\n\\n function recordDistributionFor(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n ) external returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount);\\n\\n function recordUsedAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n ) external returns (JBFundingCycle memory fundingCycle, uint256 withdrawnAmount);\\n\\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external;\\n\\n function recordMigration(uint256 _projectId) external returns (uint256 balance);\\n}\\n\",\"keccak256\":\"0xd78929c9371fd7895b829ef5e4ad4b3786523c3580ac3f6f5f25d2b5941c0dd3\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSplitAllocator.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport '../structs/JBSplitAllocationData.sol';\\n\\n/**\\n @title\\n Split allocator\\n\\n @notice\\n Provide a way to process a single split with extra logic\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n\\n @dev\\n The contract address should be set as an allocator in the adequate split\\n*/\\ninterface IJBSplitAllocator is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.distributePayoutOf(..), during the processing of the split including it\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control. The token and/or eth are optimistically transfered\\n to the allocator for its logic.\\n \\n @param _data the data passed by the terminal, as a JBSplitAllocationData struct:\\n address token;\\n uint256 amount;\\n uint256 decimals;\\n uint256 projectId;\\n uint256 group;\\n JBSplit split;\\n */\\n function allocate(JBSplitAllocationData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0x5efb6f51fc161f42ff58989386ad99028e4039a0ba897d66f358c3dfcf686105\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSplitsStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBGroupedSplits.sol';\\nimport './../structs/JBSplit.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBProjects.sol';\\n\\ninterface IJBSplitsStore {\\n event SetSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n address caller\\n );\\n\\n function projects() external view returns (IJBProjects);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function splitsOf(\\n uint256 _projectId,\\n uint256 _domain,\\n uint256 _group\\n ) external view returns (JBSplit[] memory);\\n\\n function set(\\n uint256 _projectId,\\n uint256 _domain,\\n JBGroupedSplits[] memory _groupedSplits\\n ) external;\\n}\\n\",\"keccak256\":\"0x66dab3dd394e318b850401ca92c2963b906cc0ad5562fa5d4f6f850175d1c77a\",\"license\":\"MIT\"},\"contracts/interfaces/IJBToken.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBToken {\\n function projectId() external view returns (uint256);\\n\\n function decimals() external view returns (uint8);\\n\\n function totalSupply(uint256 _projectId) external view returns (uint256);\\n\\n function balanceOf(address _account, uint256 _projectId) external view returns (uint256);\\n\\n function mint(\\n uint256 _projectId,\\n address _account,\\n uint256 _amount\\n ) external;\\n\\n function burn(\\n uint256 _projectId,\\n address _account,\\n uint256 _amount\\n ) external;\\n\\n function approve(\\n uint256,\\n address _spender,\\n uint256 _amount\\n ) external;\\n\\n function transfer(\\n uint256 _projectId,\\n address _to,\\n uint256 _amount\\n ) external;\\n\\n function transferFrom(\\n uint256 _projectId,\\n address _from,\\n address _to,\\n uint256 _amount\\n ) external;\\n}\\n\",\"keccak256\":\"0xe8969210417736c85d71101bf1c0bd8ebbf9d1e62a93e758148bd5709a6c7097\",\"license\":\"MIT\"},\"contracts/interfaces/IJBTokenStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBProjects.sol';\\nimport './IJBToken.sol';\\n\\ninterface IJBTokenStore {\\n event Issue(\\n uint256 indexed projectId,\\n IJBToken indexed token,\\n string name,\\n string symbol,\\n address caller\\n );\\n\\n event Mint(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 amount,\\n bool tokensWereClaimed,\\n bool preferClaimedTokens,\\n address caller\\n );\\n\\n event Burn(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 amount,\\n uint256 initialUnclaimedBalance,\\n uint256 initialClaimedBalance,\\n bool preferClaimedTokens,\\n address caller\\n );\\n\\n event Claim(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 initialUnclaimedBalance,\\n uint256 amount,\\n address caller\\n );\\n\\n event Set(uint256 indexed projectId, IJBToken indexed newToken, address caller);\\n\\n event Transfer(\\n address indexed holder,\\n uint256 indexed projectId,\\n address indexed recipient,\\n uint256 amount,\\n address caller\\n );\\n\\n function tokenOf(uint256 _projectId) external view returns (IJBToken);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function unclaimedBalanceOf(address _holder, uint256 _projectId) external view returns (uint256);\\n\\n function unclaimedTotalSupplyOf(uint256 _projectId) external view returns (uint256);\\n\\n function totalSupplyOf(uint256 _projectId) external view returns (uint256);\\n\\n function balanceOf(address _holder, uint256 _projectId) external view returns (uint256 _result);\\n\\n function issueFor(\\n uint256 _projectId,\\n string calldata _name,\\n string calldata _symbol\\n ) external returns (IJBToken token);\\n\\n function setFor(uint256 _projectId, IJBToken _token) external;\\n\\n function burnFrom(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function mintFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function claimFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount\\n ) external;\\n\\n function transferFrom(\\n address _holder,\\n uint256 _projectId,\\n address _recipient,\\n uint256 _amount\\n ) external;\\n}\\n\",\"keccak256\":\"0x98459e3af050d41dfeffdc97f1c93330207ba450f8ff3613224b49a89eeca9c6\",\"license\":\"MIT\"},\"contracts/interfaces/IJBTokenUriResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBTokenUriResolver {\\n function getUri(uint256 _projectId) external view returns (string memory tokenUri);\\n}\\n\",\"keccak256\":\"0xd267fd8ca7c21c2c71794acdb9a98314c33a35fc559e0bf0897a6686d196d174\",\"license\":\"MIT\"},\"contracts/libraries/JBConstants.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/**\\n @notice\\n Global constants used across Juicebox contracts.\\n*/\\nlibrary JBConstants {\\n uint256 public constant MAX_RESERVED_RATE = 10_000;\\n uint256 public constant MAX_REDEMPTION_RATE = 10_000;\\n uint256 public constant MAX_DISCOUNT_RATE = 1_000_000_000;\\n uint256 public constant SPLITS_TOTAL_PERCENT = 1_000_000_000;\\n uint256 public constant MAX_FEE = 1_000_000_000;\\n uint256 public constant MAX_FEE_DISCOUNT = 1_000_000_000;\\n}\\n\",\"keccak256\":\"0x34362846a1cd428a8bdedf4ab6857e11402f345cb87b994b2e7fb6d2474b808d\",\"license\":\"MIT\"},\"contracts/libraries/JBCurrencies.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBCurrencies {\\n uint256 public constant ETH = 1;\\n uint256 public constant USD = 2;\\n}\\n\",\"keccak256\":\"0x7e417ff25c173608ee4fe6d9fc3dcd5e1458c78c889af12bac47b1189a436076\",\"license\":\"MIT\"},\"contracts/libraries/JBFixedPointNumber.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nlibrary JBFixedPointNumber {\\n function adjustDecimals(\\n uint256 _value,\\n uint256 _decimals,\\n uint256 _targetDecimals\\n ) internal pure returns (uint256) {\\n // If decimals need adjusting, multiply or divide the price by the decimal adjuster to get the normalized result.\\n if (_targetDecimals == _decimals) return _value;\\n else if (_targetDecimals > _decimals) return _value * 10**(_targetDecimals - _decimals);\\n else return _value / 10**(_decimals - _targetDecimals);\\n }\\n}\\n\",\"keccak256\":\"0x18efac48269f3a3bd7e9a1c770776f950e0afa86769e6f8b128002c3b8c6742c\",\"license\":\"MIT\"},\"contracts/libraries/JBFundingCycleMetadataResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBFundingCycleMetadata.sol';\\nimport './../structs/JBGlobalFundingCycleMetadata.sol';\\nimport './JBConstants.sol';\\nimport './JBGlobalFundingCycleMetadataResolver.sol';\\n\\nlibrary JBFundingCycleMetadataResolver {\\n function global(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (JBGlobalFundingCycleMetadata memory)\\n {\\n return JBGlobalFundingCycleMetadataResolver.expandMetadata(uint8(_fundingCycle.metadata >> 8));\\n }\\n\\n function reservedRate(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n return uint256(uint16(_fundingCycle.metadata >> 24));\\n }\\n\\n function redemptionRate(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n // Redemption rate is a number 0-10000. It's inverse was stored so the most common case of 100% results in no storage needs.\\n return JBConstants.MAX_REDEMPTION_RATE - uint256(uint16(_fundingCycle.metadata >> 40));\\n }\\n\\n function ballotRedemptionRate(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (uint256)\\n {\\n // Redemption rate is a number 0-10000. It's inverse was stored so the most common case of 100% results in no storage needs.\\n return JBConstants.MAX_REDEMPTION_RATE - uint256(uint16(_fundingCycle.metadata >> 56));\\n }\\n\\n function payPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 72) & 1) == 1;\\n }\\n\\n function distributionsPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 73) & 1) == 1;\\n }\\n\\n function redeemPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 74) & 1) == 1;\\n }\\n\\n function burnPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 75) & 1) == 1;\\n }\\n\\n function mintingAllowed(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 76) & 1) == 1;\\n }\\n\\n function terminalMigrationAllowed(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 77) & 1) == 1;\\n }\\n\\n function controllerMigrationAllowed(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 78) & 1) == 1;\\n }\\n\\n function shouldHoldFees(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 79) & 1) == 1;\\n }\\n\\n function preferClaimedTokenOverride(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 80) & 1) == 1;\\n }\\n\\n function useTotalOverflowForRedemptions(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 81) & 1) == 1;\\n }\\n\\n function useDataSourceForPay(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return (_fundingCycle.metadata >> 82) & 1 == 1;\\n }\\n\\n function useDataSourceForRedeem(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return (_fundingCycle.metadata >> 83) & 1 == 1;\\n }\\n\\n function dataSource(JBFundingCycle memory _fundingCycle) internal pure returns (address) {\\n return address(uint160(_fundingCycle.metadata >> 84));\\n }\\n\\n function metadata(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n return uint256(uint8(_fundingCycle.metadata >> 244));\\n }\\n\\n /**\\n @notice\\n Pack the funding cycle metadata.\\n\\n @param _metadata The metadata to validate and pack.\\n\\n @return packed The packed uint256 of all metadata params. The first 8 bits specify the version.\\n */\\n function packFundingCycleMetadata(JBFundingCycleMetadata memory _metadata)\\n internal\\n pure\\n returns (uint256 packed)\\n {\\n // version 1 in the bits 0-7 (8 bits).\\n packed = 1;\\n // global metadta in bits 8-23 (16 bits).\\n packed |=\\n JBGlobalFundingCycleMetadataResolver.packFundingCycleGlobalMetadata(_metadata.global) <<\\n 8;\\n // reserved rate in bits 24-39 (16 bits).\\n packed |= _metadata.reservedRate << 24;\\n // redemption rate in bits 40-55 (16 bits).\\n // redemption rate is a number 0-10000. Store the reverse so the most common case of 100% results in no storage needs.\\n packed |= (JBConstants.MAX_REDEMPTION_RATE - _metadata.redemptionRate) << 40;\\n // ballot redemption rate rate in bits 56-71 (16 bits).\\n // ballot redemption rate is a number 0-10000. Store the reverse so the most common case of 100% results in no storage needs.\\n packed |= (JBConstants.MAX_REDEMPTION_RATE - _metadata.ballotRedemptionRate) << 56;\\n // pause pay in bit 72.\\n if (_metadata.pausePay) packed |= 1 << 72;\\n // pause tap in bit 73.\\n if (_metadata.pauseDistributions) packed |= 1 << 73;\\n // pause redeem in bit 74.\\n if (_metadata.pauseRedeem) packed |= 1 << 74;\\n // pause burn in bit 75.\\n if (_metadata.pauseBurn) packed |= 1 << 75;\\n // allow minting in bit 76.\\n if (_metadata.allowMinting) packed |= 1 << 76;\\n // allow terminal migration in bit 77.\\n if (_metadata.allowTerminalMigration) packed |= 1 << 77;\\n // allow controller migration in bit 78.\\n if (_metadata.allowControllerMigration) packed |= 1 << 78;\\n // hold fees in bit 79.\\n if (_metadata.holdFees) packed |= 1 << 79;\\n // prefer claimed token override in bit 80.\\n if (_metadata.preferClaimedTokenOverride) packed |= 1 << 80;\\n // useTotalOverflowForRedemptions in bit 81.\\n if (_metadata.useTotalOverflowForRedemptions) packed |= 1 << 81;\\n // use pay data source in bit 82.\\n if (_metadata.useDataSourceForPay) packed |= 1 << 82;\\n // use redeem data source in bit 83.\\n if (_metadata.useDataSourceForRedeem) packed |= 1 << 83;\\n // data source address in bits 84-243.\\n packed |= uint256(uint160(address(_metadata.dataSource))) << 84;\\n // metadata in bits 244-252 (8 bits).\\n packed |= _metadata.metadata << 244;\\n }\\n\\n /**\\n @notice\\n Expand the funding cycle metadata.\\n\\n @param _fundingCycle The funding cycle having its metadata expanded.\\n\\n @return metadata The metadata object.\\n */\\n function expandMetadata(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (JBFundingCycleMetadata memory)\\n {\\n return\\n JBFundingCycleMetadata(\\n global(_fundingCycle),\\n reservedRate(_fundingCycle),\\n redemptionRate(_fundingCycle),\\n ballotRedemptionRate(_fundingCycle),\\n payPaused(_fundingCycle),\\n distributionsPaused(_fundingCycle),\\n redeemPaused(_fundingCycle),\\n burnPaused(_fundingCycle),\\n mintingAllowed(_fundingCycle),\\n terminalMigrationAllowed(_fundingCycle),\\n controllerMigrationAllowed(_fundingCycle),\\n shouldHoldFees(_fundingCycle),\\n preferClaimedTokenOverride(_fundingCycle),\\n useTotalOverflowForRedemptions(_fundingCycle),\\n useDataSourceForPay(_fundingCycle),\\n useDataSourceForRedeem(_fundingCycle),\\n dataSource(_fundingCycle),\\n metadata(_fundingCycle)\\n );\\n }\\n}\\n\",\"keccak256\":\"0x3d045c38593102cfb6ac67f3ddf2232e1ff5518d6d021423ae2681387599fbd3\",\"license\":\"MIT\"},\"contracts/libraries/JBGlobalFundingCycleMetadataResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport './../structs/JBFundingCycleMetadata.sol';\\n\\nlibrary JBGlobalFundingCycleMetadataResolver {\\n function setTerminalsAllowed(uint8 _data) internal pure returns (bool) {\\n return (_data & 1) == 1;\\n }\\n\\n function setControllerAllowed(uint8 _data) internal pure returns (bool) {\\n return ((_data >> 1) & 1) == 1;\\n }\\n\\n function transfersPaused(uint8 _data) internal pure returns (bool) {\\n return ((_data >> 2) & 1) == 1;\\n }\\n\\n /**\\n @notice\\n Pack the global funding cycle metadata.\\n\\n @param _metadata The metadata to validate and pack.\\n\\n @return packed The packed uint256 of all global metadata params. The first 8 bits specify the version.\\n */\\n function packFundingCycleGlobalMetadata(JBGlobalFundingCycleMetadata memory _metadata)\\n internal\\n pure\\n returns (uint256 packed)\\n {\\n // allow set terminals in bit 0.\\n if (_metadata.allowSetTerminals) packed |= 1;\\n // allow set controller in bit 1.\\n if (_metadata.allowSetController) packed |= 1 << 1;\\n // pause transfers in bit 2.\\n if (_metadata.pauseTransfers) packed |= 1 << 2;\\n }\\n\\n /**\\n @notice\\n Expand the global funding cycle metadata.\\n\\n @param _packedMetadata The packed metadata to expand.\\n\\n @return metadata The global metadata object.\\n */\\n function expandMetadata(uint8 _packedMetadata)\\n internal\\n pure\\n returns (JBGlobalFundingCycleMetadata memory metadata)\\n {\\n return\\n JBGlobalFundingCycleMetadata(\\n setTerminalsAllowed(_packedMetadata),\\n setControllerAllowed(_packedMetadata),\\n transfersPaused(_packedMetadata)\\n );\\n }\\n}\\n\",\"keccak256\":\"0x0d998f938026edeb755987a79421267cf860801161b5f171206a200b60f1061f\",\"license\":\"MIT\"},\"contracts/structs/JBDidPayData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member payer The address from which the payment originated.\\n @member projectId The ID of the project for which the payment was made.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the payment is being made.\\n @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.\\n @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.\\n @member projectTokenCount The number of project tokens minted for the beneficiary.\\n @member beneficiary The address to which the tokens were minted.\\n @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.\\n @member memo The memo that is being emitted alongside the payment.\\n @member metadata Extra data to send to the delegate.\\n*/\\nstruct JBDidPayData {\\n address payer;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n JBTokenAmount amount;\\n JBTokenAmount forwardedAmount;\\n uint256 projectTokenCount;\\n address beneficiary;\\n bool preferClaimedTokens;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0xf3c664309b37790f16047ae97b0459889ae0242dfcde7fc8902c8d10c7f8e6b6\",\"license\":\"MIT\"},\"contracts/structs/JBDidRedeemData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member holder The holder of the tokens being redeemed.\\n @member projectId The ID of the project with which the redeemed tokens are associated.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the redemption is being made.\\n @member projectTokenCount The number of project tokens being redeemed.\\n @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.\\n @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.\\n @member beneficiary The address to which the reclaimed amount will be sent.\\n @member memo The memo that is being emitted alongside the redemption.\\n @member metadata Extra data to send to the delegate.\\n*/\\nstruct JBDidRedeemData {\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 projectTokenCount;\\n JBTokenAmount reclaimedAmount;\\n JBTokenAmount forwardedAmount;\\n address payable beneficiary;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0xe2c401f39723a7ce915b8bef328744c66daaf57460843964b941456c2258a412\",\"license\":\"MIT\"},\"contracts/structs/JBFundAccessConstraints.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBPaymentTerminal.sol';\\n\\n/** \\n @member terminal The terminal within which the distribution limit and the overflow allowance applies.\\n @member token The token for which the fund access constraints apply.\\n @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.\\n @member distributionLimitCurrency The currency of the distribution limit.\\n @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.\\n @member overflowAllowanceCurrency The currency of the overflow allowance.\\n*/\\nstruct JBFundAccessConstraints {\\n IJBPaymentTerminal terminal;\\n address token;\\n uint256 distributionLimit;\\n uint256 distributionLimitCurrency;\\n uint256 overflowAllowance;\\n uint256 overflowAllowanceCurrency;\\n}\\n\",\"keccak256\":\"0x85ebaa57b788cbdedc7a3d0eec4892eda5d79db7c1a6103797f10d0d989775b2\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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.\\n @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.\\n @member basedOn The `configuration` of the funding cycle that was active when this cycle was created.\\n @member start The timestamp marking the moment from which the funding cycle is considered active. It is a unix timestamp measured in seconds.\\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n @member metadata Extra data that can be associated with a funding cycle.\\n*/\\nstruct JBFundingCycle {\\n uint256 number;\\n uint256 configuration;\\n uint256 basedOn;\\n uint256 start;\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n uint256 metadata;\\n}\\n\",\"keccak256\":\"0xcdd3ac9b6fa67e62ada88d09b73bc35ade1cd77d43db712289266a788928b4c2\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycleData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n*/\\nstruct JBFundingCycleData {\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n}\\n\",\"keccak256\":\"0x2aa6368bf4dfc5797e8b02a978293de0c777fae2658de2c825a103587240f3b0\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycleMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBGlobalFundingCycleMetadata.sol';\\n\\n/** \\n @member global Data used globally in non-migratable ecosystem contracts.\\n @member reservedRate The reserved rate of the funding cycle. This number is a percentage calculated out of `JBConstants.MAX_RESERVED_RATE`.\\n @member redemptionRate The redemption rate of the funding cycle. This number is a percentage calculated out of `JBConstants.MAX_REDEMPTION_RATE`.\\n @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`.\\n @member pausePay A flag indicating if the pay functionality should be paused during the funding cycle.\\n @member pauseDistributions A flag indicating if the distribute functionality should be paused during the funding cycle.\\n @member pauseRedeem A flag indicating if the redeem functionality should be paused during the funding cycle.\\n @member pauseBurn A flag indicating if the burn functionality should be paused during the funding cycle.\\n @member allowMinting A flag indicating if minting tokens should be allowed during this funding cycle.\\n @member allowTerminalMigration A flag indicating if migrating terminals should be allowed during this funding cycle.\\n @member allowControllerMigration A flag indicating if migrating controllers should be allowed during this funding cycle.\\n @member holdFees A flag indicating if fees should be held during this funding cycle.\\n @member preferClaimedTokenOverride A flag indicating if claimed tokens should always be prefered to unclaimed tokens when minting.\\n @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.\\n @member useDataSourceForPay A flag indicating if the data source should be used for pay transactions during this funding cycle.\\n @member useDataSourceForRedeem A flag indicating if the data source should be used for redeem transactions during this funding cycle.\\n @member dataSource The data source to use during this funding cycle.\\n @member metadata Metadata of the metadata, up to uint8 in size.\\n*/\\nstruct JBFundingCycleMetadata {\\n JBGlobalFundingCycleMetadata global;\\n uint256 reservedRate;\\n uint256 redemptionRate;\\n uint256 ballotRedemptionRate;\\n bool pausePay;\\n bool pauseDistributions;\\n bool pauseRedeem;\\n bool pauseBurn;\\n bool allowMinting;\\n bool allowTerminalMigration;\\n bool allowControllerMigration;\\n bool holdFees;\\n bool preferClaimedTokenOverride;\\n bool useTotalOverflowForRedemptions;\\n bool useDataSourceForPay;\\n bool useDataSourceForRedeem;\\n address dataSource;\\n uint256 metadata;\\n}\\n\",\"keccak256\":\"0x783604440cac8d176332eab28166f188ee5c230378c08cfc95fea4f7187dc77d\",\"license\":\"MIT\"},\"contracts/structs/JBGlobalFundingCycleMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member allowSetTerminals A flag indicating if setting terminals should be allowed during this funding cycle.\\n @member allowSetController A flag indicating if setting a new controller should be allowed during this funding cycle.\\n @member pauseTransfers A flag indicating if the project token transfer functionality should be paused during the funding cycle.\\n*/\\nstruct JBGlobalFundingCycleMetadata {\\n bool allowSetTerminals;\\n bool allowSetController;\\n bool pauseTransfers;\\n}\\n\",\"keccak256\":\"0x05d85530305fec6d6eca54cdbc2cd9110cbda0146598032b0203aa4b622944ff\",\"license\":\"MIT\"},\"contracts/structs/JBGroupedSplits.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBSplit.sol';\\n\\n/** \\n @member group The group indentifier.\\n @member splits The splits to associate with the group.\\n*/\\nstruct JBGroupedSplits {\\n uint256 group;\\n JBSplit[] splits;\\n}\\n\",\"keccak256\":\"0x80be1b220da4ac04851ea540ebb94c1ec2b0442ec5bd1e88fdf78a56becd8b5a\",\"license\":\"MIT\"},\"contracts/structs/JBPayDelegateAllocation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '../interfaces/IJBPayDelegate.sol';\\n\\n/** \\n @member delegate A delegate contract to use for subsequent calls.\\n @member amount The amount to send to the delegate.\\n*/\\nstruct JBPayDelegateAllocation {\\n IJBPayDelegate delegate;\\n uint256 amount;\\n}\\n\",\"keccak256\":\"0xb4e558dc62231d89e9b48998012577d22c3e52b58e23401f22d9096827f6ea0c\",\"license\":\"MIT\"},\"contracts/structs/JBPayParamsData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBPaymentTerminal.sol';\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member terminal The terminal that is facilitating the payment.\\n @member payer The address from which the payment originated.\\n @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.\\n @member projectId The ID of the project being paid.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the payment is being made.\\n @member beneficiary The specified address that should be the beneficiary of anything that results from the payment.\\n @member weight The weight of the funding cycle during which the payment is being made.\\n @member reservedRate The reserved rate of the funding cycle during which the payment is being made.\\n @member memo The memo that was sent alongside the payment.\\n @member metadata Extra data provided by the payer.\\n*/\\nstruct JBPayParamsData {\\n IJBPaymentTerminal terminal;\\n address payer;\\n JBTokenAmount amount;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n address beneficiary;\\n uint256 weight;\\n uint256 reservedRate;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0x05007b26feb5d9a026b883c6d734a341b5a49ef7b8215fb40507882e2c14e24d\",\"license\":\"MIT\"},\"contracts/structs/JBProjectMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member content The metadata content.\\n @member domain The domain within which the metadata applies.\\n*/\\nstruct JBProjectMetadata {\\n string content;\\n uint256 domain;\\n}\\n\",\"keccak256\":\"0x90ad7b1014c0a9f945fe7a2efde9d5de41e40574fa27969070b1d2ff52033ea0\",\"license\":\"MIT\"},\"contracts/structs/JBRedeemParamsData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBPaymentTerminal.sol';\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member terminal The terminal that is facilitating the redemption.\\n @member holder The holder of the tokens being redeemed.\\n @member projectId The ID of the project whos tokens are being redeemed.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the redemption is being made.\\n @member tokenCount The proposed number of tokens being redeemed, as a fixed point number with 18 decimals.\\n @member totalSupply The total supply of tokens used in the calculation, as a fixed point number with 18 decimals.\\n @member overflow The amount of overflow used in the reclaim amount calculation.\\n @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.\\n @member useTotalOverflow If overflow across all of a project's terminals is being used when making redemptions.\\n @member redemptionRate The redemption rate of the funding cycle during which the redemption is being made.\\n @member memo The proposed memo that is being emitted alongside the redemption.\\n @member metadata Extra data provided by the redeemer.\\n*/\\nstruct JBRedeemParamsData {\\n IJBPaymentTerminal terminal;\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 tokenCount;\\n uint256 totalSupply;\\n uint256 overflow;\\n JBTokenAmount reclaimAmount;\\n bool useTotalOverflow;\\n uint256 redemptionRate;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0x5065a824ebb34952f016c6dfa47e8a7ac28427b719470e74a41022c11ace7788\",\"license\":\"MIT\"},\"contracts/structs/JBRedemptionDelegateAllocation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '../interfaces/IJBRedemptionDelegate.sol';\\n\\n/** \\n @member delegate A delegate contract to use for subsequent calls.\\n @member amount The amount to send to the delegate.\\n*/\\nstruct JBRedemptionDelegateAllocation {\\n IJBRedemptionDelegate delegate;\\n uint256 amount;\\n}\\n\",\"keccak256\":\"0x10c29d33dd0d875a0d4692a2b9a9355c2ebf433cc06a9a60253d4366b60d4d31\",\"license\":\"MIT\"},\"contracts/structs/JBSplit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBSplitAllocator.sol';\\n\\n/** \\n @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.\\n @member preferAddToBalance A flag indicating if a distribution to a project should prefer triggering it's addToBalance function instead of its pay function.\\n @member percent The percent of the whole group that this split occupies. This number is out of `JBConstants.SPLITS_TOTAL_PERCENT`.\\n @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.\\n @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.\\n @member lockedUntil Specifies if the split should be unchangeable until the specified time, with the exception of extending the locked period.\\n @member allocator If an allocator is specified, funds will be sent to the allocator contract along with all properties of this split.\\n*/\\nstruct JBSplit {\\n bool preferClaimed;\\n bool preferAddToBalance;\\n uint256 percent;\\n uint256 projectId;\\n address payable beneficiary;\\n uint256 lockedUntil;\\n IJBSplitAllocator allocator;\\n}\\n\",\"keccak256\":\"0xc80a16606da8abf76d0f73abc38aee041e24f29342c1939018f70c286e89f105\",\"license\":\"MIT\"},\"contracts/structs/JBSplitAllocationData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBSplit.sol';\\n\\n/** \\n @member token The token being sent to the split allocator.\\n @member amount The amount being sent to the split allocator, as a fixed point number.\\n @member decimals The number of decimals in the amount.\\n @member projectId The project to which the split belongs.\\n @member group The group to which the split belongs.\\n @member split The split that caused the allocation.\\n*/\\nstruct JBSplitAllocationData {\\n address token;\\n uint256 amount;\\n uint256 decimals;\\n uint256 projectId;\\n uint256 group;\\n JBSplit split;\\n}\\n\",\"keccak256\":\"0x39f5c41bd31d36774744698ac94484b6cab62d7038df2f29d947668959782e63\",\"license\":\"MIT\"},\"contracts/structs/JBTokenAmount.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/* \\n @member token The token the payment was made in.\\n @member value The amount of tokens that was paid, as a fixed point number.\\n @member decimals The number of decimals included in the value fixed point number.\\n @member currency The expected currency of the value.\\n**/\\nstruct JBTokenAmount {\\n address token;\\n uint256 value;\\n uint256 decimals;\\n uint256 currency;\\n}\\n\",\"keccak256\":\"0x4a778e779ba257ba5638c5469e07a4d21b55a3128d56db5a0fdfacb1f3301c51\",\"license\":\"MIT\"},\"prb-math/contracts/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivFixedPointOverflow(uint256 prod1);\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivOverflow(uint256 prod1, uint256 denominator);\\n\\n/// @notice Emitted when one of the inputs is type(int256).min.\\nerror PRBMath__MulDivSignedInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows int256.\\nerror PRBMath__MulDivSignedOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is MIN_SD59x18.\\nerror PRBMathSD59x18__AbsInputTooSmall();\\n\\n/// @notice Emitted when ceiling a number overflows SD59x18.\\nerror PRBMathSD59x18__CeilOverflow(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__DivInputTooSmall();\\n\\n/// @notice Emitted when one of the intermediary unsigned results overflows SD59x18.\\nerror PRBMathSD59x18__DivOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathSD59x18__ExpInputTooBig(int256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathSD59x18__Exp2InputTooBig(int256 x);\\n\\n/// @notice Emitted when flooring a number underflows SD59x18.\\nerror PRBMathSD59x18__FloorUnderflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format overflows SD59x18.\\nerror PRBMathSD59x18__FromIntOverflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format underflows SD59x18.\\nerror PRBMathSD59x18__FromIntUnderflow(int256 x);\\n\\n/// @notice Emitted when the product of the inputs is negative.\\nerror PRBMathSD59x18__GmNegativeProduct(int256 x, int256 y);\\n\\n/// @notice Emitted when multiplying the inputs overflows SD59x18.\\nerror PRBMathSD59x18__GmOverflow(int256 x, int256 y);\\n\\n/// @notice Emitted when the input is less than or equal to zero.\\nerror PRBMathSD59x18__LogInputTooSmall(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__MulInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__MulOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__PowuOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is negative.\\nerror PRBMathSD59x18__SqrtNegativeInput(int256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows SD59x18.\\nerror PRBMathSD59x18__SqrtOverflow(int256 x);\\n\\n/// @notice Emitted when addition overflows UD60x18.\\nerror PRBMathUD60x18__AddOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when ceiling a number overflows UD60x18.\\nerror PRBMathUD60x18__CeilOverflow(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathUD60x18__ExpInputTooBig(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathUD60x18__Exp2InputTooBig(uint256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format format overflows UD60x18.\\nerror PRBMathUD60x18__FromUintOverflow(uint256 x);\\n\\n/// @notice Emitted when multiplying the inputs overflows UD60x18.\\nerror PRBMathUD60x18__GmOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when the input is less than 1.\\nerror PRBMathUD60x18__LogInputTooSmall(uint256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows UD60x18.\\nerror PRBMathUD60x18__SqrtOverflow(uint256 x);\\n\\n/// @notice Emitted when subtraction underflows UD60x18.\\nerror PRBMathUD60x18__SubUnderflow(uint256 x, uint256 y);\\n\\n/// @dev Common mathematical functions used in both PRBMathSD59x18 and PRBMathUD60x18. Note that this shared library\\n/// does not always assume the signed 59.18-decimal fixed-point or the unsigned 60.18-decimal fixed-point\\n/// representation. When it does not, it is explicitly mentioned in the NatSpec documentation.\\nlibrary PRBMath {\\n /// STRUCTS ///\\n\\n struct SD59x18 {\\n int256 value;\\n }\\n\\n struct UD60x18 {\\n uint256 value;\\n }\\n\\n /// STORAGE ///\\n\\n /// @dev How many trailing decimals can be represented.\\n uint256 internal constant SCALE = 1e18;\\n\\n /// @dev Largest power of two divisor of SCALE.\\n uint256 internal constant SCALE_LPOTD = 262144;\\n\\n /// @dev SCALE inverted mod 2^256.\\n uint256 internal constant SCALE_INVERSE =\\n 78156646155174841979727994598816262306175212592076161876661_508869554232690281;\\n\\n /// FUNCTIONS ///\\n\\n /// @notice Calculates the binary exponent of x using the binary fraction method.\\n /// @dev Has to use 192.64-bit fixed-point numbers.\\n /// See https://ethereum.stackexchange.com/a/96594/24693.\\n /// @param x The exponent as an unsigned 192.64-bit fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp2(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n // Start from 0.5 in the 192.64-bit fixed-point format.\\n result = 0x800000000000000000000000000000000000000000000000;\\n\\n // Multiply the result by root(2, 2^-i) when the bit at position i is 1. None of the intermediary results overflows\\n // because the initial result is 2^191 and all magic factors are less than 2^65.\\n if (x & 0x8000000000000000 > 0) {\\n result = (result * 0x16A09E667F3BCC909) >> 64;\\n }\\n if (x & 0x4000000000000000 > 0) {\\n result = (result * 0x1306FE0A31B7152DF) >> 64;\\n }\\n if (x & 0x2000000000000000 > 0) {\\n result = (result * 0x1172B83C7D517ADCE) >> 64;\\n }\\n if (x & 0x1000000000000000 > 0) {\\n result = (result * 0x10B5586CF9890F62A) >> 64;\\n }\\n if (x & 0x800000000000000 > 0) {\\n result = (result * 0x1059B0D31585743AE) >> 64;\\n }\\n if (x & 0x400000000000000 > 0) {\\n result = (result * 0x102C9A3E778060EE7) >> 64;\\n }\\n if (x & 0x200000000000000 > 0) {\\n result = (result * 0x10163DA9FB33356D8) >> 64;\\n }\\n if (x & 0x100000000000000 > 0) {\\n result = (result * 0x100B1AFA5ABCBED61) >> 64;\\n }\\n if (x & 0x80000000000000 > 0) {\\n result = (result * 0x10058C86DA1C09EA2) >> 64;\\n }\\n if (x & 0x40000000000000 > 0) {\\n result = (result * 0x1002C605E2E8CEC50) >> 64;\\n }\\n if (x & 0x20000000000000 > 0) {\\n result = (result * 0x100162F3904051FA1) >> 64;\\n }\\n if (x & 0x10000000000000 > 0) {\\n result = (result * 0x1000B175EFFDC76BA) >> 64;\\n }\\n if (x & 0x8000000000000 > 0) {\\n result = (result * 0x100058BA01FB9F96D) >> 64;\\n }\\n if (x & 0x4000000000000 > 0) {\\n result = (result * 0x10002C5CC37DA9492) >> 64;\\n }\\n if (x & 0x2000000000000 > 0) {\\n result = (result * 0x1000162E525EE0547) >> 64;\\n }\\n if (x & 0x1000000000000 > 0) {\\n result = (result * 0x10000B17255775C04) >> 64;\\n }\\n if (x & 0x800000000000 > 0) {\\n result = (result * 0x1000058B91B5BC9AE) >> 64;\\n }\\n if (x & 0x400000000000 > 0) {\\n result = (result * 0x100002C5C89D5EC6D) >> 64;\\n }\\n if (x & 0x200000000000 > 0) {\\n result = (result * 0x10000162E43F4F831) >> 64;\\n }\\n if (x & 0x100000000000 > 0) {\\n result = (result * 0x100000B1721BCFC9A) >> 64;\\n }\\n if (x & 0x80000000000 > 0) {\\n result = (result * 0x10000058B90CF1E6E) >> 64;\\n }\\n if (x & 0x40000000000 > 0) {\\n result = (result * 0x1000002C5C863B73F) >> 64;\\n }\\n if (x & 0x20000000000 > 0) {\\n result = (result * 0x100000162E430E5A2) >> 64;\\n }\\n if (x & 0x10000000000 > 0) {\\n result = (result * 0x1000000B172183551) >> 64;\\n }\\n if (x & 0x8000000000 > 0) {\\n result = (result * 0x100000058B90C0B49) >> 64;\\n }\\n if (x & 0x4000000000 > 0) {\\n result = (result * 0x10000002C5C8601CC) >> 64;\\n }\\n if (x & 0x2000000000 > 0) {\\n result = (result * 0x1000000162E42FFF0) >> 64;\\n }\\n if (x & 0x1000000000 > 0) {\\n result = (result * 0x10000000B17217FBB) >> 64;\\n }\\n if (x & 0x800000000 > 0) {\\n result = (result * 0x1000000058B90BFCE) >> 64;\\n }\\n if (x & 0x400000000 > 0) {\\n result = (result * 0x100000002C5C85FE3) >> 64;\\n }\\n if (x & 0x200000000 > 0) {\\n result = (result * 0x10000000162E42FF1) >> 64;\\n }\\n if (x & 0x100000000 > 0) {\\n result = (result * 0x100000000B17217F8) >> 64;\\n }\\n if (x & 0x80000000 > 0) {\\n result = (result * 0x10000000058B90BFC) >> 64;\\n }\\n if (x & 0x40000000 > 0) {\\n result = (result * 0x1000000002C5C85FE) >> 64;\\n }\\n if (x & 0x20000000 > 0) {\\n result = (result * 0x100000000162E42FF) >> 64;\\n }\\n if (x & 0x10000000 > 0) {\\n result = (result * 0x1000000000B17217F) >> 64;\\n }\\n if (x & 0x8000000 > 0) {\\n result = (result * 0x100000000058B90C0) >> 64;\\n }\\n if (x & 0x4000000 > 0) {\\n result = (result * 0x10000000002C5C860) >> 64;\\n }\\n if (x & 0x2000000 > 0) {\\n result = (result * 0x1000000000162E430) >> 64;\\n }\\n if (x & 0x1000000 > 0) {\\n result = (result * 0x10000000000B17218) >> 64;\\n }\\n if (x & 0x800000 > 0) {\\n result = (result * 0x1000000000058B90C) >> 64;\\n }\\n if (x & 0x400000 > 0) {\\n result = (result * 0x100000000002C5C86) >> 64;\\n }\\n if (x & 0x200000 > 0) {\\n result = (result * 0x10000000000162E43) >> 64;\\n }\\n if (x & 0x100000 > 0) {\\n result = (result * 0x100000000000B1721) >> 64;\\n }\\n if (x & 0x80000 > 0) {\\n result = (result * 0x10000000000058B91) >> 64;\\n }\\n if (x & 0x40000 > 0) {\\n result = (result * 0x1000000000002C5C8) >> 64;\\n }\\n if (x & 0x20000 > 0) {\\n result = (result * 0x100000000000162E4) >> 64;\\n }\\n if (x & 0x10000 > 0) {\\n result = (result * 0x1000000000000B172) >> 64;\\n }\\n if (x & 0x8000 > 0) {\\n result = (result * 0x100000000000058B9) >> 64;\\n }\\n if (x & 0x4000 > 0) {\\n result = (result * 0x10000000000002C5D) >> 64;\\n }\\n if (x & 0x2000 > 0) {\\n result = (result * 0x1000000000000162E) >> 64;\\n }\\n if (x & 0x1000 > 0) {\\n result = (result * 0x10000000000000B17) >> 64;\\n }\\n if (x & 0x800 > 0) {\\n result = (result * 0x1000000000000058C) >> 64;\\n }\\n if (x & 0x400 > 0) {\\n result = (result * 0x100000000000002C6) >> 64;\\n }\\n if (x & 0x200 > 0) {\\n result = (result * 0x10000000000000163) >> 64;\\n }\\n if (x & 0x100 > 0) {\\n result = (result * 0x100000000000000B1) >> 64;\\n }\\n if (x & 0x80 > 0) {\\n result = (result * 0x10000000000000059) >> 64;\\n }\\n if (x & 0x40 > 0) {\\n result = (result * 0x1000000000000002C) >> 64;\\n }\\n if (x & 0x20 > 0) {\\n result = (result * 0x10000000000000016) >> 64;\\n }\\n if (x & 0x10 > 0) {\\n result = (result * 0x1000000000000000B) >> 64;\\n }\\n if (x & 0x8 > 0) {\\n result = (result * 0x10000000000000006) >> 64;\\n }\\n if (x & 0x4 > 0) {\\n result = (result * 0x10000000000000003) >> 64;\\n }\\n if (x & 0x2 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n if (x & 0x1 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n\\n // We're doing two things at the same time:\\n //\\n // 1. Multiply the result by 2^n + 1, where \\\"2^n\\\" is the integer part and the one is added to account for\\n // the fact that we initially set the result to 0.5. This is accomplished by subtracting from 191\\n // rather than 192.\\n // 2. Convert the result to the unsigned 60.18-decimal fixed-point format.\\n //\\n // This works because 2^(191-ip) = 2^ip / 2^191, where \\\"ip\\\" is the integer part \\\"2^n\\\".\\n result *= SCALE;\\n result >>= (191 - (x >> 64));\\n }\\n }\\n\\n /// @notice Finds the zero-based index of the first one in the binary representation of x.\\n /// @dev See the note on msb in the \\\"Find First Set\\\" Wikipedia article https://en.wikipedia.org/wiki/Find_first_set\\n /// @param x The uint256 number for which to find the index of the most significant bit.\\n /// @return msb The index of the most significant bit as an uint256.\\n function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\\n if (x >= 2**128) {\\n x >>= 128;\\n msb += 128;\\n }\\n if (x >= 2**64) {\\n x >>= 64;\\n msb += 64;\\n }\\n if (x >= 2**32) {\\n x >>= 32;\\n msb += 32;\\n }\\n if (x >= 2**16) {\\n x >>= 16;\\n msb += 16;\\n }\\n if (x >= 2**8) {\\n x >>= 8;\\n msb += 8;\\n }\\n if (x >= 2**4) {\\n x >>= 4;\\n msb += 4;\\n }\\n if (x >= 2**2) {\\n x >>= 2;\\n msb += 2;\\n }\\n if (x >= 2**1) {\\n // No need to shift x any more.\\n msb += 1;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.\\n ///\\n /// Requirements:\\n /// - The denominator cannot be zero.\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The multiplicand as an uint256.\\n /// @param y The multiplier as an uint256.\\n /// @param denominator The divisor as an uint256.\\n /// @return result The result as an uint256.\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n unchecked {\\n result = prod0 / denominator;\\n }\\n return result;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n if (prod1 >= denominator) {\\n revert PRBMath__MulDivOverflow(prod1, denominator);\\n }\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n unchecked {\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 lpotdod = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by lpotdod.\\n denominator := div(denominator, lpotdod)\\n\\n // Divide [prod1 prod0] by lpotdod.\\n prod0 := div(prod0, lpotdod)\\n\\n // Flip lpotdod such that it is 2^256 / lpotdod. If lpotdod is zero, then it becomes one.\\n lpotdod := add(div(sub(0, lpotdod), lpotdod), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * lpotdod;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f71e18) with full precision.\\n ///\\n /// @dev Variant of \\\"mulDiv\\\" with constant folding, i.e. in which the denominator is always 1e18. Before returning the\\n /// final result, we add 1 if (x * y) % SCALE >= HALF_SCALE. Without this, 6.6e-19 would be truncated to 0 instead of\\n /// being rounded to 1e-18. See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717.\\n ///\\n /// Requirements:\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - The body is purposely left uncommented; see the NatSpec comments in \\\"PRBMath.mulDiv\\\" to understand how this works.\\n /// - It is assumed that the result can never be type(uint256).max when x and y solve the following two equations:\\n /// 1. x * y = type(uint256).max * SCALE\\n /// 2. (x * y) % SCALE >= SCALE / 2\\n ///\\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function mulDivFixedPoint(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n uint256 prod0;\\n uint256 prod1;\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n if (prod1 >= SCALE) {\\n revert PRBMath__MulDivFixedPointOverflow(prod1);\\n }\\n\\n uint256 remainder;\\n uint256 roundUpUnit;\\n assembly {\\n remainder := mulmod(x, y, SCALE)\\n roundUpUnit := gt(remainder, 499999999999999999)\\n }\\n\\n if (prod1 == 0) {\\n unchecked {\\n result = (prod0 / SCALE) + roundUpUnit;\\n return result;\\n }\\n }\\n\\n assembly {\\n result := add(\\n mul(\\n or(\\n div(sub(prod0, remainder), SCALE_LPOTD),\\n mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, SCALE_LPOTD), SCALE_LPOTD), 1))\\n ),\\n SCALE_INVERSE\\n ),\\n roundUpUnit\\n )\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev An extension of \\\"mulDiv\\\" for signed numbers. Works by computing the signs and the absolute values separately.\\n ///\\n /// Requirements:\\n /// - None of the inputs can be type(int256).min.\\n /// - The result must fit within int256.\\n ///\\n /// @param x The multiplicand as an int256.\\n /// @param y The multiplier as an int256.\\n /// @param denominator The divisor as an int256.\\n /// @return result The result as an int256.\\n function mulDivSigned(\\n int256 x,\\n int256 y,\\n int256 denominator\\n ) internal pure returns (int256 result) {\\n if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {\\n revert PRBMath__MulDivSignedInputTooSmall();\\n }\\n\\n // Get hold of the absolute values of x, y and the denominator.\\n uint256 ax;\\n uint256 ay;\\n uint256 ad;\\n unchecked {\\n ax = x < 0 ? uint256(-x) : uint256(x);\\n ay = y < 0 ? uint256(-y) : uint256(y);\\n ad = denominator < 0 ? uint256(-denominator) : uint256(denominator);\\n }\\n\\n // Compute the absolute value of (x*y)\\u00f7denominator. The result must fit within int256.\\n uint256 rAbs = mulDiv(ax, ay, ad);\\n if (rAbs > uint256(type(int256).max)) {\\n revert PRBMath__MulDivSignedOverflow(rAbs);\\n }\\n\\n // Get the signs of x, y and the denominator.\\n uint256 sx;\\n uint256 sy;\\n uint256 sd;\\n assembly {\\n sx := sgt(x, sub(0, 1))\\n sy := sgt(y, sub(0, 1))\\n sd := sgt(denominator, sub(0, 1))\\n }\\n\\n // XOR over sx, sy and sd. This is checking whether there are one or three negative signs in the inputs.\\n // If yes, the result should be negative.\\n result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs);\\n }\\n\\n /// @notice Calculates the square root of x, rounding down.\\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The uint256 number for which to calculate the square root.\\n /// @return result The result as an uint256.\\n function sqrt(uint256 x) internal pure returns (uint256 result) {\\n if (x == 0) {\\n return 0;\\n }\\n\\n // Set the initial guess to the closest power of two that is higher than x.\\n uint256 xAux = uint256(x);\\n result = 1;\\n if (xAux >= 0x100000000000000000000000000000000) {\\n xAux >>= 128;\\n result <<= 64;\\n }\\n if (xAux >= 0x10000000000000000) {\\n xAux >>= 64;\\n result <<= 32;\\n }\\n if (xAux >= 0x100000000) {\\n xAux >>= 32;\\n result <<= 16;\\n }\\n if (xAux >= 0x10000) {\\n xAux >>= 16;\\n result <<= 8;\\n }\\n if (xAux >= 0x100) {\\n xAux >>= 8;\\n result <<= 4;\\n }\\n if (xAux >= 0x10) {\\n xAux >>= 4;\\n result <<= 2;\\n }\\n if (xAux >= 0x8) {\\n result <<= 1;\\n }\\n\\n // The operations can never overflow because the result is max 2^127 when it enters this block.\\n unchecked {\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1; // Seven iterations should be enough\\n uint256 roundedDownResult = x / result;\\n return result >= roundedDownResult ? roundedDownResult : result;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x62cbabae4910e168e99b9c2c3e3b5c9c7ad5e7abd961dcc63b7ea3d83d8ea87e\",\"license\":\"Unlicense\"}},\"version\":1}", + "metadata": "{\"compiler\":{\"version\":\"0.8.16+commit.07a7930e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IJBDirectory\",\"name\":\"_directory\",\"type\":\"address\"},{\"internalType\":\"contract IJBFundingCycleStore\",\"name\":\"_fundingCycleStore\",\"type\":\"address\"},{\"internalType\":\"contract IJBPrices\",\"name\":\"_prices\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CURRENCY_MISMATCH\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DISTRIBUTION_AMOUNT_LIMIT_REACHED\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FUNDING_CYCLE_DISTRIBUTION_PAUSED\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FUNDING_CYCLE_PAYMENT_PAUSED\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FUNDING_CYCLE_REDEEM_PAUSED\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INADEQUATE_CONTROLLER_ALLOWANCE\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INSUFFICIENT_TOKENS\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INVALID_AMOUNT_TO_SEND_DELEGATE\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"INVALID_FUNDING_CYCLE\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"prod1\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"denominator\",\"type\":\"uint256\"}],\"name\":\"PRBMath__MulDivOverflow\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminal\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminal\",\"name\":\"_terminal\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"}],\"name\":\"currentOverflowOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_tokenCount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_totalSupply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_overflow\",\"type\":\"uint256\"}],\"name\":\"currentReclaimableOverflowOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminal\",\"name\":\"_terminal\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_tokenCount\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"_useTotalOverflow\",\"type\":\"bool\"}],\"name\":\"currentReclaimableOverflowOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_decimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_currency\",\"type\":\"uint256\"}],\"name\":\"currentTotalOverflowOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"directory\",\"outputs\":[{\"internalType\":\"contract IJBDirectory\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fundingCycleStore\",\"outputs\":[{\"internalType\":\"contract IJBFundingCycleStore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"prices\",\"outputs\":[{\"internalType\":\"contract IJBPrices\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"recordAddedBalanceFor\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_currency\",\"type\":\"uint256\"}],\"name\":\"recordDistributionFor\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"configuration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"basedOn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"discountRate\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBFundingCycleBallot\",\"name\":\"ballot\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"metadata\",\"type\":\"uint256\"}],\"internalType\":\"struct JBFundingCycle\",\"name\":\"fundingCycle\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"distributedAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"}],\"name\":\"recordMigration\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_payer\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"decimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"currency\",\"type\":\"uint256\"}],\"internalType\":\"struct JBTokenAmount\",\"name\":\"_amount\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_baseWeightCurrency\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"recordPaymentFrom\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"configuration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"basedOn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"discountRate\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBFundingCycleBallot\",\"name\":\"ballot\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"metadata\",\"type\":\"uint256\"}],\"internalType\":\"struct JBFundingCycle\",\"name\":\"fundingCycle\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"tokenCount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"contract IJBPayDelegate\",\"name\":\"delegate\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"struct JBPayDelegateAllocation[]\",\"name\":\"delegateAllocations\",\"type\":\"tuple[]\"},{\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_holder\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_tokenCount\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"_memo\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"_metadata\",\"type\":\"bytes\"}],\"name\":\"recordRedemptionFor\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"configuration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"basedOn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"discountRate\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBFundingCycleBallot\",\"name\":\"ballot\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"metadata\",\"type\":\"uint256\"}],\"internalType\":\"struct JBFundingCycle\",\"name\":\"fundingCycle\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"reclaimAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"contract IJBRedemptionDelegate\",\"name\":\"delegate\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"struct JBRedemptionDelegateAllocation[]\",\"name\":\"delegateAllocations\",\"type\":\"tuple[]\"},{\"internalType\":\"string\",\"name\":\"memo\",\"type\":\"string\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_projectId\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_currency\",\"type\":\"uint256\"}],\"name\":\"recordUsedAllowanceOf\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"number\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"configuration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"basedOn\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"start\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"weight\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"discountRate\",\"type\":\"uint256\"},{\"internalType\":\"contract IJBFundingCycleBallot\",\"name\":\"ballot\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"metadata\",\"type\":\"uint256\"}],\"internalType\":\"struct JBFundingCycle\",\"name\":\"fundingCycle\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"usedAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminal\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"usedDistributionLimitOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IJBSingleTokenPaymentTerminal\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"usedOverflowAllowanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Adheres to: IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.Inherits from - ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.This Store expects a project's controller to be an IJBController3_1. This is the only difference between this version and the original.\",\"kind\":\"dev\",\"methods\":{\"constructor\":{\"params\":{\"_directory\":\"A contract storing directories of terminals and controllers for each project.\",\"_fundingCycleStore\":\"A contract storing all funding cycle configurations.\",\"_prices\":\"A contract that exposes price feeds.\"}},\"currentOverflowOf(address,uint256)\":{\"details\":\"The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\",\"params\":{\"_projectId\":\"The ID of the project to get overflow for.\",\"_terminal\":\"The terminal for which the overflow is being calculated.\"},\"returns\":{\"_0\":\"The current amount of overflow that project has in the specified terminal.\"}},\"currentReclaimableOverflowOf(address,uint256,uint256,bool)\":{\"details\":\" If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.The current reclaimable overflow is returned in terms of the specified terminal's currency.The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\",\"params\":{\"_projectId\":\"The ID of the project to get the reclaimable overflow amount for.\",\"_terminal\":\"The terminal from which the reclaimable amount would come.\",\"_tokenCount\":\"The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\",\"_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`.\"},\"returns\":{\"_0\":\"The amount of overflowed tokens that can be reclaimed, as a fixed point number with the same number of decimals as the provided `_terminal`.\"}},\"currentReclaimableOverflowOf(uint256,uint256,uint256,uint256)\":{\"details\":\" If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\",\"params\":{\"_overflow\":\"The amount of overflow to make the calculation with, as a fixed point number.\",\"_projectId\":\"The ID of the project to get the reclaimable overflow amount for.\",\"_tokenCount\":\"The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\",\"_totalSupply\":\"The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\"},\"returns\":{\"_0\":\"The amount of overflowed tokens that can be reclaimed, as a fixed point number with the same number of decimals as the provided `_overflow`.\"}},\"currentTotalOverflowOf(uint256,uint256,uint256)\":{\"params\":{\"_currency\":\"The currency that the total overflow should be in terms of.\",\"_decimals\":\"The number of decimals that the fixed point overflow should include.\",\"_projectId\":\"The ID of the project to get total overflow for.\"},\"returns\":{\"_0\":\"The current total amount of overflow that project has across all terminals.\"}},\"recordAddedBalanceFor(uint256,uint256)\":{\"details\":\"The msg.sender must be an IJBSingleTokenPaymentTerminal. \",\"params\":{\"_amount\":\"The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\",\"_projectId\":\"The ID of the project to which the funds being added belong.\"}},\"recordDistributionFor(uint256,uint256,uint256)\":{\"details\":\"The msg.sender must be an IJBSingleTokenPaymentTerminal. \",\"params\":{\"_amount\":\"The amount to use from the distribution limit, as a fixed point number.\",\"_currency\":\"The currency of the `_amount`. This must match the project's current funding cycle's currency.\",\"_projectId\":\"The ID of the project that is having funds distributed.\"},\"returns\":{\"distributedAmount\":\"The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\",\"fundingCycle\":\"The funding cycle during which the distribution was made.\"}},\"recordMigration(uint256)\":{\"details\":\"The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\",\"params\":{\"_projectId\":\"The ID of the project being migrated.\"},\"returns\":{\"balance\":\"The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\"}},\"recordPaymentFrom(address,(address,uint256,uint256,uint256),uint256,uint256,address,string,bytes)\":{\"details\":\"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.The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\",\"params\":{\"_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.\",\"_baseWeightCurrency\":\"The currency to base token issuance on.\",\"_beneficiary\":\"The specified address that should be the beneficiary of anything that results from the payment.\",\"_memo\":\"A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\",\"_metadata\":\"Bytes to send along to the data source, if one is provided.\",\"_payer\":\"The original address that sent the payment to the terminal.\",\"_projectId\":\"The ID of the project being paid.\"},\"returns\":{\"delegateAllocations\":\"The amount to send to delegates instead of adding to the local balance.\",\"fundingCycle\":\"The project's funding cycle during which payment was made.\",\"memo\":\"A memo that should be passed along to the emitted event.\",\"tokenCount\":\"The number of project tokens that were minted, as a fixed point number with 18 decimals.\"}},\"recordRedemptionFor(address,uint256,uint256,string,bytes)\":{\"details\":\"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.The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\",\"params\":{\"_holder\":\"The account that is having its tokens redeemed.\",\"_memo\":\"A memo to pass along to the emitted event.\",\"_metadata\":\"Bytes to send along to the data source, if one is provided.\",\"_projectId\":\"The ID of the project to which the tokens being redeemed belong.\",\"_tokenCount\":\"The number of project tokens to redeem, as a fixed point number with 18 decimals.\"},\"returns\":{\"delegateAllocations\":\"The amount to send to delegates instead of sending to the beneficiary.\",\"fundingCycle\":\"The funding cycle during which the redemption was made.\",\"memo\":\"A memo that should be passed along to the emitted event.\",\"reclaimAmount\":\"The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\"}},\"recordUsedAllowanceOf(uint256,uint256,uint256)\":{\"details\":\"The msg.sender must be an IJBSingleTokenPaymentTerminal. \",\"params\":{\"_amount\":\"The amount to use from the allowance, as a fixed point number. \",\"_currency\":\"The currency of the `_amount`. Must match the currency of the overflow allowance.\",\"_projectId\":\"The ID of the project to use the allowance of.\"},\"returns\":{\"fundingCycle\":\"The funding cycle during which the overflow allowance is being used.\",\"usedAmount\":\"The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\"}}},\"stateVariables\":{\"balanceOf\":{\"details\":\"The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal. _terminal The terminal to which the balance applies. _projectId The ID of the project to get the balance of.\"},\"usedDistributionLimitOf\":{\"details\":\"Increases as projects use their preconfigured distribution limits.The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal. _terminal The terminal to which the used distribution limit applies. _projectId The ID of the project to get the used distribution limit of. _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\"},\"usedOverflowAllowanceOf\":{\"details\":\"Increases as projects use their allowance.The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal. _terminal The terminal to which the overflow allowance applies. _projectId The ID of the project to get the used overflow allowance of. _configuration The configuration of the during which the allowance was used.\"}},\"version\":1},\"userdoc\":{\"errors\":{\"PRBMath__MulDivOverflow(uint256,uint256)\":[{\"notice\":\"Emitted when the result overflows uint256.\"}]},\"kind\":\"user\",\"methods\":{\"balanceOf(address,uint256)\":{\"notice\":\"The amount of tokens that each project has for each terminal, in terms of the terminal's token.\"},\"currentOverflowOf(address,uint256)\":{\"notice\":\"Gets the current overflowed amount in a terminal for a specified project.\"},\"currentReclaimableOverflowOf(address,uint256,uint256,bool)\":{\"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.\"},\"currentReclaimableOverflowOf(uint256,uint256,uint256,uint256)\":{\"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.\"},\"currentTotalOverflowOf(uint256,uint256,uint256)\":{\"notice\":\"Gets the current overflowed amount for a specified project across all terminals.\"},\"directory()\":{\"notice\":\"The directory of terminals and controllers for projects.\"},\"fundingCycleStore()\":{\"notice\":\"The contract storing all funding cycle configurations.\"},\"prices()\":{\"notice\":\"The contract that exposes price feeds.\"},\"recordAddedBalanceFor(uint256,uint256)\":{\"notice\":\"Records newly added funds for the project.\"},\"recordDistributionFor(uint256,uint256,uint256)\":{\"notice\":\"Records newly distributed funds for a project.\"},\"recordMigration(uint256)\":{\"notice\":\"Records the migration of funds from this store.\"},\"recordPaymentFrom(address,(address,uint256,uint256,uint256),uint256,uint256,address,string,bytes)\":{\"notice\":\"Records newly contributed tokens to a project.\"},\"recordRedemptionFor(address,uint256,uint256,string,bytes)\":{\"notice\":\"Records newly redeemed tokens of a project.\"},\"recordUsedAllowanceOf(uint256,uint256,uint256)\":{\"notice\":\"Records newly used allowance funds of a project.\"},\"usedDistributionLimitOf(address,uint256,uint256)\":{\"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.\"},\"usedOverflowAllowanceOf(address,uint256,uint256)\":{\"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.\"}},\"notice\":\"Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/JBSingleTokenPaymentTerminalStore3_1.sol\":\"JBSingleTokenPaymentTerminalStore3_1\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/security/ReentrancyGuard.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Contract module that helps prevent reentrant calls to a function.\\n *\\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\\n * available, which can be applied to functions to make sure there are no nested\\n * (reentrant) calls to them.\\n *\\n * Note that because there is a single `nonReentrant` guard, functions marked as\\n * `nonReentrant` may not call one another. This can be worked around by making\\n * those functions `private`, and then adding `external` `nonReentrant` entry\\n * points to them.\\n *\\n * TIP: If you would like to learn more about reentrancy and alternative ways\\n * to protect against it, check out our blog post\\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\\n */\\nabstract contract ReentrancyGuard {\\n // Booleans are more expensive than uint256 or any type that takes up a full\\n // word because each write operation emits an extra SLOAD to first read the\\n // slot's contents, replace the bits taken up by the boolean, and then write\\n // back. This is the compiler's defense against contract upgrades and\\n // pointer aliasing, and it cannot be disabled.\\n\\n // The values being non-zero value makes deployment a bit more expensive,\\n // but in exchange the refund on every call to nonReentrant will be lower in\\n // amount. Since refunds are capped to a percentage of the total\\n // transaction's gas, it is best to keep them low in cases like this one, to\\n // increase the likelihood of the full refund coming into effect.\\n uint256 private constant _NOT_ENTERED = 1;\\n uint256 private constant _ENTERED = 2;\\n\\n uint256 private _status;\\n\\n constructor() {\\n _status = _NOT_ENTERED;\\n }\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and making it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n // On the first call to nonReentrant, _notEntered will be true\\n require(_status != _ENTERED, \\\"ReentrancyGuard: reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n _status = _ENTERED;\\n\\n _;\\n\\n // By storing the original value once again, a refund is triggered (see\\n // https://eips.ethereum.org/EIPS/eip-2200)\\n _status = _NOT_ENTERED;\\n }\\n}\\n\",\"keccak256\":\"0x0e9621f60b2faabe65549f7ed0f24e8853a45c1b7990d47e8160e523683f3935\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool _approved) external;\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes calldata data\\n ) external;\\n}\\n\",\"keccak256\":\"0x516a22876c1fab47f49b1bc22b4614491cd05338af8bd2e7b382da090a079990\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"@paulrberg/contracts/math/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\nimport \\\"prb-math/contracts/PRBMath.sol\\\";\\n\",\"keccak256\":\"0x42821345981bc0434a90ba2268a2f5278dfe9e38166981d72fc7f3b776a29495\",\"license\":\"Unlicense\"},\"contracts/JBSingleTokenPaymentTerminalStore3_1.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\\nimport '@paulrberg/contracts/math/PRBMath.sol';\\nimport './interfaces/IJBController3_1.sol';\\nimport './interfaces/IJBFundingCycleDataSource.sol';\\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\\nimport './libraries/JBConstants.sol';\\nimport './libraries/JBCurrencies.sol';\\nimport './libraries/JBFixedPointNumber.sol';\\nimport './libraries/JBFundingCycleMetadataResolver.sol';\\nimport './structs/JBPayDelegateAllocation.sol';\\nimport './structs/JBPayParamsData.sol';\\n\\n/**\\n @notice\\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\\n\\n @dev\\n Adheres to:\\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\\n\\n @dev\\n Inherits from -\\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\\n\\n @dev\\n This Store expects a project's controller to be an IJBController3_1. This is the only difference between this version and the original.\\n*/\\ncontract JBSingleTokenPaymentTerminalStore3_1 is\\n ReentrancyGuard,\\n IJBSingleTokenPaymentTerminalStore\\n{\\n // A library that parses the packed funding cycle metadata into a friendlier format.\\n using JBFundingCycleMetadataResolver for JBFundingCycle;\\n\\n //*********************************************************************//\\n // --------------------------- custom errors ------------------------- //\\n //*********************************************************************//\\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\\n error CURRENCY_MISMATCH();\\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\\n error FUNDING_CYCLE_PAYMENT_PAUSED();\\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\\n error FUNDING_CYCLE_REDEEM_PAUSED();\\n error INADEQUATE_CONTROLLER_ALLOWANCE();\\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\\n error INSUFFICIENT_TOKENS();\\n error INVALID_FUNDING_CYCLE();\\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\\n\\n //*********************************************************************//\\n // -------------------------- private constants ---------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \\n */\\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\\n\\n //*********************************************************************//\\n // ---------------- public immutable stored properties --------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The directory of terminals and controllers for projects.\\n */\\n IJBDirectory public immutable override directory;\\n\\n /**\\n @notice\\n The contract storing all funding cycle configurations.\\n */\\n IJBFundingCycleStore public immutable override fundingCycleStore;\\n\\n /**\\n @notice\\n The contract that exposes price feeds.\\n */\\n IJBPrices public immutable override prices;\\n\\n //*********************************************************************//\\n // --------------------- public stored properties -------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\\n\\n @dev\\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\\n\\n _terminal The terminal to which the balance applies.\\n _projectId The ID of the project to get the balance of.\\n */\\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\\n\\n /**\\n @notice\\n 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.\\n\\n @dev\\n Increases as projects use their preconfigured distribution limits.\\n\\n @dev\\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\\n\\n _terminal The terminal to which the used distribution limit applies.\\n _projectId The ID of the project to get the used distribution limit of.\\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\\n */\\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\\n public\\n override usedDistributionLimitOf;\\n\\n /**\\n @notice\\n 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.\\n\\n @dev\\n Increases as projects use their allowance.\\n\\n @dev\\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\\n\\n _terminal The terminal to which the overflow allowance applies.\\n _projectId The ID of the project to get the used overflow allowance of.\\n _configuration The configuration of the during which the allowance was used.\\n */\\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\\n public\\n override usedOverflowAllowanceOf;\\n\\n //*********************************************************************//\\n // ------------------------- external views -------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Gets the current overflowed amount in a terminal for a specified project.\\n\\n @dev\\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\\n\\n @param _terminal The terminal for which the overflow is being calculated.\\n @param _projectId The ID of the project to get overflow for.\\n\\n @return The current amount of overflow that project has in the specified terminal.\\n */\\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\\n external\\n view\\n override\\n returns (uint256)\\n {\\n // Return the overflow during the project's current funding cycle.\\n return\\n _overflowDuring(\\n _terminal,\\n _projectId,\\n fundingCycleStore.currentOf(_projectId),\\n _terminal.currency()\\n );\\n }\\n\\n /**\\n @notice\\n Gets the current overflowed amount for a specified project across all terminals.\\n\\n @param _projectId The ID of the project to get total overflow for.\\n @param _decimals The number of decimals that the fixed point overflow should include.\\n @param _currency The currency that the total overflow should be in terms of.\\n\\n @return The current total amount of overflow that project has across all terminals.\\n */\\n function currentTotalOverflowOf(\\n uint256 _projectId,\\n uint256 _decimals,\\n uint256 _currency\\n ) external view override returns (uint256) {\\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\\n }\\n\\n /**\\n @notice\\n 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.\\n\\n @dev \\n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\\n\\n @dev\\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\\n\\n @dev\\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\\n\\n @param _terminal The terminal from which the reclaimable amount would come.\\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\\n @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`.\\n\\n @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`.\\n */\\n function currentReclaimableOverflowOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n bool _useTotalOverflow\\n ) external view override returns (uint256) {\\n // Get a reference to the project's current funding cycle.\\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // Get the amount of current overflow.\\n // 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.\\n uint256 _currentOverflow = _useTotalOverflow\\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\\n\\n // If there's no overflow, there's no reclaimable overflow.\\n if (_currentOverflow == 0) return 0;\\n\\n // Get the number of outstanding tokens the project has.\\n uint256 _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\\n .totalOutstandingTokensOf(_projectId);\\n\\n // Can't redeem more tokens that is in the supply.\\n if (_tokenCount > _totalSupply) return 0;\\n\\n // Return the reclaimable overflow amount.\\n return\\n _reclaimableOverflowDuring(\\n _projectId,\\n _fundingCycle,\\n _tokenCount,\\n _totalSupply,\\n _currentOverflow\\n );\\n }\\n\\n /**\\n @notice\\n 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.\\n\\n @dev \\n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\\n\\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\\n\\n @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`.\\n */\\n function currentReclaimableOverflowOf(\\n uint256 _projectId,\\n uint256 _tokenCount,\\n uint256 _totalSupply,\\n uint256 _overflow\\n ) external view override returns (uint256) {\\n // If there's no overflow, there's no reclaimable overflow.\\n if (_overflow == 0) return 0;\\n\\n // Can't redeem more tokens that is in the supply.\\n if (_tokenCount > _totalSupply) return 0;\\n\\n // Get a reference to the project's current funding cycle.\\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // Return the reclaimable overflow amount.\\n return\\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\\n }\\n\\n //*********************************************************************//\\n // -------------------------- constructor ---------------------------- //\\n //*********************************************************************//\\n\\n /**\\n @param _directory A contract storing directories of terminals and controllers for each project.\\n @param _fundingCycleStore A contract storing all funding cycle configurations.\\n @param _prices A contract that exposes price feeds.\\n */\\n constructor(\\n IJBDirectory _directory,\\n IJBFundingCycleStore _fundingCycleStore,\\n IJBPrices _prices\\n ) {\\n directory = _directory;\\n fundingCycleStore = _fundingCycleStore;\\n prices = _prices;\\n }\\n\\n //*********************************************************************//\\n // ---------------------- external transactions ---------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n Records newly contributed tokens to a project.\\n\\n @dev\\n 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.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\\n\\n @param _payer The original address that sent the payment to the terminal.\\n @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.\\n @param _projectId The ID of the project being paid.\\n @param _baseWeightCurrency The currency to base token issuance on.\\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\\n @param _metadata Bytes to send along to the data source, if one is provided.\\n\\n @return fundingCycle The project's funding cycle during which payment was made.\\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\\n @return memo A memo that should be passed along to the emitted event.\\n */\\n function recordPaymentFrom(\\n address _payer,\\n JBTokenAmount calldata _amount,\\n uint256 _projectId,\\n uint256 _baseWeightCurrency,\\n address _beneficiary,\\n string calldata _memo,\\n bytes memory _metadata\\n )\\n external\\n override\\n nonReentrant\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 tokenCount,\\n JBPayDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n )\\n {\\n // Get a reference to the current funding cycle for the project.\\n fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // The project must have a funding cycle configured.\\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\\n\\n // Must not be paused.\\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\\n\\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\\n uint256 _weight;\\n\\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\\n // Create the params that'll be sent to the data source.\\n JBPayParamsData memory _data = JBPayParamsData(\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n _payer,\\n _amount,\\n _projectId,\\n fundingCycle.configuration,\\n _beneficiary,\\n fundingCycle.weight,\\n fundingCycle.reservedRate(),\\n _memo,\\n _metadata\\n );\\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\\n .payParams(_data);\\n }\\n // Otherwise use the funding cycle's weight\\n else {\\n _weight = fundingCycle.weight;\\n memo = _memo;\\n }\\n\\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\\n {\\n // Keep a reference to the amount that should be added to the project's balance.\\n uint256 _balanceDiff = _amount.value;\\n\\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\\n if (delegateAllocations.length != 0) {\\n for (uint256 _i; _i < delegateAllocations.length; ) {\\n // Get a reference to the amount to be delegated.\\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\\n\\n // Validate if non-zero.\\n if (_delegatedAmount != 0) {\\n // Can't delegate more than was paid.\\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\\n\\n // Decrement the total amount being added to the balance.\\n _balanceDiff = _balanceDiff - _delegatedAmount;\\n }\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n\\n // If there's no amount being recorded, there's nothing left to do.\\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\\n\\n // Add the correct balance difference to the token balance of the project.\\n if (_balanceDiff != 0)\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\\n _balanceDiff;\\n }\\n\\n // If there's no weight, token count must be 0 so there's nothing left to do.\\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\\n\\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\\n uint256 _decimals = _amount.decimals;\\n\\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\\n // 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`.\\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\\n ? 10**_decimals\\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\\n\\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\\n }\\n\\n /**\\n @notice\\n Records newly redeemed tokens of a project.\\n\\n @dev\\n 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.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\\n\\n @param _holder The account that is having its tokens redeemed.\\n @param _projectId The ID of the project to which the tokens being redeemed belong.\\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\\n @param _memo A memo to pass along to the emitted event.\\n @param _metadata Bytes to send along to the data source, if one is provided.\\n\\n @return fundingCycle The funding cycle during which the redemption was made.\\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\\n @return memo A memo that should be passed along to the emitted event.\\n */\\n function recordRedemptionFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n string memory _memo,\\n bytes memory _metadata\\n )\\n external\\n override\\n nonReentrant\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 reclaimAmount,\\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n )\\n {\\n // Get a reference to the project's current funding cycle.\\n fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // The current funding cycle must not be paused.\\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\\n\\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\\n {\\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\\n JBTokenAmount memory _reclaimedTokenAmount;\\n uint256 _currentOverflow;\\n uint256 _totalSupply;\\n\\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\\n {\\n // Get a reference to the terminal's tokens.\\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\\n\\n // Get a reference to the terminal's decimals.\\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\\n\\n // Get areference to the terminal's currency.\\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\\n\\n // Get the amount of current overflow.\\n // 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.\\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\\n : _overflowDuring(\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n _projectId,\\n fundingCycle,\\n _currency\\n );\\n\\n // Get the number of outstanding tokens the project has.\\n _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\\n .totalOutstandingTokensOf(_projectId);\\n\\n // Can't redeem more tokens that is in the supply.\\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\\n\\n if (_currentOverflow != 0)\\n // Calculate reclaim amount using the current overflow amount.\\n reclaimAmount = _reclaimableOverflowDuring(\\n _projectId,\\n fundingCycle,\\n _tokenCount,\\n _totalSupply,\\n _currentOverflow\\n );\\n\\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\\n }\\n\\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\\n {\\n // Get a reference to the ballot state.\\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\\n\\n // Create the params that'll be sent to the data source.\\n JBRedeemParamsData memory _data = JBRedeemParamsData(\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n _holder,\\n _projectId,\\n fundingCycle.configuration,\\n _tokenCount,\\n _totalSupply,\\n _currentOverflow,\\n _reclaimedTokenAmount,\\n fundingCycle.useTotalOverflowForRedemptions(),\\n _state == JBBallotState.Active\\n ? fundingCycle.ballotRedemptionRate()\\n : fundingCycle.redemptionRate(),\\n _memo,\\n _metadata\\n );\\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\\n fundingCycle.dataSource()\\n ).redeemParams(_data);\\n }\\n } else {\\n memo = _memo;\\n }\\n }\\n\\n // Keep a reference to the amount that should be subtracted from the project's balance.\\n uint256 _balanceDiff = reclaimAmount;\\n\\n if (delegateAllocations.length != 0) {\\n // Validate all delegated amounts.\\n for (uint256 _i; _i < delegateAllocations.length; ) {\\n // Get a reference to the amount to be delegated.\\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\\n\\n // Validate if non-zero.\\n if (_delegatedAmount != 0)\\n // Increment the total amount being subtracted from the balance.\\n _balanceDiff = _balanceDiff + _delegatedAmount;\\n\\n unchecked {\\n ++_i;\\n }\\n }\\n }\\n\\n // The amount being reclaimed must be within the project's balance.\\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\\n\\n // Remove the reclaimed funds from the project's balance.\\n if (_balanceDiff != 0) {\\n unchecked {\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\\n _balanceDiff;\\n }\\n }\\n }\\n\\n /**\\n @notice\\n Records newly distributed funds for a project.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \\n\\n @param _projectId The ID of the project that is having funds distributed.\\n @param _amount The amount to use from the distribution limit, as a fixed point number.\\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\\n\\n @return fundingCycle The funding cycle during which the distribution was made.\\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\\n */\\n function recordDistributionFor(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n )\\n external\\n override\\n nonReentrant\\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\\n {\\n // Get a reference to the project's current funding cycle.\\n fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // The funding cycle must not be configured to have distributions paused.\\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\\n\\n // The new total amount that has been distributed during this funding cycle.\\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\\n IJBSingleTokenPaymentTerminal(msg.sender)\\n ][_projectId][fundingCycle.number] + _amount;\\n\\n // Amount must be within what is still distributable.\\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController3_1(\\n directory.controllerOf(_projectId)\\n ).fundAccessConstraintsStore().distributionLimitOf(\\n _projectId,\\n fundingCycle.configuration,\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n IJBSingleTokenPaymentTerminal(msg.sender).token()\\n );\\n\\n // Make sure the new used amount is within the distribution limit.\\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\\n\\n // Make sure the currencies match.\\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\\n\\n // Get a reference to the terminal's currency.\\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\\n\\n // Convert the amount to the balance's currency.\\n distributedAmount = (_currency == _balanceCurrency)\\n ? _amount\\n : PRBMath.mulDiv(\\n _amount,\\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\\n );\\n\\n // The amount being distributed must be available.\\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\\n\\n // Store the new amount.\\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\\n fundingCycle.number\\n ] = _newUsedDistributionLimitOf;\\n\\n // Removed the distributed funds from the project's token balance.\\n unchecked {\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\\n distributedAmount;\\n }\\n }\\n\\n /**\\n @notice\\n Records newly used allowance funds of a project.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \\n\\n @param _projectId The ID of the project to use the allowance of.\\n @param _amount The amount to use from the allowance, as a fixed point number. \\n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\\n\\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\\n */\\n function recordUsedAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n )\\n external\\n override\\n nonReentrant\\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\\n {\\n // Get a reference to the project's current funding cycle.\\n fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\\n IJBSingleTokenPaymentTerminal(msg.sender)\\n ][_projectId][fundingCycle.configuration] + _amount;\\n\\n // There must be sufficient allowance available.\\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController3_1(\\n directory.controllerOf(_projectId)\\n ).fundAccessConstraintsStore().overflowAllowanceOf(\\n _projectId,\\n fundingCycle.configuration,\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n IJBSingleTokenPaymentTerminal(msg.sender).token()\\n );\\n\\n // Make sure the new used amount is within the allowance.\\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\\n\\n // Make sure the currencies match.\\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\\n\\n // Get a reference to the terminal's currency.\\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\\n\\n // Convert the amount to this store's terminal's token.\\n usedAmount = (_currency == _balanceCurrency)\\n ? _amount\\n : PRBMath.mulDiv(\\n _amount,\\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\\n );\\n\\n // The amount being distributed must be available in the overflow.\\n if (\\n usedAmount >\\n _overflowDuring(\\n IJBSingleTokenPaymentTerminal(msg.sender),\\n _projectId,\\n fundingCycle,\\n _balanceCurrency\\n )\\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\\n\\n // Store the incremented value.\\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\\n fundingCycle.configuration\\n ] = _newUsedOverflowAllowanceOf;\\n\\n // Update the project's balance.\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\\n usedAmount;\\n }\\n\\n /**\\n @notice\\n Records newly added funds for the project.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \\n\\n @param _projectId The ID of the project to which the funds being added belong.\\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\\n */\\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\\n // Increment the balance.\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\\n _amount;\\n }\\n\\n /**\\n @notice\\n Records the migration of funds from this store.\\n\\n @dev\\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\\n\\n @param _projectId The ID of the project being migrated.\\n\\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\\n */\\n function recordMigration(uint256 _projectId)\\n external\\n override\\n nonReentrant\\n returns (uint256 balance)\\n {\\n // Get a reference to the project's current funding cycle.\\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\\n\\n // Migration must be allowed.\\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\\n\\n // Return the current balance.\\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\\n\\n // Set the balance to 0.\\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\\n }\\n\\n //*********************************************************************//\\n // --------------------- private helper functions -------------------- //\\n //*********************************************************************//\\n\\n /**\\n @notice\\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\\n\\n @dev \\n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\\n\\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\\n @param _overflow The amount of overflow to make the calculation with.\\n\\n @return The amount of overflowed tokens that can be reclaimed.\\n */\\n function _reclaimableOverflowDuring(\\n uint256 _projectId,\\n JBFundingCycle memory _fundingCycle,\\n uint256 _tokenCount,\\n uint256 _totalSupply,\\n uint256 _overflow\\n ) private view returns (uint256) {\\n // If the amount being redeemed is the total supply, return the rest of the overflow.\\n if (_tokenCount == _totalSupply) return _overflow;\\n\\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\\n JBBallotState.Active\\n ? _fundingCycle.ballotRedemptionRate()\\n : _fundingCycle.redemptionRate();\\n\\n // If the redemption rate is 0, nothing is claimable.\\n if (_redemptionRate == 0) return 0;\\n\\n // Get a reference to the linear proportion.\\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\\n\\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\\n\\n return\\n PRBMath.mulDiv(\\n _base,\\n _redemptionRate +\\n PRBMath.mulDiv(\\n _tokenCount,\\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\\n _totalSupply\\n ),\\n JBConstants.MAX_REDEMPTION_RATE\\n );\\n }\\n\\n /**\\n @notice\\n Gets the amount that is overflowing when measured from the specified funding cycle.\\n\\n @dev\\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\\n\\n @param _terminal The terminal for which the overflow is being calculated.\\n @param _projectId The ID of the project to get overflow for.\\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\\n\\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\\n */\\n function _overflowDuring(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n JBFundingCycle memory _fundingCycle,\\n uint256 _balanceCurrency\\n ) private view returns (uint256) {\\n // Get the current balance of the project.\\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\\n\\n // If there's no balance, there's no overflow.\\n if (_balanceOf == 0) return 0;\\n\\n // Get a reference to the distribution limit during the funding cycle.\\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController3_1(\\n directory.controllerOf(_projectId)\\n ).fundAccessConstraintsStore().distributionLimitOf(\\n _projectId,\\n _fundingCycle.configuration,\\n _terminal,\\n _terminal.token()\\n );\\n\\n // Get a reference to the amount still distributable during the funding cycle.\\n uint256 _distributionLimitRemaining = _distributionLimit -\\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\\n\\n // Convert the _distributionRemaining to be in terms of the provided currency.\\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\\n _distributionLimitRemaining = PRBMath.mulDiv(\\n _distributionLimitRemaining,\\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\\n );\\n\\n // Overflow is the balance of this project minus the amount that can still be distributed.\\n unchecked {\\n return\\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\\n }\\n }\\n\\n /**\\n @notice\\n Gets the amount that is currently overflowing across all of a project's terminals. \\n\\n @dev\\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\\n\\n @param _projectId The ID of the project to get the total overflow for.\\n @param _decimals The number of decimals that the fixed point overflow should include.\\n @param _currency The currency that the overflow should be in terms of.\\n\\n @return overflow The total overflow of a project's funds.\\n */\\n function _currentTotalOverflowOf(\\n uint256 _projectId,\\n uint256 _decimals,\\n uint256 _currency\\n ) private view returns (uint256) {\\n // Get a reference to the project's terminals.\\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\\n\\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\\n uint256 _ethOverflow;\\n\\n // Add the current ETH overflow for each terminal.\\n for (uint256 _i; _i < _terminals.length; ) {\\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\\n unchecked {\\n ++_i;\\n }\\n }\\n\\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.GAS_CURRENCY\\n ? _ethOverflow\\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.GAS_CURRENCY, _currency, 18));\\n\\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\\n return\\n (_decimals == 18)\\n ? _totalOverflow18Decimal\\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\\n }\\n}\\n\",\"keccak256\":\"0x7fc9e05a77c0d37c10709df6f479562d73d684b9aec28d0227e83beffa4d2a01\",\"license\":\"MIT\"},\"contracts/enums/JBBallotState.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nenum JBBallotState {\\n Active,\\n Approved,\\n Failed\\n}\\n\",\"keccak256\":\"0x891fcac63470398b3a11239da7feba6b07d640809fcefd2404303b823d7378f8\",\"license\":\"MIT\"},\"contracts/interfaces/IJBController.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBFundAccessConstraints.sol';\\nimport './../structs/JBFundingCycleData.sol';\\nimport './../structs/JBFundingCycleMetadata.sol';\\nimport './../structs/JBGroupedSplits.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBMigratable.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBSplitsStore.sol';\\nimport './IJBTokenStore.sol';\\n\\ninterface IJBController is IERC165 {\\n event LaunchProject(uint256 configuration, uint256 projectId, string memo, address caller);\\n\\n event LaunchFundingCycles(uint256 configuration, uint256 projectId, string memo, address caller);\\n\\n event ReconfigureFundingCycles(\\n uint256 configuration,\\n uint256 projectId,\\n string memo,\\n address caller\\n );\\n\\n event SetFundAccessConstraints(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n JBFundAccessConstraints constraints,\\n address caller\\n );\\n\\n event DistributeReservedTokens(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address beneficiary,\\n uint256 tokenCount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n address caller\\n );\\n\\n event DistributeToReservedTokenSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n uint256 tokenCount,\\n address caller\\n );\\n\\n event MintTokens(\\n address indexed beneficiary,\\n uint256 indexed projectId,\\n uint256 tokenCount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n uint256 reservedRate,\\n address caller\\n );\\n\\n event BurnTokens(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 tokenCount,\\n string memo,\\n address caller\\n );\\n\\n event Migrate(uint256 indexed projectId, IJBMigratable to, address caller);\\n\\n event PrepMigration(uint256 indexed projectId, address from, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function tokenStore() external view returns (IJBTokenStore);\\n\\n function splitsStore() external view returns (IJBSplitsStore);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function reservedTokenBalanceOf(uint256 _projectId, uint256 _reservedRate)\\n external\\n view\\n returns (uint256);\\n\\n function distributionLimitOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n IJBPaymentTerminal _terminal,\\n address _token\\n ) external view returns (uint256 distributionLimit, uint256 distributionLimitCurrency);\\n\\n function overflowAllowanceOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n IJBPaymentTerminal _terminal,\\n address _token\\n ) external view returns (uint256 overflowAllowance, uint256 overflowAllowanceCurrency);\\n\\n function totalOutstandingTokensOf(uint256 _projectId, uint256 _reservedRate)\\n external\\n view\\n returns (uint256);\\n\\n function getFundingCycleOf(uint256 _projectId, uint256 _configuration)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function latestConfiguredFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (\\n JBFundingCycle memory,\\n JBFundingCycleMetadata memory metadata,\\n JBBallotState\\n );\\n\\n function currentFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function queuedFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function launchProjectFor(\\n address _owner,\\n JBProjectMetadata calldata _projectMetadata,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n IJBPaymentTerminal[] memory _terminals,\\n string calldata _memo\\n ) external returns (uint256 projectId);\\n\\n function launchFundingCyclesFor(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n IJBPaymentTerminal[] memory _terminals,\\n string calldata _memo\\n ) external returns (uint256 configuration);\\n\\n function reconfigureFundingCyclesOf(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n string calldata _memo\\n ) external returns (uint256);\\n\\n function mintTokensOf(\\n uint256 _projectId,\\n uint256 _tokenCount,\\n address _beneficiary,\\n string calldata _memo,\\n bool _preferClaimedTokens,\\n bool _useReservedRate\\n ) external returns (uint256 beneficiaryTokenCount);\\n\\n function burnTokensOf(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n string calldata _memo,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function distributeReservedTokensOf(uint256 _projectId, string memory _memo)\\n external\\n returns (uint256);\\n\\n function migrate(uint256 _projectId, IJBMigratable _to) external;\\n}\\n\",\"keccak256\":\"0xb1ee4b41f2a06f28f69c74cb729b8964f2e75f3c545a68f85bd9082b5575bc85\",\"license\":\"MIT\"},\"contracts/interfaces/IJBController3_0_1.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBFundAccessConstraints.sol';\\nimport './../structs/JBFundingCycleData.sol';\\nimport './../structs/JBFundingCycleMetadata.sol';\\nimport './../structs/JBGroupedSplits.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBController.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBMigratable.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBSplitsStore.sol';\\nimport './IJBTokenStore.sol';\\n\\ninterface IJBController3_0_1 {\\n function reservedTokenBalanceOf(uint256 _projectId) external view returns (uint256);\\n function totalOutstandingTokensOf(uint256 _projectId) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xf853badd9b8c149b7e1cd01b1123a949bc64036cfcc9e4b6d237b6911eccb058\",\"license\":\"MIT\"},\"contracts/interfaces/IJBController3_1.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBFundAccessConstraints.sol';\\nimport './../structs/JBFundingCycleData.sol';\\nimport './../structs/JBFundingCycleMetadata.sol';\\nimport './../structs/JBGroupedSplits.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBController3_0_1.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFundAccessConstraintsStore.sol';\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBMigratable.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBSplitsStore.sol';\\nimport './IJBTokenStore.sol';\\n\\ninterface IJBController3_1 is IJBController3_0_1, IERC165 {\\n event LaunchProject(uint256 configuration, uint256 projectId, string memo, address caller);\\n\\n event LaunchFundingCycles(uint256 configuration, uint256 projectId, string memo, address caller);\\n\\n event ReconfigureFundingCycles(\\n uint256 configuration,\\n uint256 projectId,\\n string memo,\\n address caller\\n );\\n\\n event DistributeReservedTokens(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed fundingCycleNumber,\\n uint256 indexed projectId,\\n address beneficiary,\\n uint256 tokenCount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n address caller\\n );\\n\\n event DistributeToReservedTokenSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n uint256 tokenCount,\\n address caller\\n );\\n\\n event MintTokens(\\n address indexed beneficiary,\\n uint256 indexed projectId,\\n uint256 tokenCount,\\n uint256 beneficiaryTokenCount,\\n string memo,\\n uint256 reservedRate,\\n address caller\\n );\\n\\n event BurnTokens(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 tokenCount,\\n string memo,\\n address caller\\n );\\n\\n event Migrate(uint256 indexed projectId, IJBMigratable to, address caller);\\n\\n event PrepMigration(uint256 indexed projectId, address from, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function tokenStore() external view returns (IJBTokenStore);\\n\\n function splitsStore() external view returns (IJBSplitsStore);\\n\\n function fundAccessConstraintsStore() external view returns (IJBFundAccessConstraintsStore);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function reservedTokenBalanceOf(uint256 _projectId) external view returns (uint256);\\n\\n function totalOutstandingTokensOf(uint256 _projectId) external view returns (uint256);\\n\\n function getFundingCycleOf(uint256 _projectId, uint256 _configuration)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function latestConfiguredFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (\\n JBFundingCycle memory,\\n JBFundingCycleMetadata memory metadata,\\n JBBallotState\\n );\\n\\n function currentFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function queuedFundingCycleOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\\n\\n function launchProjectFor(\\n address _owner,\\n JBProjectMetadata calldata _projectMetadata,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n IJBPaymentTerminal[] memory _terminals,\\n string calldata _memo\\n ) external returns (uint256 projectId);\\n\\n function launchFundingCyclesFor(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n IJBPaymentTerminal[] memory _terminals,\\n string calldata _memo\\n ) external returns (uint256 configuration);\\n\\n function reconfigureFundingCyclesOf(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n JBFundingCycleMetadata calldata _metadata,\\n uint256 _mustStartAtOrAfter,\\n JBGroupedSplits[] memory _groupedSplits,\\n JBFundAccessConstraints[] memory _fundAccessConstraints,\\n string calldata _memo\\n ) external returns (uint256);\\n\\n function mintTokensOf(\\n uint256 _projectId,\\n uint256 _tokenCount,\\n address _beneficiary,\\n string calldata _memo,\\n bool _preferClaimedTokens,\\n bool _useReservedRate\\n ) external returns (uint256 beneficiaryTokenCount);\\n\\n function burnTokensOf(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n string calldata _memo,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function distributeReservedTokensOf(uint256 _projectId, string memory _memo)\\n external\\n returns (uint256);\\n\\n function migrate(uint256 _projectId, IJBMigratable _to) external;\\n}\\n\",\"keccak256\":\"0x9aea97f1a77f48d313aee6c9ea97dffdfdb4f50c1cfd94f0b360a8ce6e383f4c\",\"license\":\"MIT\"},\"contracts/interfaces/IJBDirectory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBPaymentTerminal.sol';\\nimport './IJBProjects.sol';\\n\\ninterface IJBDirectory {\\n event SetController(uint256 indexed projectId, address indexed controller, address caller);\\n\\n event AddTerminal(uint256 indexed projectId, IJBPaymentTerminal indexed terminal, address caller);\\n\\n event SetTerminals(uint256 indexed projectId, IJBPaymentTerminal[] terminals, address caller);\\n\\n event SetPrimaryTerminal(\\n uint256 indexed projectId,\\n address indexed token,\\n IJBPaymentTerminal indexed terminal,\\n address caller\\n );\\n\\n event SetIsAllowedToSetFirstController(address indexed addr, bool indexed flag, address caller);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function controllerOf(uint256 _projectId) external view returns (address);\\n\\n function isAllowedToSetFirstController(address _address) external view returns (bool);\\n\\n function terminalsOf(uint256 _projectId) external view returns (IJBPaymentTerminal[] memory);\\n\\n function isTerminalOf(uint256 _projectId, IJBPaymentTerminal _terminal)\\n external\\n view\\n returns (bool);\\n\\n function primaryTerminalOf(uint256 _projectId, address _token)\\n external\\n view\\n returns (IJBPaymentTerminal);\\n\\n function setControllerOf(uint256 _projectId, address _controller) external;\\n\\n function setTerminalsOf(uint256 _projectId, IJBPaymentTerminal[] calldata _terminals) external;\\n\\n function setPrimaryTerminalOf(\\n uint256 _projectId,\\n address _token,\\n IJBPaymentTerminal _terminal\\n ) external;\\n\\n function setIsAllowedToSetFirstController(address _address, bool _flag) external;\\n}\\n\",\"keccak256\":\"0x715321646db00514d1355ed43c40cd3f01e94959552fd07797b315d9c49cdb1d\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundAccessConstraintsStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBFundAccessConstraints.sol';\\nimport './IJBPaymentTerminal.sol';\\n\\ninterface IJBFundAccessConstraintsStore is IERC165 {\\n event SetFundAccessConstraints(\\n uint256 indexed fundingCycleConfiguration,\\n uint256 indexed projectId,\\n JBFundAccessConstraints constraints,\\n address caller\\n );\\n\\n function distributionLimitOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n IJBPaymentTerminal _terminal,\\n address _token\\n ) external view returns (uint256 distributionLimit, uint256 distributionLimitCurrency);\\n\\n function overflowAllowanceOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n IJBPaymentTerminal _terminal,\\n address _token\\n ) external view returns (uint256 overflowAllowance, uint256 overflowAllowanceCurrency);\\n\\n function setFor(\\n uint256 _projectId,\\n uint256 _configuration,\\n JBFundAccessConstraints[] memory _fundAccessConstaints\\n ) external;\\n}\\n\",\"keccak256\":\"0x3158c6cab1b81827a5a2d90a5936a0c7f8ba0d1bcdb05ae8b8a1ac7f03d0c999\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleBallot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../enums/JBBallotState.sol';\\n\\ninterface IJBFundingCycleBallot is IERC165 {\\n function duration() external view returns (uint256);\\n\\n function stateOf(\\n uint256 _projectId,\\n uint256 _configuration,\\n uint256 _start\\n ) external view returns (JBBallotState);\\n}\\n\",\"keccak256\":\"0x49553a56209237846bc400cf27f260824a6bd06fd8094a7eb5abb9de75779598\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleDataSource.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBPayDelegateAllocation.sol';\\nimport './../structs/JBPayParamsData.sol';\\nimport './../structs/JBRedeemParamsData.sol';\\nimport './../structs/JBRedemptionDelegateAllocation.sol';\\n\\n/**\\n @title\\n Datasource\\n\\n @notice\\n The datasource is called by JBPaymentTerminal on pay and redemption, and provide an extra layer of logic to use \\n a custom weight, a custom memo and/or a pay/redeem delegate\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n*/\\ninterface IJBFundingCycleDataSource is IERC165 {\\n /**\\n @notice\\n The datasource implementation for JBPaymentTerminal.pay(..)\\n\\n @param _data the data passed to the data source in terminal.pay(..), as a JBPayParamsData struct:\\n IJBPaymentTerminal terminal;\\n address payer;\\n JBTokenAmount amount;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n address beneficiary;\\n uint256 weight;\\n uint256 reservedRate;\\n string memo;\\n bytes metadata;\\n\\n @return weight the weight to use to override the funding cycle weight\\n @return memo the memo to override the pay(..) memo\\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\\n */\\n function payParams(JBPayParamsData calldata _data)\\n external\\n returns (\\n uint256 weight,\\n string memory memo,\\n JBPayDelegateAllocation[] memory delegateAllocations\\n );\\n\\n /**\\n @notice\\n The datasource implementation for JBPaymentTerminal.redeemTokensOf(..)\\n\\n @param _data the data passed to the data source in terminal.redeemTokensOf(..), as a JBRedeemParamsData struct:\\n IJBPaymentTerminal terminal;\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 tokenCount;\\n uint256 totalSupply;\\n uint256 overflow;\\n JBTokenAmount reclaimAmount;\\n bool useTotalOverflow;\\n uint256 redemptionRate;\\n uint256 ballotRedemptionRate;\\n string memo;\\n bytes metadata;\\n\\n @return reclaimAmount The amount to claim, overriding the terminal logic.\\n @return memo The memo to override the redeemTokensOf(..) memo.\\n @return delegateAllocations The amount to send to delegates instead of adding to the beneficiary.\\n */\\n function redeemParams(JBRedeemParamsData calldata _data)\\n external\\n returns (\\n uint256 reclaimAmount,\\n string memory memo,\\n JBRedemptionDelegateAllocation[] memory delegateAllocations\\n );\\n}\\n\",\"keccak256\":\"0xa424abc146a61b69db83e511c064492da6fab6d8226e13d1580bc9fbc50d6738\",\"license\":\"MIT\"},\"contracts/interfaces/IJBFundingCycleStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../enums/JBBallotState.sol';\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBFundingCycleData.sol';\\n\\ninterface IJBFundingCycleStore {\\n event Configure(\\n uint256 indexed configuration,\\n uint256 indexed projectId,\\n JBFundingCycleData data,\\n uint256 metadata,\\n uint256 mustStartAtOrAfter,\\n address caller\\n );\\n\\n event Init(uint256 indexed configuration, uint256 indexed projectId, uint256 indexed basedOn);\\n\\n function latestConfigurationOf(uint256 _projectId) external view returns (uint256);\\n\\n function get(uint256 _projectId, uint256 _configuration)\\n external\\n view\\n returns (JBFundingCycle memory);\\n\\n function latestConfiguredOf(uint256 _projectId)\\n external\\n view\\n returns (JBFundingCycle memory fundingCycle, JBBallotState ballotState);\\n\\n function queuedOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentOf(uint256 _projectId) external view returns (JBFundingCycle memory fundingCycle);\\n\\n function currentBallotStateOf(uint256 _projectId) external view returns (JBBallotState);\\n\\n function configureFor(\\n uint256 _projectId,\\n JBFundingCycleData calldata _data,\\n uint256 _metadata,\\n uint256 _mustStartAtOrAfter\\n ) external returns (JBFundingCycle memory fundingCycle);\\n}\\n\",\"keccak256\":\"0xaead823851433be0c2ddc8f8086813e6cd647de3a1bc0f7570a5d6b38c378b5a\",\"license\":\"MIT\"},\"contracts/interfaces/IJBMigratable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBMigratable {\\n function prepForMigrationOf(uint256 _projectId, address _from) external;\\n}\\n\",\"keccak256\":\"0xc81053e4b4754fc510aa04fecd3ab1460f01e3e27761e7a8c94f631a978ae127\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPayDelegate.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBDidPayData.sol';\\n\\n/**\\n @title\\n Pay delegate\\n\\n @notice\\n Delegate called after JBTerminal.pay(..) logic completion (if passed by the funding cycle datasource)\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n*/\\ninterface IJBPayDelegate is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.pay(..), after the execution of its logic\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control\\n \\n @param _data the data passed by the terminal, as a JBDidPayData struct:\\n address payer;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n JBTokenAmount amount;\\n JBTokenAmount forwardedAmount;\\n uint256 projectTokenCount;\\n address beneficiary;\\n bool preferClaimedTokens;\\n string memo;\\n bytes metadata;\\n */\\n function didPay(JBDidPayData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0xa797de18b69eceba117e1f0b3810cf3cc2d2791417d580a5bdc510d1b868ab26\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\n\\ninterface IJBPaymentTerminal is IERC165 {\\n function acceptsToken(address _token, uint256 _projectId) external view returns (bool);\\n\\n function currencyForToken(address _token) external view returns (uint256);\\n\\n function decimalsForToken(address _token) external view returns (uint256);\\n\\n // Return value must be a fixed point number with 18 decimals.\\n function currentEthOverflowOf(uint256 _projectId) external view returns (uint256);\\n\\n function pay(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n address _beneficiary,\\n uint256 _minReturnedTokens,\\n bool _preferClaimedTokens,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable returns (uint256 beneficiaryTokenCount);\\n\\n function addToBalanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n address _token,\\n string calldata _memo,\\n bytes calldata _metadata\\n ) external payable;\\n}\\n\",\"keccak256\":\"0xb7826f5ed609359ce322c09e83236c47ba385df1c3cad3607e56fd0a2e00eee2\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPriceFeed.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBPriceFeed {\\n function currentPrice(uint256 _targetDecimals) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x57c71282fec1b34b00cf991ffed2e36031c393e35bfa7ca5d723eb6572fb7122\",\"license\":\"MIT\"},\"contracts/interfaces/IJBPrices.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBPriceFeed.sol';\\n\\ninterface IJBPrices {\\n event AddFeed(uint256 indexed currency, uint256 indexed base, IJBPriceFeed feed);\\n\\n function feedFor(uint256 _currency, uint256 _base) external view returns (IJBPriceFeed);\\n\\n function priceFor(\\n uint256 _currency,\\n uint256 _base,\\n uint256 _decimals\\n ) external view returns (uint256);\\n\\n function addFeedFor(\\n uint256 _currency,\\n uint256 _base,\\n IJBPriceFeed _priceFeed\\n ) external;\\n}\\n\",\"keccak256\":\"0x82a175b1f4b95b506c98406576cd59cbe04615e3df24f9cf3587b61b8ee323b1\",\"license\":\"MIT\"},\"contracts/interfaces/IJBProjects.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\\nimport './../structs/JBProjectMetadata.sol';\\nimport './IJBTokenUriResolver.sol';\\n\\ninterface IJBProjects is IERC721 {\\n event Create(\\n uint256 indexed projectId,\\n address indexed owner,\\n JBProjectMetadata metadata,\\n address caller\\n );\\n\\n event SetMetadata(uint256 indexed projectId, JBProjectMetadata metadata, address caller);\\n\\n event SetTokenUriResolver(IJBTokenUriResolver indexed resolver, address caller);\\n\\n function count() external view returns (uint256);\\n\\n function metadataContentOf(uint256 _projectId, uint256 _domain)\\n external\\n view\\n returns (string memory);\\n\\n function tokenUriResolver() external view returns (IJBTokenUriResolver);\\n\\n function createFor(address _owner, JBProjectMetadata calldata _metadata)\\n external\\n returns (uint256 projectId);\\n\\n function setMetadataOf(uint256 _projectId, JBProjectMetadata calldata _metadata) external;\\n\\n function setTokenUriResolver(IJBTokenUriResolver _newResolver) external;\\n}\\n\",\"keccak256\":\"0x7cfc021d0bd7e73b1ba8f4845d7d35e3419d6a14d3d25ca3a8010e7f91062fe4\",\"license\":\"MIT\"},\"contracts/interfaces/IJBRedemptionDelegate.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport './../structs/JBDidRedeemData.sol';\\n\\n/**\\n @title\\n Redemption delegate\\n\\n @notice\\n Delegate called after JBTerminal.redeemTokensOf(..) logic completion (if passed by the funding cycle datasource)\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n*/\\ninterface IJBRedemptionDelegate is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.redeemTokensOf(..), after the execution of its logic\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control\\n \\n @param _data the data passed by the terminal, as a JBDidRedeemData struct:\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 projectTokenCount;\\n JBTokenAmount reclaimedAmount;\\n JBTokenAmount forwardedAmount;\\n address payable beneficiary;\\n string memo;\\n bytes metadata;\\n */\\n function didRedeem(JBDidRedeemData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0x172d2c0be65e72e54f71ae521907067f0fa30e8ca05c4f88826903208aa437e2\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSingleTokenPaymentTerminal.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBPaymentTerminal.sol';\\n\\ninterface IJBSingleTokenPaymentTerminal is IJBPaymentTerminal {\\n function token() external view returns (address);\\n\\n function currency() external view returns (uint256);\\n\\n function decimals() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0xf6e78323caa9af7bbf024f44b2032a83fed0394e0b3a242a6346e73c85b2e46f\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSingleTokenPaymentTerminalStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBPayDelegateAllocation.sol';\\nimport './../structs/JBRedemptionDelegateAllocation.sol';\\nimport './../structs/JBTokenAmount.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBPrices.sol';\\nimport './IJBSingleTokenPaymentTerminal.sol';\\n\\ninterface IJBSingleTokenPaymentTerminalStore {\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function prices() external view returns (IJBPrices);\\n\\n function balanceOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\\n external\\n view\\n returns (uint256);\\n\\n function usedDistributionLimitOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _fundingCycleNumber\\n ) external view returns (uint256);\\n\\n function usedOverflowAllowanceOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _fundingCycleConfiguration\\n ) external view returns (uint256);\\n\\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\\n external\\n view\\n returns (uint256);\\n\\n function currentTotalOverflowOf(\\n uint256 _projectId,\\n uint256 _decimals,\\n uint256 _currency\\n ) external view returns (uint256);\\n\\n function currentReclaimableOverflowOf(\\n IJBSingleTokenPaymentTerminal _terminal,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n bool _useTotalOverflow\\n ) external view returns (uint256);\\n\\n function currentReclaimableOverflowOf(\\n uint256 _projectId,\\n uint256 _tokenCount,\\n uint256 _totalSupply,\\n uint256 _overflow\\n ) external view returns (uint256);\\n\\n function recordPaymentFrom(\\n address _payer,\\n JBTokenAmount memory _amount,\\n uint256 _projectId,\\n uint256 _baseWeightCurrency,\\n address _beneficiary,\\n string calldata _memo,\\n bytes calldata _metadata\\n )\\n external\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 tokenCount,\\n JBPayDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n );\\n\\n function recordRedemptionFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _tokenCount,\\n string calldata _memo,\\n bytes calldata _metadata\\n )\\n external\\n returns (\\n JBFundingCycle memory fundingCycle,\\n uint256 reclaimAmount,\\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\\n string memory memo\\n );\\n\\n function recordDistributionFor(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n ) external returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount);\\n\\n function recordUsedAllowanceOf(\\n uint256 _projectId,\\n uint256 _amount,\\n uint256 _currency\\n ) external returns (JBFundingCycle memory fundingCycle, uint256 withdrawnAmount);\\n\\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external;\\n\\n function recordMigration(uint256 _projectId) external returns (uint256 balance);\\n}\\n\",\"keccak256\":\"0xd78929c9371fd7895b829ef5e4ad4b3786523c3580ac3f6f5f25d2b5941c0dd3\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSplitAllocator.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\\nimport '../structs/JBSplitAllocationData.sol';\\n\\n/**\\n @title\\n Split allocator\\n\\n @notice\\n Provide a way to process a single split with extra logic\\n\\n @dev\\n Adheres to:\\n IERC165 for adequate interface integration\\n\\n @dev\\n The contract address should be set as an allocator in the adequate split\\n*/\\ninterface IJBSplitAllocator is IERC165 {\\n /**\\n @notice\\n This function is called by JBPaymentTerminal.distributePayoutOf(..), during the processing of the split including it\\n\\n @dev\\n Critical business logic should be protected by an appropriate access control. The token and/or eth are optimistically transfered\\n to the allocator for its logic.\\n \\n @param _data the data passed by the terminal, as a JBSplitAllocationData struct:\\n address token;\\n uint256 amount;\\n uint256 decimals;\\n uint256 projectId;\\n uint256 group;\\n JBSplit split;\\n */\\n function allocate(JBSplitAllocationData calldata _data) external payable;\\n}\\n\",\"keccak256\":\"0x5efb6f51fc161f42ff58989386ad99028e4039a0ba897d66f358c3dfcf686105\",\"license\":\"MIT\"},\"contracts/interfaces/IJBSplitsStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../structs/JBGroupedSplits.sol';\\nimport './../structs/JBSplit.sol';\\nimport './IJBDirectory.sol';\\nimport './IJBProjects.sol';\\n\\ninterface IJBSplitsStore {\\n event SetSplit(\\n uint256 indexed projectId,\\n uint256 indexed domain,\\n uint256 indexed group,\\n JBSplit split,\\n address caller\\n );\\n\\n function projects() external view returns (IJBProjects);\\n\\n function directory() external view returns (IJBDirectory);\\n\\n function splitsOf(\\n uint256 _projectId,\\n uint256 _domain,\\n uint256 _group\\n ) external view returns (JBSplit[] memory);\\n\\n function set(\\n uint256 _projectId,\\n uint256 _domain,\\n JBGroupedSplits[] memory _groupedSplits\\n ) external;\\n}\\n\",\"keccak256\":\"0x66dab3dd394e318b850401ca92c2963b906cc0ad5562fa5d4f6f850175d1c77a\",\"license\":\"MIT\"},\"contracts/interfaces/IJBToken.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBToken {\\n function projectId() external view returns (uint256);\\n\\n function decimals() external view returns (uint8);\\n\\n function totalSupply(uint256 _projectId) external view returns (uint256);\\n\\n function balanceOf(address _account, uint256 _projectId) external view returns (uint256);\\n\\n function mint(\\n uint256 _projectId,\\n address _account,\\n uint256 _amount\\n ) external;\\n\\n function burn(\\n uint256 _projectId,\\n address _account,\\n uint256 _amount\\n ) external;\\n\\n function approve(\\n uint256,\\n address _spender,\\n uint256 _amount\\n ) external;\\n\\n function transfer(\\n uint256 _projectId,\\n address _to,\\n uint256 _amount\\n ) external;\\n\\n function transferFrom(\\n uint256 _projectId,\\n address _from,\\n address _to,\\n uint256 _amount\\n ) external;\\n}\\n\",\"keccak256\":\"0xe8969210417736c85d71101bf1c0bd8ebbf9d1e62a93e758148bd5709a6c7097\",\"license\":\"MIT\"},\"contracts/interfaces/IJBTokenStore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './IJBFundingCycleStore.sol';\\nimport './IJBProjects.sol';\\nimport './IJBToken.sol';\\n\\ninterface IJBTokenStore {\\n event Issue(\\n uint256 indexed projectId,\\n IJBToken indexed token,\\n string name,\\n string symbol,\\n address caller\\n );\\n\\n event Mint(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 amount,\\n bool tokensWereClaimed,\\n bool preferClaimedTokens,\\n address caller\\n );\\n\\n event Burn(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 amount,\\n uint256 initialUnclaimedBalance,\\n uint256 initialClaimedBalance,\\n bool preferClaimedTokens,\\n address caller\\n );\\n\\n event Claim(\\n address indexed holder,\\n uint256 indexed projectId,\\n uint256 initialUnclaimedBalance,\\n uint256 amount,\\n address caller\\n );\\n\\n event Set(uint256 indexed projectId, IJBToken indexed newToken, address caller);\\n\\n event Transfer(\\n address indexed holder,\\n uint256 indexed projectId,\\n address indexed recipient,\\n uint256 amount,\\n address caller\\n );\\n\\n function tokenOf(uint256 _projectId) external view returns (IJBToken);\\n\\n function projects() external view returns (IJBProjects);\\n\\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\\n\\n function unclaimedBalanceOf(address _holder, uint256 _projectId) external view returns (uint256);\\n\\n function unclaimedTotalSupplyOf(uint256 _projectId) external view returns (uint256);\\n\\n function totalSupplyOf(uint256 _projectId) external view returns (uint256);\\n\\n function balanceOf(address _holder, uint256 _projectId) external view returns (uint256 _result);\\n\\n function issueFor(\\n uint256 _projectId,\\n string calldata _name,\\n string calldata _symbol\\n ) external returns (IJBToken token);\\n\\n function setFor(uint256 _projectId, IJBToken _token) external;\\n\\n function burnFrom(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function mintFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount,\\n bool _preferClaimedTokens\\n ) external;\\n\\n function claimFor(\\n address _holder,\\n uint256 _projectId,\\n uint256 _amount\\n ) external;\\n\\n function transferFrom(\\n address _holder,\\n uint256 _projectId,\\n address _recipient,\\n uint256 _amount\\n ) external;\\n}\\n\",\"keccak256\":\"0x98459e3af050d41dfeffdc97f1c93330207ba450f8ff3613224b49a89eeca9c6\",\"license\":\"MIT\"},\"contracts/interfaces/IJBTokenUriResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IJBTokenUriResolver {\\n function getUri(uint256 _projectId) external view returns (string memory tokenUri);\\n}\\n\",\"keccak256\":\"0xd267fd8ca7c21c2c71794acdb9a98314c33a35fc559e0bf0897a6686d196d174\",\"license\":\"MIT\"},\"contracts/libraries/JBConstants.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/**\\n @notice\\n Global constants used across Juicebox contracts.\\n*/\\nlibrary JBConstants {\\n uint256 public constant MAX_RESERVED_RATE = 10_000;\\n uint256 public constant MAX_REDEMPTION_RATE = 10_000;\\n uint256 public constant MAX_DISCOUNT_RATE = 1_000_000_000;\\n uint256 public constant SPLITS_TOTAL_PERCENT = 1_000_000_000;\\n uint256 public constant MAX_FEE = 1_000_000_000;\\n uint256 public constant MAX_FEE_DISCOUNT = 1_000_000_000;\\n}\\n\",\"keccak256\":\"0x34362846a1cd428a8bdedf4ab6857e11402f345cb87b994b2e7fb6d2474b808d\",\"license\":\"MIT\"},\"contracts/libraries/JBCurrencies.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nlibrary JBCurrencies {\\n uint256 public constant ETH = 1;\\n uint256 public constant USD = 2;\\n}\\n\",\"keccak256\":\"0x7e417ff25c173608ee4fe6d9fc3dcd5e1458c78c889af12bac47b1189a436076\",\"license\":\"MIT\"},\"contracts/libraries/JBFixedPointNumber.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nlibrary JBFixedPointNumber {\\n function adjustDecimals(\\n uint256 _value,\\n uint256 _decimals,\\n uint256 _targetDecimals\\n ) internal pure returns (uint256) {\\n // If decimals need adjusting, multiply or divide the price by the decimal adjuster to get the normalized result.\\n if (_targetDecimals == _decimals) return _value;\\n else if (_targetDecimals > _decimals) return _value * 10**(_targetDecimals - _decimals);\\n else return _value / 10**(_decimals - _targetDecimals);\\n }\\n}\\n\",\"keccak256\":\"0x18efac48269f3a3bd7e9a1c770776f950e0afa86769e6f8b128002c3b8c6742c\",\"license\":\"MIT\"},\"contracts/libraries/JBFundingCycleMetadataResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport './../structs/JBFundingCycle.sol';\\nimport './../structs/JBFundingCycleMetadata.sol';\\nimport './../structs/JBGlobalFundingCycleMetadata.sol';\\nimport './JBConstants.sol';\\nimport './JBGlobalFundingCycleMetadataResolver.sol';\\n\\nlibrary JBFundingCycleMetadataResolver {\\n function global(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (JBGlobalFundingCycleMetadata memory)\\n {\\n return JBGlobalFundingCycleMetadataResolver.expandMetadata(uint8(_fundingCycle.metadata >> 8));\\n }\\n\\n function reservedRate(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n return uint256(uint16(_fundingCycle.metadata >> 24));\\n }\\n\\n function redemptionRate(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n // Redemption rate is a number 0-10000. It's inverse was stored so the most common case of 100% results in no storage needs.\\n return JBConstants.MAX_REDEMPTION_RATE - uint256(uint16(_fundingCycle.metadata >> 40));\\n }\\n\\n function ballotRedemptionRate(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (uint256)\\n {\\n // Redemption rate is a number 0-10000. It's inverse was stored so the most common case of 100% results in no storage needs.\\n return JBConstants.MAX_REDEMPTION_RATE - uint256(uint16(_fundingCycle.metadata >> 56));\\n }\\n\\n function payPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 72) & 1) == 1;\\n }\\n\\n function distributionsPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 73) & 1) == 1;\\n }\\n\\n function redeemPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 74) & 1) == 1;\\n }\\n\\n function burnPaused(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 75) & 1) == 1;\\n }\\n\\n function mintingAllowed(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 76) & 1) == 1;\\n }\\n\\n function terminalMigrationAllowed(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 77) & 1) == 1;\\n }\\n\\n function controllerMigrationAllowed(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 78) & 1) == 1;\\n }\\n\\n function shouldHoldFees(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return ((_fundingCycle.metadata >> 79) & 1) == 1;\\n }\\n\\n function preferClaimedTokenOverride(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 80) & 1) == 1;\\n }\\n\\n function useTotalOverflowForRedemptions(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return ((_fundingCycle.metadata >> 81) & 1) == 1;\\n }\\n\\n function useDataSourceForPay(JBFundingCycle memory _fundingCycle) internal pure returns (bool) {\\n return (_fundingCycle.metadata >> 82) & 1 == 1;\\n }\\n\\n function useDataSourceForRedeem(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (bool)\\n {\\n return (_fundingCycle.metadata >> 83) & 1 == 1;\\n }\\n\\n function dataSource(JBFundingCycle memory _fundingCycle) internal pure returns (address) {\\n return address(uint160(_fundingCycle.metadata >> 84));\\n }\\n\\n function metadata(JBFundingCycle memory _fundingCycle) internal pure returns (uint256) {\\n return uint256(uint8(_fundingCycle.metadata >> 244));\\n }\\n\\n /**\\n @notice\\n Pack the funding cycle metadata.\\n\\n @param _metadata The metadata to validate and pack.\\n\\n @return packed The packed uint256 of all metadata params. The first 8 bits specify the version.\\n */\\n function packFundingCycleMetadata(JBFundingCycleMetadata memory _metadata)\\n internal\\n pure\\n returns (uint256 packed)\\n {\\n // version 1 in the bits 0-7 (8 bits).\\n packed = 1;\\n // global metadta in bits 8-23 (16 bits).\\n packed |=\\n JBGlobalFundingCycleMetadataResolver.packFundingCycleGlobalMetadata(_metadata.global) <<\\n 8;\\n // reserved rate in bits 24-39 (16 bits).\\n packed |= _metadata.reservedRate << 24;\\n // redemption rate in bits 40-55 (16 bits).\\n // redemption rate is a number 0-10000. Store the reverse so the most common case of 100% results in no storage needs.\\n packed |= (JBConstants.MAX_REDEMPTION_RATE - _metadata.redemptionRate) << 40;\\n // ballot redemption rate rate in bits 56-71 (16 bits).\\n // ballot redemption rate is a number 0-10000. Store the reverse so the most common case of 100% results in no storage needs.\\n packed |= (JBConstants.MAX_REDEMPTION_RATE - _metadata.ballotRedemptionRate) << 56;\\n // pause pay in bit 72.\\n if (_metadata.pausePay) packed |= 1 << 72;\\n // pause tap in bit 73.\\n if (_metadata.pauseDistributions) packed |= 1 << 73;\\n // pause redeem in bit 74.\\n if (_metadata.pauseRedeem) packed |= 1 << 74;\\n // pause burn in bit 75.\\n if (_metadata.pauseBurn) packed |= 1 << 75;\\n // allow minting in bit 76.\\n if (_metadata.allowMinting) packed |= 1 << 76;\\n // allow terminal migration in bit 77.\\n if (_metadata.allowTerminalMigration) packed |= 1 << 77;\\n // allow controller migration in bit 78.\\n if (_metadata.allowControllerMigration) packed |= 1 << 78;\\n // hold fees in bit 79.\\n if (_metadata.holdFees) packed |= 1 << 79;\\n // prefer claimed token override in bit 80.\\n if (_metadata.preferClaimedTokenOverride) packed |= 1 << 80;\\n // useTotalOverflowForRedemptions in bit 81.\\n if (_metadata.useTotalOverflowForRedemptions) packed |= 1 << 81;\\n // use pay data source in bit 82.\\n if (_metadata.useDataSourceForPay) packed |= 1 << 82;\\n // use redeem data source in bit 83.\\n if (_metadata.useDataSourceForRedeem) packed |= 1 << 83;\\n // data source address in bits 84-243.\\n packed |= uint256(uint160(address(_metadata.dataSource))) << 84;\\n // metadata in bits 244-252 (8 bits).\\n packed |= _metadata.metadata << 244;\\n }\\n\\n /**\\n @notice\\n Expand the funding cycle metadata.\\n\\n @param _fundingCycle The funding cycle having its metadata expanded.\\n\\n @return metadata The metadata object.\\n */\\n function expandMetadata(JBFundingCycle memory _fundingCycle)\\n internal\\n pure\\n returns (JBFundingCycleMetadata memory)\\n {\\n return\\n JBFundingCycleMetadata(\\n global(_fundingCycle),\\n reservedRate(_fundingCycle),\\n redemptionRate(_fundingCycle),\\n ballotRedemptionRate(_fundingCycle),\\n payPaused(_fundingCycle),\\n distributionsPaused(_fundingCycle),\\n redeemPaused(_fundingCycle),\\n burnPaused(_fundingCycle),\\n mintingAllowed(_fundingCycle),\\n terminalMigrationAllowed(_fundingCycle),\\n controllerMigrationAllowed(_fundingCycle),\\n shouldHoldFees(_fundingCycle),\\n preferClaimedTokenOverride(_fundingCycle),\\n useTotalOverflowForRedemptions(_fundingCycle),\\n useDataSourceForPay(_fundingCycle),\\n useDataSourceForRedeem(_fundingCycle),\\n dataSource(_fundingCycle),\\n metadata(_fundingCycle)\\n );\\n }\\n}\\n\",\"keccak256\":\"0x3d045c38593102cfb6ac67f3ddf2232e1ff5518d6d021423ae2681387599fbd3\",\"license\":\"MIT\"},\"contracts/libraries/JBGlobalFundingCycleMetadataResolver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.16;\\n\\nimport './../structs/JBFundingCycleMetadata.sol';\\n\\nlibrary JBGlobalFundingCycleMetadataResolver {\\n function setTerminalsAllowed(uint8 _data) internal pure returns (bool) {\\n return (_data & 1) == 1;\\n }\\n\\n function setControllerAllowed(uint8 _data) internal pure returns (bool) {\\n return ((_data >> 1) & 1) == 1;\\n }\\n\\n function transfersPaused(uint8 _data) internal pure returns (bool) {\\n return ((_data >> 2) & 1) == 1;\\n }\\n\\n /**\\n @notice\\n Pack the global funding cycle metadata.\\n\\n @param _metadata The metadata to validate and pack.\\n\\n @return packed The packed uint256 of all global metadata params. The first 8 bits specify the version.\\n */\\n function packFundingCycleGlobalMetadata(JBGlobalFundingCycleMetadata memory _metadata)\\n internal\\n pure\\n returns (uint256 packed)\\n {\\n // allow set terminals in bit 0.\\n if (_metadata.allowSetTerminals) packed |= 1;\\n // allow set controller in bit 1.\\n if (_metadata.allowSetController) packed |= 1 << 1;\\n // pause transfers in bit 2.\\n if (_metadata.pauseTransfers) packed |= 1 << 2;\\n }\\n\\n /**\\n @notice\\n Expand the global funding cycle metadata.\\n\\n @param _packedMetadata The packed metadata to expand.\\n\\n @return metadata The global metadata object.\\n */\\n function expandMetadata(uint8 _packedMetadata)\\n internal\\n pure\\n returns (JBGlobalFundingCycleMetadata memory metadata)\\n {\\n return\\n JBGlobalFundingCycleMetadata(\\n setTerminalsAllowed(_packedMetadata),\\n setControllerAllowed(_packedMetadata),\\n transfersPaused(_packedMetadata)\\n );\\n }\\n}\\n\",\"keccak256\":\"0x0d998f938026edeb755987a79421267cf860801161b5f171206a200b60f1061f\",\"license\":\"MIT\"},\"contracts/structs/JBDidPayData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member payer The address from which the payment originated.\\n @member projectId The ID of the project for which the payment was made.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the payment is being made.\\n @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.\\n @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.\\n @member projectTokenCount The number of project tokens minted for the beneficiary.\\n @member beneficiary The address to which the tokens were minted.\\n @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.\\n @member memo The memo that is being emitted alongside the payment.\\n @member metadata Extra data to send to the delegate.\\n*/\\nstruct JBDidPayData {\\n address payer;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n JBTokenAmount amount;\\n JBTokenAmount forwardedAmount;\\n uint256 projectTokenCount;\\n address beneficiary;\\n bool preferClaimedTokens;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0xf3c664309b37790f16047ae97b0459889ae0242dfcde7fc8902c8d10c7f8e6b6\",\"license\":\"MIT\"},\"contracts/structs/JBDidRedeemData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member holder The holder of the tokens being redeemed.\\n @member projectId The ID of the project with which the redeemed tokens are associated.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the redemption is being made.\\n @member projectTokenCount The number of project tokens being redeemed.\\n @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.\\n @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.\\n @member beneficiary The address to which the reclaimed amount will be sent.\\n @member memo The memo that is being emitted alongside the redemption.\\n @member metadata Extra data to send to the delegate.\\n*/\\nstruct JBDidRedeemData {\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 projectTokenCount;\\n JBTokenAmount reclaimedAmount;\\n JBTokenAmount forwardedAmount;\\n address payable beneficiary;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0xe2c401f39723a7ce915b8bef328744c66daaf57460843964b941456c2258a412\",\"license\":\"MIT\"},\"contracts/structs/JBFundAccessConstraints.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBPaymentTerminal.sol';\\n\\n/** \\n @member terminal The terminal within which the distribution limit and the overflow allowance applies.\\n @member token The token for which the fund access constraints apply.\\n @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.\\n @member distributionLimitCurrency The currency of the distribution limit.\\n @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.\\n @member overflowAllowanceCurrency The currency of the overflow allowance.\\n*/\\nstruct JBFundAccessConstraints {\\n IJBPaymentTerminal terminal;\\n address token;\\n uint256 distributionLimit;\\n uint256 distributionLimitCurrency;\\n uint256 overflowAllowance;\\n uint256 overflowAllowanceCurrency;\\n}\\n\",\"keccak256\":\"0x85ebaa57b788cbdedc7a3d0eec4892eda5d79db7c1a6103797f10d0d989775b2\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycle.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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.\\n @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.\\n @member basedOn The `configuration` of the funding cycle that was active when this cycle was created.\\n @member start The timestamp marking the moment from which the funding cycle is considered active. It is a unix timestamp measured in seconds.\\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n @member metadata Extra data that can be associated with a funding cycle.\\n*/\\nstruct JBFundingCycle {\\n uint256 number;\\n uint256 configuration;\\n uint256 basedOn;\\n uint256 start;\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n uint256 metadata;\\n}\\n\",\"keccak256\":\"0xcdd3ac9b6fa67e62ada88d09b73bc35ade1cd77d43db712289266a788928b4c2\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycleData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBFundingCycleBallot.sol';\\n\\n/** \\n @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 \\u2013 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`.\\n @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.\\n @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`.\\n @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.\\n*/\\nstruct JBFundingCycleData {\\n uint256 duration;\\n uint256 weight;\\n uint256 discountRate;\\n IJBFundingCycleBallot ballot;\\n}\\n\",\"keccak256\":\"0x2aa6368bf4dfc5797e8b02a978293de0c777fae2658de2c825a103587240f3b0\",\"license\":\"MIT\"},\"contracts/structs/JBFundingCycleMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBGlobalFundingCycleMetadata.sol';\\n\\n/** \\n @member global Data used globally in non-migratable ecosystem contracts.\\n @member reservedRate The reserved rate of the funding cycle. This number is a percentage calculated out of `JBConstants.MAX_RESERVED_RATE`.\\n @member redemptionRate The redemption rate of the funding cycle. This number is a percentage calculated out of `JBConstants.MAX_REDEMPTION_RATE`.\\n @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`.\\n @member pausePay A flag indicating if the pay functionality should be paused during the funding cycle.\\n @member pauseDistributions A flag indicating if the distribute functionality should be paused during the funding cycle.\\n @member pauseRedeem A flag indicating if the redeem functionality should be paused during the funding cycle.\\n @member pauseBurn A flag indicating if the burn functionality should be paused during the funding cycle.\\n @member allowMinting A flag indicating if minting tokens should be allowed during this funding cycle.\\n @member allowTerminalMigration A flag indicating if migrating terminals should be allowed during this funding cycle.\\n @member allowControllerMigration A flag indicating if migrating controllers should be allowed during this funding cycle.\\n @member holdFees A flag indicating if fees should be held during this funding cycle.\\n @member preferClaimedTokenOverride A flag indicating if claimed tokens should always be prefered to unclaimed tokens when minting.\\n @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.\\n @member useDataSourceForPay A flag indicating if the data source should be used for pay transactions during this funding cycle.\\n @member useDataSourceForRedeem A flag indicating if the data source should be used for redeem transactions during this funding cycle.\\n @member dataSource The data source to use during this funding cycle.\\n @member metadata Metadata of the metadata, up to uint8 in size.\\n*/\\nstruct JBFundingCycleMetadata {\\n JBGlobalFundingCycleMetadata global;\\n uint256 reservedRate;\\n uint256 redemptionRate;\\n uint256 ballotRedemptionRate;\\n bool pausePay;\\n bool pauseDistributions;\\n bool pauseRedeem;\\n bool pauseBurn;\\n bool allowMinting;\\n bool allowTerminalMigration;\\n bool allowControllerMigration;\\n bool holdFees;\\n bool preferClaimedTokenOverride;\\n bool useTotalOverflowForRedemptions;\\n bool useDataSourceForPay;\\n bool useDataSourceForRedeem;\\n address dataSource;\\n uint256 metadata;\\n}\\n\",\"keccak256\":\"0x783604440cac8d176332eab28166f188ee5c230378c08cfc95fea4f7187dc77d\",\"license\":\"MIT\"},\"contracts/structs/JBGlobalFundingCycleMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member allowSetTerminals A flag indicating if setting terminals should be allowed during this funding cycle.\\n @member allowSetController A flag indicating if setting a new controller should be allowed during this funding cycle.\\n @member pauseTransfers A flag indicating if the project token transfer functionality should be paused during the funding cycle.\\n*/\\nstruct JBGlobalFundingCycleMetadata {\\n bool allowSetTerminals;\\n bool allowSetController;\\n bool pauseTransfers;\\n}\\n\",\"keccak256\":\"0x05d85530305fec6d6eca54cdbc2cd9110cbda0146598032b0203aa4b622944ff\",\"license\":\"MIT\"},\"contracts/structs/JBGroupedSplits.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBSplit.sol';\\n\\n/** \\n @member group The group indentifier.\\n @member splits The splits to associate with the group.\\n*/\\nstruct JBGroupedSplits {\\n uint256 group;\\n JBSplit[] splits;\\n}\\n\",\"keccak256\":\"0x80be1b220da4ac04851ea540ebb94c1ec2b0442ec5bd1e88fdf78a56becd8b5a\",\"license\":\"MIT\"},\"contracts/structs/JBPayDelegateAllocation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '../interfaces/IJBPayDelegate.sol';\\n\\n/** \\n @member delegate A delegate contract to use for subsequent calls.\\n @member amount The amount to send to the delegate.\\n*/\\nstruct JBPayDelegateAllocation {\\n IJBPayDelegate delegate;\\n uint256 amount;\\n}\\n\",\"keccak256\":\"0xb4e558dc62231d89e9b48998012577d22c3e52b58e23401f22d9096827f6ea0c\",\"license\":\"MIT\"},\"contracts/structs/JBPayParamsData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBPaymentTerminal.sol';\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member terminal The terminal that is facilitating the payment.\\n @member payer The address from which the payment originated.\\n @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.\\n @member projectId The ID of the project being paid.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the payment is being made.\\n @member beneficiary The specified address that should be the beneficiary of anything that results from the payment.\\n @member weight The weight of the funding cycle during which the payment is being made.\\n @member reservedRate The reserved rate of the funding cycle during which the payment is being made.\\n @member memo The memo that was sent alongside the payment.\\n @member metadata Extra data provided by the payer.\\n*/\\nstruct JBPayParamsData {\\n IJBPaymentTerminal terminal;\\n address payer;\\n JBTokenAmount amount;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n address beneficiary;\\n uint256 weight;\\n uint256 reservedRate;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0x05007b26feb5d9a026b883c6d734a341b5a49ef7b8215fb40507882e2c14e24d\",\"license\":\"MIT\"},\"contracts/structs/JBProjectMetadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/** \\n @member content The metadata content.\\n @member domain The domain within which the metadata applies.\\n*/\\nstruct JBProjectMetadata {\\n string content;\\n uint256 domain;\\n}\\n\",\"keccak256\":\"0x90ad7b1014c0a9f945fe7a2efde9d5de41e40574fa27969070b1d2ff52033ea0\",\"license\":\"MIT\"},\"contracts/structs/JBRedeemParamsData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBPaymentTerminal.sol';\\nimport './JBTokenAmount.sol';\\n\\n/** \\n @member terminal The terminal that is facilitating the redemption.\\n @member holder The holder of the tokens being redeemed.\\n @member projectId The ID of the project whos tokens are being redeemed.\\n @member currentFundingCycleConfiguration The configuration of the funding cycle during which the redemption is being made.\\n @member tokenCount The proposed number of tokens being redeemed, as a fixed point number with 18 decimals.\\n @member totalSupply The total supply of tokens used in the calculation, as a fixed point number with 18 decimals.\\n @member overflow The amount of overflow used in the reclaim amount calculation.\\n @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.\\n @member useTotalOverflow If overflow across all of a project's terminals is being used when making redemptions.\\n @member redemptionRate The redemption rate of the funding cycle during which the redemption is being made.\\n @member memo The proposed memo that is being emitted alongside the redemption.\\n @member metadata Extra data provided by the redeemer.\\n*/\\nstruct JBRedeemParamsData {\\n IJBPaymentTerminal terminal;\\n address holder;\\n uint256 projectId;\\n uint256 currentFundingCycleConfiguration;\\n uint256 tokenCount;\\n uint256 totalSupply;\\n uint256 overflow;\\n JBTokenAmount reclaimAmount;\\n bool useTotalOverflow;\\n uint256 redemptionRate;\\n string memo;\\n bytes metadata;\\n}\\n\",\"keccak256\":\"0x5065a824ebb34952f016c6dfa47e8a7ac28427b719470e74a41022c11ace7788\",\"license\":\"MIT\"},\"contracts/structs/JBRedemptionDelegateAllocation.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport '../interfaces/IJBRedemptionDelegate.sol';\\n\\n/** \\n @member delegate A delegate contract to use for subsequent calls.\\n @member amount The amount to send to the delegate.\\n*/\\nstruct JBRedemptionDelegateAllocation {\\n IJBRedemptionDelegate delegate;\\n uint256 amount;\\n}\\n\",\"keccak256\":\"0x10c29d33dd0d875a0d4692a2b9a9355c2ebf433cc06a9a60253d4366b60d4d31\",\"license\":\"MIT\"},\"contracts/structs/JBSplit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './../interfaces/IJBSplitAllocator.sol';\\n\\n/** \\n @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.\\n @member preferAddToBalance A flag indicating if a distribution to a project should prefer triggering it's addToBalance function instead of its pay function.\\n @member percent The percent of the whole group that this split occupies. This number is out of `JBConstants.SPLITS_TOTAL_PERCENT`.\\n @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.\\n @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.\\n @member lockedUntil Specifies if the split should be unchangeable until the specified time, with the exception of extending the locked period.\\n @member allocator If an allocator is specified, funds will be sent to the allocator contract along with all properties of this split.\\n*/\\nstruct JBSplit {\\n bool preferClaimed;\\n bool preferAddToBalance;\\n uint256 percent;\\n uint256 projectId;\\n address payable beneficiary;\\n uint256 lockedUntil;\\n IJBSplitAllocator allocator;\\n}\\n\",\"keccak256\":\"0xc80a16606da8abf76d0f73abc38aee041e24f29342c1939018f70c286e89f105\",\"license\":\"MIT\"},\"contracts/structs/JBSplitAllocationData.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport './JBSplit.sol';\\n\\n/** \\n @member token The token being sent to the split allocator.\\n @member amount The amount being sent to the split allocator, as a fixed point number.\\n @member decimals The number of decimals in the amount.\\n @member projectId The project to which the split belongs.\\n @member group The group to which the split belongs.\\n @member split The split that caused the allocation.\\n*/\\nstruct JBSplitAllocationData {\\n address token;\\n uint256 amount;\\n uint256 decimals;\\n uint256 projectId;\\n uint256 group;\\n JBSplit split;\\n}\\n\",\"keccak256\":\"0x39f5c41bd31d36774744698ac94484b6cab62d7038df2f29d947668959782e63\",\"license\":\"MIT\"},\"contracts/structs/JBTokenAmount.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/* \\n @member token The token the payment was made in.\\n @member value The amount of tokens that was paid, as a fixed point number.\\n @member decimals The number of decimals included in the value fixed point number.\\n @member currency The expected currency of the value.\\n**/\\nstruct JBTokenAmount {\\n address token;\\n uint256 value;\\n uint256 decimals;\\n uint256 currency;\\n}\\n\",\"keccak256\":\"0x4a778e779ba257ba5638c5469e07a4d21b55a3128d56db5a0fdfacb1f3301c51\",\"license\":\"MIT\"},\"prb-math/contracts/PRBMath.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity >=0.8.4;\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivFixedPointOverflow(uint256 prod1);\\n\\n/// @notice Emitted when the result overflows uint256.\\nerror PRBMath__MulDivOverflow(uint256 prod1, uint256 denominator);\\n\\n/// @notice Emitted when one of the inputs is type(int256).min.\\nerror PRBMath__MulDivSignedInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows int256.\\nerror PRBMath__MulDivSignedOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is MIN_SD59x18.\\nerror PRBMathSD59x18__AbsInputTooSmall();\\n\\n/// @notice Emitted when ceiling a number overflows SD59x18.\\nerror PRBMathSD59x18__CeilOverflow(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__DivInputTooSmall();\\n\\n/// @notice Emitted when one of the intermediary unsigned results overflows SD59x18.\\nerror PRBMathSD59x18__DivOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathSD59x18__ExpInputTooBig(int256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathSD59x18__Exp2InputTooBig(int256 x);\\n\\n/// @notice Emitted when flooring a number underflows SD59x18.\\nerror PRBMathSD59x18__FloorUnderflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format overflows SD59x18.\\nerror PRBMathSD59x18__FromIntOverflow(int256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format underflows SD59x18.\\nerror PRBMathSD59x18__FromIntUnderflow(int256 x);\\n\\n/// @notice Emitted when the product of the inputs is negative.\\nerror PRBMathSD59x18__GmNegativeProduct(int256 x, int256 y);\\n\\n/// @notice Emitted when multiplying the inputs overflows SD59x18.\\nerror PRBMathSD59x18__GmOverflow(int256 x, int256 y);\\n\\n/// @notice Emitted when the input is less than or equal to zero.\\nerror PRBMathSD59x18__LogInputTooSmall(int256 x);\\n\\n/// @notice Emitted when one of the inputs is MIN_SD59x18.\\nerror PRBMathSD59x18__MulInputTooSmall();\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__MulOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the intermediary absolute result overflows SD59x18.\\nerror PRBMathSD59x18__PowuOverflow(uint256 rAbs);\\n\\n/// @notice Emitted when the input is negative.\\nerror PRBMathSD59x18__SqrtNegativeInput(int256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows SD59x18.\\nerror PRBMathSD59x18__SqrtOverflow(int256 x);\\n\\n/// @notice Emitted when addition overflows UD60x18.\\nerror PRBMathUD60x18__AddOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when ceiling a number overflows UD60x18.\\nerror PRBMathUD60x18__CeilOverflow(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 133.084258667509499441.\\nerror PRBMathUD60x18__ExpInputTooBig(uint256 x);\\n\\n/// @notice Emitted when the input is greater than 192.\\nerror PRBMathUD60x18__Exp2InputTooBig(uint256 x);\\n\\n/// @notice Emitted when converting a basic integer to the fixed-point format format overflows UD60x18.\\nerror PRBMathUD60x18__FromUintOverflow(uint256 x);\\n\\n/// @notice Emitted when multiplying the inputs overflows UD60x18.\\nerror PRBMathUD60x18__GmOverflow(uint256 x, uint256 y);\\n\\n/// @notice Emitted when the input is less than 1.\\nerror PRBMathUD60x18__LogInputTooSmall(uint256 x);\\n\\n/// @notice Emitted when the calculating the square root overflows UD60x18.\\nerror PRBMathUD60x18__SqrtOverflow(uint256 x);\\n\\n/// @notice Emitted when subtraction underflows UD60x18.\\nerror PRBMathUD60x18__SubUnderflow(uint256 x, uint256 y);\\n\\n/// @dev Common mathematical functions used in both PRBMathSD59x18 and PRBMathUD60x18. Note that this shared library\\n/// does not always assume the signed 59.18-decimal fixed-point or the unsigned 60.18-decimal fixed-point\\n/// representation. When it does not, it is explicitly mentioned in the NatSpec documentation.\\nlibrary PRBMath {\\n /// STRUCTS ///\\n\\n struct SD59x18 {\\n int256 value;\\n }\\n\\n struct UD60x18 {\\n uint256 value;\\n }\\n\\n /// STORAGE ///\\n\\n /// @dev How many trailing decimals can be represented.\\n uint256 internal constant SCALE = 1e18;\\n\\n /// @dev Largest power of two divisor of SCALE.\\n uint256 internal constant SCALE_LPOTD = 262144;\\n\\n /// @dev SCALE inverted mod 2^256.\\n uint256 internal constant SCALE_INVERSE =\\n 78156646155174841979727994598816262306175212592076161876661_508869554232690281;\\n\\n /// FUNCTIONS ///\\n\\n /// @notice Calculates the binary exponent of x using the binary fraction method.\\n /// @dev Has to use 192.64-bit fixed-point numbers.\\n /// See https://ethereum.stackexchange.com/a/96594/24693.\\n /// @param x The exponent as an unsigned 192.64-bit fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function exp2(uint256 x) internal pure returns (uint256 result) {\\n unchecked {\\n // Start from 0.5 in the 192.64-bit fixed-point format.\\n result = 0x800000000000000000000000000000000000000000000000;\\n\\n // Multiply the result by root(2, 2^-i) when the bit at position i is 1. None of the intermediary results overflows\\n // because the initial result is 2^191 and all magic factors are less than 2^65.\\n if (x & 0x8000000000000000 > 0) {\\n result = (result * 0x16A09E667F3BCC909) >> 64;\\n }\\n if (x & 0x4000000000000000 > 0) {\\n result = (result * 0x1306FE0A31B7152DF) >> 64;\\n }\\n if (x & 0x2000000000000000 > 0) {\\n result = (result * 0x1172B83C7D517ADCE) >> 64;\\n }\\n if (x & 0x1000000000000000 > 0) {\\n result = (result * 0x10B5586CF9890F62A) >> 64;\\n }\\n if (x & 0x800000000000000 > 0) {\\n result = (result * 0x1059B0D31585743AE) >> 64;\\n }\\n if (x & 0x400000000000000 > 0) {\\n result = (result * 0x102C9A3E778060EE7) >> 64;\\n }\\n if (x & 0x200000000000000 > 0) {\\n result = (result * 0x10163DA9FB33356D8) >> 64;\\n }\\n if (x & 0x100000000000000 > 0) {\\n result = (result * 0x100B1AFA5ABCBED61) >> 64;\\n }\\n if (x & 0x80000000000000 > 0) {\\n result = (result * 0x10058C86DA1C09EA2) >> 64;\\n }\\n if (x & 0x40000000000000 > 0) {\\n result = (result * 0x1002C605E2E8CEC50) >> 64;\\n }\\n if (x & 0x20000000000000 > 0) {\\n result = (result * 0x100162F3904051FA1) >> 64;\\n }\\n if (x & 0x10000000000000 > 0) {\\n result = (result * 0x1000B175EFFDC76BA) >> 64;\\n }\\n if (x & 0x8000000000000 > 0) {\\n result = (result * 0x100058BA01FB9F96D) >> 64;\\n }\\n if (x & 0x4000000000000 > 0) {\\n result = (result * 0x10002C5CC37DA9492) >> 64;\\n }\\n if (x & 0x2000000000000 > 0) {\\n result = (result * 0x1000162E525EE0547) >> 64;\\n }\\n if (x & 0x1000000000000 > 0) {\\n result = (result * 0x10000B17255775C04) >> 64;\\n }\\n if (x & 0x800000000000 > 0) {\\n result = (result * 0x1000058B91B5BC9AE) >> 64;\\n }\\n if (x & 0x400000000000 > 0) {\\n result = (result * 0x100002C5C89D5EC6D) >> 64;\\n }\\n if (x & 0x200000000000 > 0) {\\n result = (result * 0x10000162E43F4F831) >> 64;\\n }\\n if (x & 0x100000000000 > 0) {\\n result = (result * 0x100000B1721BCFC9A) >> 64;\\n }\\n if (x & 0x80000000000 > 0) {\\n result = (result * 0x10000058B90CF1E6E) >> 64;\\n }\\n if (x & 0x40000000000 > 0) {\\n result = (result * 0x1000002C5C863B73F) >> 64;\\n }\\n if (x & 0x20000000000 > 0) {\\n result = (result * 0x100000162E430E5A2) >> 64;\\n }\\n if (x & 0x10000000000 > 0) {\\n result = (result * 0x1000000B172183551) >> 64;\\n }\\n if (x & 0x8000000000 > 0) {\\n result = (result * 0x100000058B90C0B49) >> 64;\\n }\\n if (x & 0x4000000000 > 0) {\\n result = (result * 0x10000002C5C8601CC) >> 64;\\n }\\n if (x & 0x2000000000 > 0) {\\n result = (result * 0x1000000162E42FFF0) >> 64;\\n }\\n if (x & 0x1000000000 > 0) {\\n result = (result * 0x10000000B17217FBB) >> 64;\\n }\\n if (x & 0x800000000 > 0) {\\n result = (result * 0x1000000058B90BFCE) >> 64;\\n }\\n if (x & 0x400000000 > 0) {\\n result = (result * 0x100000002C5C85FE3) >> 64;\\n }\\n if (x & 0x200000000 > 0) {\\n result = (result * 0x10000000162E42FF1) >> 64;\\n }\\n if (x & 0x100000000 > 0) {\\n result = (result * 0x100000000B17217F8) >> 64;\\n }\\n if (x & 0x80000000 > 0) {\\n result = (result * 0x10000000058B90BFC) >> 64;\\n }\\n if (x & 0x40000000 > 0) {\\n result = (result * 0x1000000002C5C85FE) >> 64;\\n }\\n if (x & 0x20000000 > 0) {\\n result = (result * 0x100000000162E42FF) >> 64;\\n }\\n if (x & 0x10000000 > 0) {\\n result = (result * 0x1000000000B17217F) >> 64;\\n }\\n if (x & 0x8000000 > 0) {\\n result = (result * 0x100000000058B90C0) >> 64;\\n }\\n if (x & 0x4000000 > 0) {\\n result = (result * 0x10000000002C5C860) >> 64;\\n }\\n if (x & 0x2000000 > 0) {\\n result = (result * 0x1000000000162E430) >> 64;\\n }\\n if (x & 0x1000000 > 0) {\\n result = (result * 0x10000000000B17218) >> 64;\\n }\\n if (x & 0x800000 > 0) {\\n result = (result * 0x1000000000058B90C) >> 64;\\n }\\n if (x & 0x400000 > 0) {\\n result = (result * 0x100000000002C5C86) >> 64;\\n }\\n if (x & 0x200000 > 0) {\\n result = (result * 0x10000000000162E43) >> 64;\\n }\\n if (x & 0x100000 > 0) {\\n result = (result * 0x100000000000B1721) >> 64;\\n }\\n if (x & 0x80000 > 0) {\\n result = (result * 0x10000000000058B91) >> 64;\\n }\\n if (x & 0x40000 > 0) {\\n result = (result * 0x1000000000002C5C8) >> 64;\\n }\\n if (x & 0x20000 > 0) {\\n result = (result * 0x100000000000162E4) >> 64;\\n }\\n if (x & 0x10000 > 0) {\\n result = (result * 0x1000000000000B172) >> 64;\\n }\\n if (x & 0x8000 > 0) {\\n result = (result * 0x100000000000058B9) >> 64;\\n }\\n if (x & 0x4000 > 0) {\\n result = (result * 0x10000000000002C5D) >> 64;\\n }\\n if (x & 0x2000 > 0) {\\n result = (result * 0x1000000000000162E) >> 64;\\n }\\n if (x & 0x1000 > 0) {\\n result = (result * 0x10000000000000B17) >> 64;\\n }\\n if (x & 0x800 > 0) {\\n result = (result * 0x1000000000000058C) >> 64;\\n }\\n if (x & 0x400 > 0) {\\n result = (result * 0x100000000000002C6) >> 64;\\n }\\n if (x & 0x200 > 0) {\\n result = (result * 0x10000000000000163) >> 64;\\n }\\n if (x & 0x100 > 0) {\\n result = (result * 0x100000000000000B1) >> 64;\\n }\\n if (x & 0x80 > 0) {\\n result = (result * 0x10000000000000059) >> 64;\\n }\\n if (x & 0x40 > 0) {\\n result = (result * 0x1000000000000002C) >> 64;\\n }\\n if (x & 0x20 > 0) {\\n result = (result * 0x10000000000000016) >> 64;\\n }\\n if (x & 0x10 > 0) {\\n result = (result * 0x1000000000000000B) >> 64;\\n }\\n if (x & 0x8 > 0) {\\n result = (result * 0x10000000000000006) >> 64;\\n }\\n if (x & 0x4 > 0) {\\n result = (result * 0x10000000000000003) >> 64;\\n }\\n if (x & 0x2 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n if (x & 0x1 > 0) {\\n result = (result * 0x10000000000000001) >> 64;\\n }\\n\\n // We're doing two things at the same time:\\n //\\n // 1. Multiply the result by 2^n + 1, where \\\"2^n\\\" is the integer part and the one is added to account for\\n // the fact that we initially set the result to 0.5. This is accomplished by subtracting from 191\\n // rather than 192.\\n // 2. Convert the result to the unsigned 60.18-decimal fixed-point format.\\n //\\n // This works because 2^(191-ip) = 2^ip / 2^191, where \\\"ip\\\" is the integer part \\\"2^n\\\".\\n result *= SCALE;\\n result >>= (191 - (x >> 64));\\n }\\n }\\n\\n /// @notice Finds the zero-based index of the first one in the binary representation of x.\\n /// @dev See the note on msb in the \\\"Find First Set\\\" Wikipedia article https://en.wikipedia.org/wiki/Find_first_set\\n /// @param x The uint256 number for which to find the index of the most significant bit.\\n /// @return msb The index of the most significant bit as an uint256.\\n function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {\\n if (x >= 2**128) {\\n x >>= 128;\\n msb += 128;\\n }\\n if (x >= 2**64) {\\n x >>= 64;\\n msb += 64;\\n }\\n if (x >= 2**32) {\\n x >>= 32;\\n msb += 32;\\n }\\n if (x >= 2**16) {\\n x >>= 16;\\n msb += 16;\\n }\\n if (x >= 2**8) {\\n x >>= 8;\\n msb += 8;\\n }\\n if (x >= 2**4) {\\n x >>= 4;\\n msb += 4;\\n }\\n if (x >= 2**2) {\\n x >>= 2;\\n msb += 2;\\n }\\n if (x >= 2**1) {\\n // No need to shift x any more.\\n msb += 1;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.\\n ///\\n /// Requirements:\\n /// - The denominator cannot be zero.\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The multiplicand as an uint256.\\n /// @param y The multiplier as an uint256.\\n /// @param denominator The divisor as an uint256.\\n /// @return result The result as an uint256.\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n unchecked {\\n result = prod0 / denominator;\\n }\\n return result;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n if (prod1 >= denominator) {\\n revert PRBMath__MulDivOverflow(prod1, denominator);\\n }\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n unchecked {\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 lpotdod = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by lpotdod.\\n denominator := div(denominator, lpotdod)\\n\\n // Divide [prod1 prod0] by lpotdod.\\n prod0 := div(prod0, lpotdod)\\n\\n // Flip lpotdod such that it is 2^256 / lpotdod. If lpotdod is zero, then it becomes one.\\n lpotdod := add(div(sub(0, lpotdod), lpotdod), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * lpotdod;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f71e18) with full precision.\\n ///\\n /// @dev Variant of \\\"mulDiv\\\" with constant folding, i.e. in which the denominator is always 1e18. Before returning the\\n /// final result, we add 1 if (x * y) % SCALE >= HALF_SCALE. Without this, 6.6e-19 would be truncated to 0 instead of\\n /// being rounded to 1e-18. See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717.\\n ///\\n /// Requirements:\\n /// - The result must fit within uint256.\\n ///\\n /// Caveats:\\n /// - The body is purposely left uncommented; see the NatSpec comments in \\\"PRBMath.mulDiv\\\" to understand how this works.\\n /// - It is assumed that the result can never be type(uint256).max when x and y solve the following two equations:\\n /// 1. x * y = type(uint256).max * SCALE\\n /// 2. (x * y) % SCALE >= SCALE / 2\\n ///\\n /// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.\\n /// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.\\n /// @return result The result as an unsigned 60.18-decimal fixed-point number.\\n function mulDivFixedPoint(uint256 x, uint256 y) internal pure returns (uint256 result) {\\n uint256 prod0;\\n uint256 prod1;\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n if (prod1 >= SCALE) {\\n revert PRBMath__MulDivFixedPointOverflow(prod1);\\n }\\n\\n uint256 remainder;\\n uint256 roundUpUnit;\\n assembly {\\n remainder := mulmod(x, y, SCALE)\\n roundUpUnit := gt(remainder, 499999999999999999)\\n }\\n\\n if (prod1 == 0) {\\n unchecked {\\n result = (prod0 / SCALE) + roundUpUnit;\\n return result;\\n }\\n }\\n\\n assembly {\\n result := add(\\n mul(\\n or(\\n div(sub(prod0, remainder), SCALE_LPOTD),\\n mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, SCALE_LPOTD), SCALE_LPOTD), 1))\\n ),\\n SCALE_INVERSE\\n ),\\n roundUpUnit\\n )\\n }\\n }\\n\\n /// @notice Calculates floor(x*y\\u00f7denominator) with full precision.\\n ///\\n /// @dev An extension of \\\"mulDiv\\\" for signed numbers. Works by computing the signs and the absolute values separately.\\n ///\\n /// Requirements:\\n /// - None of the inputs can be type(int256).min.\\n /// - The result must fit within int256.\\n ///\\n /// @param x The multiplicand as an int256.\\n /// @param y The multiplier as an int256.\\n /// @param denominator The divisor as an int256.\\n /// @return result The result as an int256.\\n function mulDivSigned(\\n int256 x,\\n int256 y,\\n int256 denominator\\n ) internal pure returns (int256 result) {\\n if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {\\n revert PRBMath__MulDivSignedInputTooSmall();\\n }\\n\\n // Get hold of the absolute values of x, y and the denominator.\\n uint256 ax;\\n uint256 ay;\\n uint256 ad;\\n unchecked {\\n ax = x < 0 ? uint256(-x) : uint256(x);\\n ay = y < 0 ? uint256(-y) : uint256(y);\\n ad = denominator < 0 ? uint256(-denominator) : uint256(denominator);\\n }\\n\\n // Compute the absolute value of (x*y)\\u00f7denominator. The result must fit within int256.\\n uint256 rAbs = mulDiv(ax, ay, ad);\\n if (rAbs > uint256(type(int256).max)) {\\n revert PRBMath__MulDivSignedOverflow(rAbs);\\n }\\n\\n // Get the signs of x, y and the denominator.\\n uint256 sx;\\n uint256 sy;\\n uint256 sd;\\n assembly {\\n sx := sgt(x, sub(0, 1))\\n sy := sgt(y, sub(0, 1))\\n sd := sgt(denominator, sub(0, 1))\\n }\\n\\n // XOR over sx, sy and sd. This is checking whether there are one or three negative signs in the inputs.\\n // If yes, the result should be negative.\\n result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs);\\n }\\n\\n /// @notice Calculates the square root of x, rounding down.\\n /// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.\\n ///\\n /// Caveats:\\n /// - This function does not work with fixed-point numbers.\\n ///\\n /// @param x The uint256 number for which to calculate the square root.\\n /// @return result The result as an uint256.\\n function sqrt(uint256 x) internal pure returns (uint256 result) {\\n if (x == 0) {\\n return 0;\\n }\\n\\n // Set the initial guess to the closest power of two that is higher than x.\\n uint256 xAux = uint256(x);\\n result = 1;\\n if (xAux >= 0x100000000000000000000000000000000) {\\n xAux >>= 128;\\n result <<= 64;\\n }\\n if (xAux >= 0x10000000000000000) {\\n xAux >>= 64;\\n result <<= 32;\\n }\\n if (xAux >= 0x100000000) {\\n xAux >>= 32;\\n result <<= 16;\\n }\\n if (xAux >= 0x10000) {\\n xAux >>= 16;\\n result <<= 8;\\n }\\n if (xAux >= 0x100) {\\n xAux >>= 8;\\n result <<= 4;\\n }\\n if (xAux >= 0x10) {\\n xAux >>= 4;\\n result <<= 2;\\n }\\n if (xAux >= 0x8) {\\n result <<= 1;\\n }\\n\\n // The operations can never overflow because the result is max 2^127 when it enters this block.\\n unchecked {\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1;\\n result = (result + x / result) >> 1; // Seven iterations should be enough\\n uint256 roundedDownResult = x / result;\\n return result >= roundedDownResult ? roundedDownResult : result;\\n }\\n }\\n}\\n\",\"keccak256\":\"0x62cbabae4910e168e99b9c2c3e3b5c9c7ad5e7abd961dcc63b7ea3d83d8ea87e\",\"license\":\"Unlicense\"}},\"version\":1}", "bytecode": "0x60e06040523480156200001157600080fd5b506040516200350d3803806200350d833981016040819052620000349162000070565b60016000556001600160a01b0392831660805290821660a0521660c052620000c4565b6001600160a01b03811681146200006d57600080fd5b50565b6000806000606084860312156200008657600080fd5b8351620000938162000057565b6020850151909350620000a68162000057565b6040850151909250620000b98162000057565b809150509250925092565b60805160a05160c05161338d6200018060003960008181610263015281816106c201528181610c0c0152818161213c015261231901526000818161018b0152818161035f0152818161082f01528181610cf601528181610e0c015281816111fd015281816114c701528181611590015281816118c901528181611ccf01526123a00152600081816102290152818161040f0152818161104c01528181611772015281816119a201528181611f1201526121b8015261338d6000f3fe608060405234801561001057600080fd5b50600436106100ff5760003560e01c8063c294b2f411610097578063d49031c011610066578063d49031c014610285578063d4c3a8d214610298578063e7c8e3e3146102c9578063e8ba563a146102de57600080fd5b8063c294b2f414610211578063c41c2f2414610224578063c66445971461024b578063d3419bf31461025e57600080fd5b80636bb6a5ad116100d35780636bb6a5ad146101c5578063a2df1f95146101d8578063a57c7f59146101eb578063b753d7e9146101fe57600080fd5b8062fdd58e1461010457806325386715146101425780632fa1b39114610163578063557e715514610186575b600080fd5b61012f6101123660046125b3565b600160209081526000928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b6101556101503660046125df565b61030f565b60405161013992919061266a565b6101766101713660046127ea565b6107e5565b60405161013994939291906128fb565b6101ad7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610139565b61012f6101d336600461297a565b610cb5565b6101766101e6366004612993565b610dc2565b61012f6101f9366004612a34565b61148c565b61012f61020c3660046125df565b611556565b61012f61021f366004612a66565b61156d565b6101ad7f000000000000000000000000000000000000000000000000000000000000000081565b6101556102593660046125df565b611882565b6101ad7f000000000000000000000000000000000000000000000000000000000000000081565b61012f6102933660046125b3565b611cc6565b61012f6102a6366004612ab5565b600360209081526000938452604080852082529284528284209052825290205481565b6102dc6102d7366004612aea565b611da4565b005b61012f6102ec366004612ab5565b600260209081526000938452604080852082529284528284209052825290205481565b610317612546565b60006002600054036103445760405162461bcd60e51b815260040161033b90612b0c565b60405180910390fd5b60026000556040516321d1336160e11b8152600481018690527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa1580156103af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103d39190612b53565b336000908152600360209081526040808320898452825280832082850151845290915281205491935090610408908690612be9565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635dd8f6aa896040518263ffffffff1660e01b815260040161045b91815260200190565b602060405180830381865afa158015610478573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049c9190612bfc565b6001600160a01b031663a29a68146040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104fd9190612bfc565b6001600160a01b0316637a81b56289876020015133336001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610550573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105749190612bfc565b6040518563ffffffff1660e01b81526004016105939493929190612c19565b6040805180830381865afa1580156105af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105d39190612c40565b91509150818311806105e3575081155b1561060157604051635b76558960e11b815260040160405180910390fd5b8086146106215760405163e56ea4e760e01b815260040160405180910390fd5b6000336001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610661573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106859190612c64565b90508087146107405761073b8861069e6012600a612d61565b604051635268657960e11b8152600481018b905260248101859052601260448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a4d0caf2906064015b602060405180830381865afa158015610712573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107369190612c64565b611ded565b610742565b875b9450610750338a8884611eba565b851115610770576040516317e53f6760e11b815260040160405180910390fd5b3360008181526003602090815260408083208d845282528083208a83015184528252808320889055928252600181528282208c8352905220546107b4908690612d6d565b3360009081526001602081815260408084209d84529c90529a81209190915598909855509296919550909350505050565b6107ed612546565b60006060806002600054036108145760405162461bcd60e51b815260040161033b90612b0c565b60026000556040516321d1336160e11b8152600481018b90527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa15801561087f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108a39190612b53565b80519094506000036108c85760405163174b338d60e11b815260040160405180910390fd5b61010084015160481c6001908116036108f45760405163a3bb913360e01b815260040160405180910390fd5b61010084015160009060521c600190811614801561092a5750600061091e86610100015160541c90565b6001600160a01b031614155b15610a7c576000604051806101400160405280336001600160a01b031681526020018f6001600160a01b031681526020018e80360381019061096c9190612d80565b815260208082018f905288015160408201526001600160a01b038c16606082015260a080890151608083015261010089015191019060181c61ffff1681526020018a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525060200188905290506109fd86610100015160541c90565b6001600160a01b031663d46cf171826040518263ffffffff1660e01b8152600401610a289190612def565b6000604051808303816000875af1158015610a47573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610a6f9190810190612f5a565b955093509150610abd9050565b8460a00151905087878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294505050505b825160208d01359015610b395760005b8451811015610b37576000858281518110610aea57610aea61304b565b602002602001015160200151905080600014610b2e5782811115610b21576040516336a8da9360e11b815260040160405180910390fd5b610b2b8184612d6d565b92505b50600101610acd565b505b8c60200135600003610b51575060009350610c9e9050565b8015610bb8573360009081526001602090815260408083208f8452909152902054610b7d908290612be9565b60016000336001600160a01b03166001600160a01b0316815260200190815260200160002060008e8152602001908152602001600020819055505b5080600003610bcb575060009250610c9e565b60408c0135600060608e01358c14610c7c57604051635268657960e11b815260608f01356004820152602481018d9052604481018390526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a4d0caf290606401602060405180830381865afa158015610c53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c779190612c64565b610c87565b610c8782600a612d61565b9050610c988e602001358483611ded565b95505050505b600160008190555098509850985098945050505050565b6000600260005403610cd95760405162461bcd60e51b815260040161033b90612b0c565b600260009081556040516321d1336160e11b8152600481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa158015610d46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d6a9190612b53565b610100810151909150604d1c600190811614610d99576040516373e4f05f60e11b815260040160405180910390fd5b505033600090815260016020818152604080842094845293905291812080549082905591905590565b610dca612546565b6000606080600260005403610df15760405162461bcd60e51b815260040161033b90612b0c565b60026000556040516321d1336160e11b8152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa158015610e5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e809190612b53565b610100810151909450604a1c600190811603610eaf5760405163a97cf58f60e01b815260040160405180910390fd5b610ee3604051806080016040528060006001600160a01b031681526020016000815260200160008152602001600081525090565b6000806000336001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f26573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4a9190612bfc565b90506000336001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f8c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fb09190612c64565b90506000336001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ff2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110169190612c64565b6101008b015190915060511c60019081161461103d57611038338f8c84611eba565b611048565b6110488e8383612195565b94507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635dd8f6aa8f6040518263ffffffff1660e01b815260040161109891815260200190565b602060405180830381865afa1580156110b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d99190612bfc565b6001600160a01b031663c18f2d318f6040518263ffffffff1660e01b815260040161110691815260200190565b602060405180830381865afa158015611123573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111479190612c64565b9350838d111561116957604051625c579160e91b815260040160405180910390fd5b841561117f5761117c8e8b8f8789612377565b98505b604080516080810182526001600160a01b03949094168452602084018a9052830191909152606082015261010088015190935060531c60019081161480156111df575060006111d388610100015160541c90565b6001600160a01b031614155b156113b657604051633157d5c760e21b8152600481018c90526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c55f571c90602401602060405180830381865afa15801561124c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112709190613061565b90506000604051806101800160405280336001600160a01b031681526020018f6001600160a01b031681526020018e81526020018a6020015181526020018d81526020018481526020018581526020018681526020016112dd8b6101000151600160519190911c81161490565b1515815260200160008460028111156112f8576112f8613082565b1461130b576113068b6124af565b611314565b6113148b6124cc565b81526020018c81526020018b815250905061133489610100015160541c90565b6001600160a01b031663a51cfd18826040518263ffffffff1660e01b815260040161135f9190613098565b6000604051808303816000875af115801561137e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526113a69190810190613190565b91995090975095506113ba915050565b8893505b50508251849150156114145760005b83518110156114125760008482815181106113e6576113e661304b565b602002602001015160200151905080600014611409576114068184612be9565b92505b506001016113c9565b505b3360009081526001602090815260408083208c845290915290205481111561144f576040516317e53f6760e11b815260040160405180910390fd5b8015611477573360009081526001602090815260408083208c84529091529020805482900390555b50600160008190555095509550955095915050565b60008160000361149e5750600061154e565b828411156114ae5750600061154e565b6040516321d1336160e11b8152600481018690526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa158015611517573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061153b9190612b53565b905061154a8682878787612377565b9150505b949350505050565b6000611563848484612195565b90505b9392505050565b6040516321d1336160e11b81526004810184905260009081906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906343a266c29060240161012060405180830381865afa1580156115d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fc9190612b53565b9050600083611677576116728787848a6001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611649573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061166d9190612c64565b611eba565b611744565b61174486886001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116dd9190612c64565b896001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561171b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061173f9190612c64565b612195565b9050806000036117595760009250505061154e565b604051632eec7b5560e11b8152600481018790526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635dd8f6aa90602401602060405180830381865afa1580156117c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e59190612bfc565b6001600160a01b031663c18f2d31886040518263ffffffff1660e01b815260040161181291815260200190565b602060405180830381865afa15801561182f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118539190612c64565b905080861115611869576000935050505061154e565b6118768784888486612377565b98975050505050505050565b61188a612546565b60006002600054036118ae5760405162461bcd60e51b815260040161033b90612b0c565b60026000556040516321d1336160e11b8152600481018690527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa158015611919573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061193d9190612b53565b61010081015190925060491c60019081160361196c5760405163861e9dcd60e01b815260040160405180910390fd5b33600090815260026020908152604080832088845282528083208551845290915281205461199b908690612be9565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635dd8f6aa896040518263ffffffff1660e01b81526004016119ee91815260200190565b602060405180830381865afa158015611a0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a2f9190612bfc565b6001600160a01b031663a29a68146040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a909190612bfc565b6001600160a01b031663e8db213089876020015133336001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ae3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b079190612bfc565b6040518563ffffffff1660e01b8152600401611b269493929190612c19565b6040805180830381865afa158015611b42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b669190612c40565b9150915081831180611b76575081155b15611b9457604051630236b92b60e21b815260040160405180910390fd5b808614611bb45760405163e56ea4e760e01b815260040160405180910390fd5b6000336001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bf4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c189190612c64565b9050808714611c3657611c318861069e6012600a612d61565b611c38565b875b3360009081526001602090815260408083208d8452909152902054909550851115611c76576040516317e53f6760e11b815260040160405180910390fd5b50503360008181526002602090815260408083208b845282528083208851845282528083209590955591815260018083528482209982529890915291822080548490039055509490945593915050565b6000611d9b83837f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166343a266c2866040518263ffffffff1660e01b8152600401611d1b91815260200190565b61012060405180830381865afa158015611d39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d5d9190612b53565b866001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611649573d6000803e3d6000fd5b90505b92915050565b336000908152600160209081526040808320858452909152902054611dca908290612be9565b336000908152600160209081526040808320958352949052929092209190915550565b6000808060001985870985870292508281108382030391505080600003611e2757838281611e1d57611e1d613271565b0492505050611566565b838110611e5157604051631dcf306360e21b8152600481018290526024810185905260440161033b565b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b6001600160a01b0384166000908152600160209081526040808320868452909152812054808203611eef57600091505061154e565b604051632eec7b5560e11b81526004810186905260009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690635dd8f6aa90602401602060405180830381865afa158015611f59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f7d9190612bfc565b6001600160a01b031663a29a68146040518163ffffffff1660e01b8152600401602060405180830381865afa158015611fba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fde9190612bfc565b6001600160a01b031663e8db21308888602001518b8c6001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612031573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120559190612bfc565b6040518563ffffffff1660e01b81526004016120749493929190612c19565b6040805180830381865afa158015612090573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120b49190612c40565b6001600160a01b038a1660009081526002602090815260408083208c845282528083208b518452909152812054929450909250906120f29084612d6d565b905080158015906121035750858214155b1561217657612173816121186012600a612d61565b604051635268657960e11b815260048101869052602481018a9052601260448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a4d0caf2906064016106f5565b90505b808411612184576000612188565b8084035b9998505050505050505050565b60405163d175415360e01b81526004810184905260009081906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063d175415390602401600060405180830381865afa1580156121ff573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526122279190810190613287565b90506000805b82518110156122d2578281815181106122485761224861304b565b60200260200101516001600160a01b031663a32e1e96886040518263ffffffff1660e01b815260040161227d91815260200190565b602060405180830381865afa15801561229a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122be9190612c64565b6122c89083612be9565b915060010161222d565b5060006001851461234d57604051635268657960e11b8152600160048201526024810186905260126044820152612348908390670de0b6b3a7640000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a4d0caf2906064016106f5565b61234f565b815b90508560121461236a57612365816012886124e9565b61236c565b805b979650505050505050565b60008284036123875750806124a6565b600080604051633157d5c760e21b8152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c55f571c90602401602060405180830381865afa1580156123ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124139190613061565b600281111561242457612424613082565b1461243757612432866124af565b612440565b612440866124cc565b9050806000036124545760009150506124a6565b6000612461848787611ded565b905061271082036124755791506124a69050565b6124a18161248f8861248986612710612d6d565b89611ded565b6124999085612be9565b612710611ded565b925050505b95945050505050565b60006028826101000151901c61ffff16612710611d9e9190612d6d565b60006038826101000151901c61ffff16612710611d9e9190612d6d565b60008282036124f9575082611566565b828211156125275761250b8383612d6d565b61251690600a612d61565b6125209085613316565b9050611566565b6125318284612d6d565b61253c90600a612d61565b6125209085613335565b6040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b6001600160a01b03811681146125b057600080fd5b50565b600080604083850312156125c657600080fd5b82356125d18161259b565b946020939093013593505050565b6000806000606084860312156125f457600080fd5b505081359360208301359350604090920135919050565b805182526020808201519083015260408082015190830152606080820151908301526080808201519083015260a0808201519083015260c0808201519083015260e0808201516001600160a01b03169083015261010090810151910152565b6101408101612679828561260b565b826101208301529392505050565b60008083601f84011261269957600080fd5b50813567ffffffffffffffff8111156126b157600080fd5b6020830191508360208285010111156126c957600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051610120810167ffffffffffffffff8111828210171561270a5761270a6126d0565b60405290565b6040805190810167ffffffffffffffff8111828210171561270a5761270a6126d0565b604051601f8201601f1916810167ffffffffffffffff8111828210171561275c5761275c6126d0565b604052919050565b600067ffffffffffffffff82111561277e5761277e6126d0565b50601f01601f191660200190565b600061279f61279a84612764565b612733565b90508281528383830111156127b357600080fd5b828260208301376000602084830101529392505050565b600082601f8301126127db57600080fd5b611d9b8383356020850161278c565b600080600080600080600080888a0361014081121561280857600080fd5b89356128138161259b565b98506080601f198201121561282757600080fd5b5060208901965060a0890135955060c0890135945060e089013561284a8161259b565b935061010089013567ffffffffffffffff8082111561286857600080fd5b6128748c838d01612687565b90955093506101208b013591508082111561288e57600080fd5b5061289b8b828c016127ca565b9150509295985092959890939650565b60005b838110156128c65781810151838201526020016128ae565b50506000910152565b600081518084526128e78160208601602086016128ab565b601f01601f19169290920160200192915050565b600061018080830161290d848961260b565b61012084018790526101408401919091528451908190526101a083019060209081870160005b8281101561296357815180516001600160a01b031686528401518486015260409094019390830190600101612933565b5050505082810361016084015261236c81856128cf565b60006020828403121561298c57600080fd5b5035919050565b600080600080600060a086880312156129ab57600080fd5b85356129b68161259b565b94506020860135935060408601359250606086013567ffffffffffffffff808211156129e157600080fd5b818801915088601f8301126129f557600080fd5b612a048983356020850161278c565b93506080880135915080821115612a1a57600080fd5b50612a27888289016127ca565b9150509295509295909350565b60008060008060808587031215612a4a57600080fd5b5050823594602084013594506040840135936060013592509050565b60008060008060808587031215612a7c57600080fd5b8435612a878161259b565b9350602085013592506040850135915060608501358015158114612aaa57600080fd5b939692955090935050565b600080600060608486031215612aca57600080fd5b8335612ad58161259b565b95602085013595506040909401359392505050565b60008060408385031215612afd57600080fd5b50508035926020909101359150565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b8051612b4e8161259b565b919050565b60006101208284031215612b6657600080fd5b612b6e6126e6565b825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c0820152612bba60e08401612b43565b60e0820152610100928301519281019290925250919050565b634e487b7160e01b600052601160045260246000fd5b80820180821115611d9e57611d9e612bd3565b600060208284031215612c0e57600080fd5b81516115668161259b565b93845260208401929092526001600160a01b03908116604084015216606082015260800190565b60008060408385031215612c5357600080fd5b505080516020909101519092909150565b600060208284031215612c7657600080fd5b5051919050565b600181815b80851115612cb8578160001904821115612c9e57612c9e612bd3565b80851615612cab57918102915b93841c9390800290612c82565b509250929050565b600082612ccf57506001611d9e565b81612cdc57506000611d9e565b8160018114612cf25760028114612cfc57612d18565b6001915050611d9e565b60ff841115612d0d57612d0d612bd3565b50506001821b611d9e565b5060208310610133831016604e8410600b8410161715612d3b575081810a611d9e565b612d458383612c7d565b8060001904821115612d5957612d59612bd3565b029392505050565b6000611d9b8383612cc0565b81810381811115611d9e57611d9e612bd3565b600060808284031215612d9257600080fd5b6040516080810181811067ffffffffffffffff82111715612db557612db56126d0565b6040528235612dc38161259b565b808252506020830135602082015260408301356040820152606083013560608201528091505092915050565b60208152612e096020820183516001600160a01b03169052565b60006020830151612e2560408401826001600160a01b03169052565b506040830151612e5f606084018280516001600160a01b031682526020808201519083015260408082015190830152606090810151910152565b50606083015160e08301526080830151610100818185015260a08501519150610120612e95818601846001600160a01b03169052565b60c086015161014086015260e08601516101608601528186015192506101a0915081610180860152612ecb6101c08601846128cf565b90860151858203601f190183870152909250612ee783826128cf565b9695505050505050565b600082601f830112612f0257600080fd5b8151612f1061279a82612764565b818152846020838601011115612f2557600080fd5b61154e8260208301602087016128ab565b600067ffffffffffffffff821115612f5057612f506126d0565b5060051b60200190565b600080600060608486031215612f6f57600080fd5b8351925060208085015167ffffffffffffffff80821115612f8f57600080fd5b612f9b88838901612ef1565b9450604091508187015181811115612fb257600080fd5b87019050601f81018813612fc557600080fd5b8051612fd361279a82612f36565b81815260069190911b8201840190848101908a831115612ff257600080fd5b928501925b8284101561303b5784848c03121561300f5760008081fd5b613017612710565b84516130228161259b565b8152848701518782015282529284019290850190612ff7565b8096505050505050509250925092565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561307357600080fd5b81516003811061156657600080fd5b634e487b7160e01b600052602160045260246000fd5b602081526130b26020820183516001600160a01b03169052565b600060208301516130ce60408401826001600160a01b03169052565b506040830151606083015260608301516080830152608083015160a083015260a083015160c083015260c083015160e083015260e083015161010061313c8185018380516001600160a01b031682526020808201519083015260408082015190830152606090810151910152565b8401511515610180840152506101208301516101a08301526101408301516101e06101c084018190526131736102008501836128cf565b9150610160850151601f198584030182860152612ee783826128cf565b6000806000606084860312156131a557600080fd5b8351925060208085015167ffffffffffffffff808211156131c557600080fd5b6131d188838901612ef1565b94506040915081870151818111156131e857600080fd5b87019050601f810188136131fb57600080fd5b805161320961279a82612f36565b81815260069190911b8201840190848101908a83111561322857600080fd5b928501925b8284101561303b5784848c0312156132455760008081fd5b61324d612710565b84516132588161259b565b815284870151878201528252928401929085019061322d565b634e487b7160e01b600052601260045260246000fd5b6000602080838503121561329a57600080fd5b825167ffffffffffffffff8111156132b157600080fd5b8301601f810185136132c257600080fd5b80516132d061279a82612f36565b81815260059190911b820183019083810190878311156132ef57600080fd5b928401925b8284101561236c5783516133078161259b565b825292840192908401906132f4565b600081600019048311821515161561333057613330612bd3565b500290565b60008261335257634e487b7160e01b600052601260045260246000fd5b50049056fea2646970667358221220b7946353bb36b956c0e33bade6b03ba8a4ea378cf80ee03d1c4c5ccc83ebba0d64736f6c63430008100033", "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100ff5760003560e01c8063c294b2f411610097578063d49031c011610066578063d49031c014610285578063d4c3a8d214610298578063e7c8e3e3146102c9578063e8ba563a146102de57600080fd5b8063c294b2f414610211578063c41c2f2414610224578063c66445971461024b578063d3419bf31461025e57600080fd5b80636bb6a5ad116100d35780636bb6a5ad146101c5578063a2df1f95146101d8578063a57c7f59146101eb578063b753d7e9146101fe57600080fd5b8062fdd58e1461010457806325386715146101425780632fa1b39114610163578063557e715514610186575b600080fd5b61012f6101123660046125b3565b600160209081526000928352604080842090915290825290205481565b6040519081526020015b60405180910390f35b6101556101503660046125df565b61030f565b60405161013992919061266a565b6101766101713660046127ea565b6107e5565b60405161013994939291906128fb565b6101ad7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610139565b61012f6101d336600461297a565b610cb5565b6101766101e6366004612993565b610dc2565b61012f6101f9366004612a34565b61148c565b61012f61020c3660046125df565b611556565b61012f61021f366004612a66565b61156d565b6101ad7f000000000000000000000000000000000000000000000000000000000000000081565b6101556102593660046125df565b611882565b6101ad7f000000000000000000000000000000000000000000000000000000000000000081565b61012f6102933660046125b3565b611cc6565b61012f6102a6366004612ab5565b600360209081526000938452604080852082529284528284209052825290205481565b6102dc6102d7366004612aea565b611da4565b005b61012f6102ec366004612ab5565b600260209081526000938452604080852082529284528284209052825290205481565b610317612546565b60006002600054036103445760405162461bcd60e51b815260040161033b90612b0c565b60405180910390fd5b60026000556040516321d1336160e11b8152600481018690527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa1580156103af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103d39190612b53565b336000908152600360209081526040808320898452825280832082850151845290915281205491935090610408908690612be9565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635dd8f6aa896040518263ffffffff1660e01b815260040161045b91815260200190565b602060405180830381865afa158015610478573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061049c9190612bfc565b6001600160a01b031663a29a68146040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104fd9190612bfc565b6001600160a01b0316637a81b56289876020015133336001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610550573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105749190612bfc565b6040518563ffffffff1660e01b81526004016105939493929190612c19565b6040805180830381865afa1580156105af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105d39190612c40565b91509150818311806105e3575081155b1561060157604051635b76558960e11b815260040160405180910390fd5b8086146106215760405163e56ea4e760e01b815260040160405180910390fd5b6000336001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610661573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106859190612c64565b90508087146107405761073b8861069e6012600a612d61565b604051635268657960e11b8152600481018b905260248101859052601260448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a4d0caf2906064015b602060405180830381865afa158015610712573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107369190612c64565b611ded565b610742565b875b9450610750338a8884611eba565b851115610770576040516317e53f6760e11b815260040160405180910390fd5b3360008181526003602090815260408083208d845282528083208a83015184528252808320889055928252600181528282208c8352905220546107b4908690612d6d565b3360009081526001602081815260408084209d84529c90529a81209190915598909855509296919550909350505050565b6107ed612546565b60006060806002600054036108145760405162461bcd60e51b815260040161033b90612b0c565b60026000556040516321d1336160e11b8152600481018b90527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa15801561087f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108a39190612b53565b80519094506000036108c85760405163174b338d60e11b815260040160405180910390fd5b61010084015160481c6001908116036108f45760405163a3bb913360e01b815260040160405180910390fd5b61010084015160009060521c600190811614801561092a5750600061091e86610100015160541c90565b6001600160a01b031614155b15610a7c576000604051806101400160405280336001600160a01b031681526020018f6001600160a01b031681526020018e80360381019061096c9190612d80565b815260208082018f905288015160408201526001600160a01b038c16606082015260a080890151608083015261010089015191019060181c61ffff1681526020018a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525060200188905290506109fd86610100015160541c90565b6001600160a01b031663d46cf171826040518263ffffffff1660e01b8152600401610a289190612def565b6000604051808303816000875af1158015610a47573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610a6f9190810190612f5a565b955093509150610abd9050565b8460a00151905087878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294505050505b825160208d01359015610b395760005b8451811015610b37576000858281518110610aea57610aea61304b565b602002602001015160200151905080600014610b2e5782811115610b21576040516336a8da9360e11b815260040160405180910390fd5b610b2b8184612d6d565b92505b50600101610acd565b505b8c60200135600003610b51575060009350610c9e9050565b8015610bb8573360009081526001602090815260408083208f8452909152902054610b7d908290612be9565b60016000336001600160a01b03166001600160a01b0316815260200190815260200160002060008e8152602001908152602001600020819055505b5080600003610bcb575060009250610c9e565b60408c0135600060608e01358c14610c7c57604051635268657960e11b815260608f01356004820152602481018d9052604481018390526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a4d0caf290606401602060405180830381865afa158015610c53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c779190612c64565b610c87565b610c8782600a612d61565b9050610c988e602001358483611ded565b95505050505b600160008190555098509850985098945050505050565b6000600260005403610cd95760405162461bcd60e51b815260040161033b90612b0c565b600260009081556040516321d1336160e11b8152600481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa158015610d46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d6a9190612b53565b610100810151909150604d1c600190811614610d99576040516373e4f05f60e11b815260040160405180910390fd5b505033600090815260016020818152604080842094845293905291812080549082905591905590565b610dca612546565b6000606080600260005403610df15760405162461bcd60e51b815260040161033b90612b0c565b60026000556040516321d1336160e11b8152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa158015610e5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e809190612b53565b610100810151909450604a1c600190811603610eaf5760405163a97cf58f60e01b815260040160405180910390fd5b610ee3604051806080016040528060006001600160a01b031681526020016000815260200160008152602001600081525090565b6000806000336001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f26573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4a9190612bfc565b90506000336001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f8c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fb09190612c64565b90506000336001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ff2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110169190612c64565b6101008b015190915060511c60019081161461103d57611038338f8c84611eba565b611048565b6110488e8383612195565b94507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635dd8f6aa8f6040518263ffffffff1660e01b815260040161109891815260200190565b602060405180830381865afa1580156110b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d99190612bfc565b6001600160a01b031663c18f2d318f6040518263ffffffff1660e01b815260040161110691815260200190565b602060405180830381865afa158015611123573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111479190612c64565b9350838d111561116957604051625c579160e91b815260040160405180910390fd5b841561117f5761117c8e8b8f8789612377565b98505b604080516080810182526001600160a01b03949094168452602084018a9052830191909152606082015261010088015190935060531c60019081161480156111df575060006111d388610100015160541c90565b6001600160a01b031614155b156113b657604051633157d5c760e21b8152600481018c90526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c55f571c90602401602060405180830381865afa15801561124c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112709190613061565b90506000604051806101800160405280336001600160a01b031681526020018f6001600160a01b031681526020018e81526020018a6020015181526020018d81526020018481526020018581526020018681526020016112dd8b6101000151600160519190911c81161490565b1515815260200160008460028111156112f8576112f8613082565b1461130b576113068b6124af565b611314565b6113148b6124cc565b81526020018c81526020018b815250905061133489610100015160541c90565b6001600160a01b031663a51cfd18826040518263ffffffff1660e01b815260040161135f9190613098565b6000604051808303816000875af115801561137e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526113a69190810190613190565b91995090975095506113ba915050565b8893505b50508251849150156114145760005b83518110156114125760008482815181106113e6576113e661304b565b602002602001015160200151905080600014611409576114068184612be9565b92505b506001016113c9565b505b3360009081526001602090815260408083208c845290915290205481111561144f576040516317e53f6760e11b815260040160405180910390fd5b8015611477573360009081526001602090815260408083208c84529091529020805482900390555b50600160008190555095509550955095915050565b60008160000361149e5750600061154e565b828411156114ae5750600061154e565b6040516321d1336160e11b8152600481018690526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa158015611517573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061153b9190612b53565b905061154a8682878787612377565b9150505b949350505050565b6000611563848484612195565b90505b9392505050565b6040516321d1336160e11b81526004810184905260009081906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906343a266c29060240161012060405180830381865afa1580156115d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fc9190612b53565b9050600083611677576116728787848a6001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611649573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061166d9190612c64565b611eba565b611744565b61174486886001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116dd9190612c64565b896001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561171b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061173f9190612c64565b612195565b9050806000036117595760009250505061154e565b604051632eec7b5560e11b8152600481018790526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635dd8f6aa90602401602060405180830381865afa1580156117c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117e59190612bfc565b6001600160a01b031663c18f2d31886040518263ffffffff1660e01b815260040161181291815260200190565b602060405180830381865afa15801561182f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118539190612c64565b905080861115611869576000935050505061154e565b6118768784888486612377565b98975050505050505050565b61188a612546565b60006002600054036118ae5760405162461bcd60e51b815260040161033b90612b0c565b60026000556040516321d1336160e11b8152600481018690527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906343a266c29060240161012060405180830381865afa158015611919573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061193d9190612b53565b61010081015190925060491c60019081160361196c5760405163861e9dcd60e01b815260040160405180910390fd5b33600090815260026020908152604080832088845282528083208551845290915281205461199b908690612be9565b90506000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635dd8f6aa896040518263ffffffff1660e01b81526004016119ee91815260200190565b602060405180830381865afa158015611a0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a2f9190612bfc565b6001600160a01b031663a29a68146040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a6c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a909190612bfc565b6001600160a01b031663e8db213089876020015133336001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ae3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b079190612bfc565b6040518563ffffffff1660e01b8152600401611b269493929190612c19565b6040805180830381865afa158015611b42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b669190612c40565b9150915081831180611b76575081155b15611b9457604051630236b92b60e21b815260040160405180910390fd5b808614611bb45760405163e56ea4e760e01b815260040160405180910390fd5b6000336001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bf4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c189190612c64565b9050808714611c3657611c318861069e6012600a612d61565b611c38565b875b3360009081526001602090815260408083208d8452909152902054909550851115611c76576040516317e53f6760e11b815260040160405180910390fd5b50503360008181526002602090815260408083208b845282528083208851845282528083209590955591815260018083528482209982529890915291822080548490039055509490945593915050565b6000611d9b83837f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166343a266c2866040518263ffffffff1660e01b8152600401611d1b91815260200190565b61012060405180830381865afa158015611d39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d5d9190612b53565b866001600160a01b031663e5a6b10f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611649573d6000803e3d6000fd5b90505b92915050565b336000908152600160209081526040808320858452909152902054611dca908290612be9565b336000908152600160209081526040808320958352949052929092209190915550565b6000808060001985870985870292508281108382030391505080600003611e2757838281611e1d57611e1d613271565b0492505050611566565b838110611e5157604051631dcf306360e21b8152600481018290526024810185905260440161033b565b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b6001600160a01b0384166000908152600160209081526040808320868452909152812054808203611eef57600091505061154e565b604051632eec7b5560e11b81526004810186905260009081906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690635dd8f6aa90602401602060405180830381865afa158015611f59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f7d9190612bfc565b6001600160a01b031663a29a68146040518163ffffffff1660e01b8152600401602060405180830381865afa158015611fba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fde9190612bfc565b6001600160a01b031663e8db21308888602001518b8c6001600160a01b031663fc0c546a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612031573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120559190612bfc565b6040518563ffffffff1660e01b81526004016120749493929190612c19565b6040805180830381865afa158015612090573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120b49190612c40565b6001600160a01b038a1660009081526002602090815260408083208c845282528083208b518452909152812054929450909250906120f29084612d6d565b905080158015906121035750858214155b1561217657612173816121186012600a612d61565b604051635268657960e11b815260048101869052602481018a9052601260448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063a4d0caf2906064016106f5565b90505b808411612184576000612188565b8084035b9998505050505050505050565b60405163d175415360e01b81526004810184905260009081906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063d175415390602401600060405180830381865afa1580156121ff573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526122279190810190613287565b90506000805b82518110156122d2578281815181106122485761224861304b565b60200260200101516001600160a01b031663a32e1e96886040518263ffffffff1660e01b815260040161227d91815260200190565b602060405180830381865afa15801561229a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122be9190612c64565b6122c89083612be9565b915060010161222d565b5060006001851461234d57604051635268657960e11b8152600160048201526024810186905260126044820152612348908390670de0b6b3a7640000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a4d0caf2906064016106f5565b61234f565b815b90508560121461236a57612365816012886124e9565b61236c565b805b979650505050505050565b60008284036123875750806124a6565b600080604051633157d5c760e21b8152600481018990527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c55f571c90602401602060405180830381865afa1580156123ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124139190613061565b600281111561242457612424613082565b1461243757612432866124af565b612440565b612440866124cc565b9050806000036124545760009150506124a6565b6000612461848787611ded565b905061271082036124755791506124a69050565b6124a18161248f8861248986612710612d6d565b89611ded565b6124999085612be9565b612710611ded565b925050505b95945050505050565b60006028826101000151901c61ffff16612710611d9e9190612d6d565b60006038826101000151901c61ffff16612710611d9e9190612d6d565b60008282036124f9575082611566565b828211156125275761250b8383612d6d565b61251690600a612d61565b6125209085613316565b9050611566565b6125318284612d6d565b61253c90600a612d61565b6125209085613335565b6040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160006001600160a01b03168152602001600081525090565b6001600160a01b03811681146125b057600080fd5b50565b600080604083850312156125c657600080fd5b82356125d18161259b565b946020939093013593505050565b6000806000606084860312156125f457600080fd5b505081359360208301359350604090920135919050565b805182526020808201519083015260408082015190830152606080820151908301526080808201519083015260a0808201519083015260c0808201519083015260e0808201516001600160a01b03169083015261010090810151910152565b6101408101612679828561260b565b826101208301529392505050565b60008083601f84011261269957600080fd5b50813567ffffffffffffffff8111156126b157600080fd5b6020830191508360208285010111156126c957600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051610120810167ffffffffffffffff8111828210171561270a5761270a6126d0565b60405290565b6040805190810167ffffffffffffffff8111828210171561270a5761270a6126d0565b604051601f8201601f1916810167ffffffffffffffff8111828210171561275c5761275c6126d0565b604052919050565b600067ffffffffffffffff82111561277e5761277e6126d0565b50601f01601f191660200190565b600061279f61279a84612764565b612733565b90508281528383830111156127b357600080fd5b828260208301376000602084830101529392505050565b600082601f8301126127db57600080fd5b611d9b8383356020850161278c565b600080600080600080600080888a0361014081121561280857600080fd5b89356128138161259b565b98506080601f198201121561282757600080fd5b5060208901965060a0890135955060c0890135945060e089013561284a8161259b565b935061010089013567ffffffffffffffff8082111561286857600080fd5b6128748c838d01612687565b90955093506101208b013591508082111561288e57600080fd5b5061289b8b828c016127ca565b9150509295985092959890939650565b60005b838110156128c65781810151838201526020016128ae565b50506000910152565b600081518084526128e78160208601602086016128ab565b601f01601f19169290920160200192915050565b600061018080830161290d848961260b565b61012084018790526101408401919091528451908190526101a083019060209081870160005b8281101561296357815180516001600160a01b031686528401518486015260409094019390830190600101612933565b5050505082810361016084015261236c81856128cf565b60006020828403121561298c57600080fd5b5035919050565b600080600080600060a086880312156129ab57600080fd5b85356129b68161259b565b94506020860135935060408601359250606086013567ffffffffffffffff808211156129e157600080fd5b818801915088601f8301126129f557600080fd5b612a048983356020850161278c565b93506080880135915080821115612a1a57600080fd5b50612a27888289016127ca565b9150509295509295909350565b60008060008060808587031215612a4a57600080fd5b5050823594602084013594506040840135936060013592509050565b60008060008060808587031215612a7c57600080fd5b8435612a878161259b565b9350602085013592506040850135915060608501358015158114612aaa57600080fd5b939692955090935050565b600080600060608486031215612aca57600080fd5b8335612ad58161259b565b95602085013595506040909401359392505050565b60008060408385031215612afd57600080fd5b50508035926020909101359150565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b8051612b4e8161259b565b919050565b60006101208284031215612b6657600080fd5b612b6e6126e6565b825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c0820152612bba60e08401612b43565b60e0820152610100928301519281019290925250919050565b634e487b7160e01b600052601160045260246000fd5b80820180821115611d9e57611d9e612bd3565b600060208284031215612c0e57600080fd5b81516115668161259b565b93845260208401929092526001600160a01b03908116604084015216606082015260800190565b60008060408385031215612c5357600080fd5b505080516020909101519092909150565b600060208284031215612c7657600080fd5b5051919050565b600181815b80851115612cb8578160001904821115612c9e57612c9e612bd3565b80851615612cab57918102915b93841c9390800290612c82565b509250929050565b600082612ccf57506001611d9e565b81612cdc57506000611d9e565b8160018114612cf25760028114612cfc57612d18565b6001915050611d9e565b60ff841115612d0d57612d0d612bd3565b50506001821b611d9e565b5060208310610133831016604e8410600b8410161715612d3b575081810a611d9e565b612d458383612c7d565b8060001904821115612d5957612d59612bd3565b029392505050565b6000611d9b8383612cc0565b81810381811115611d9e57611d9e612bd3565b600060808284031215612d9257600080fd5b6040516080810181811067ffffffffffffffff82111715612db557612db56126d0565b6040528235612dc38161259b565b808252506020830135602082015260408301356040820152606083013560608201528091505092915050565b60208152612e096020820183516001600160a01b03169052565b60006020830151612e2560408401826001600160a01b03169052565b506040830151612e5f606084018280516001600160a01b031682526020808201519083015260408082015190830152606090810151910152565b50606083015160e08301526080830151610100818185015260a08501519150610120612e95818601846001600160a01b03169052565b60c086015161014086015260e08601516101608601528186015192506101a0915081610180860152612ecb6101c08601846128cf565b90860151858203601f190183870152909250612ee783826128cf565b9695505050505050565b600082601f830112612f0257600080fd5b8151612f1061279a82612764565b818152846020838601011115612f2557600080fd5b61154e8260208301602087016128ab565b600067ffffffffffffffff821115612f5057612f506126d0565b5060051b60200190565b600080600060608486031215612f6f57600080fd5b8351925060208085015167ffffffffffffffff80821115612f8f57600080fd5b612f9b88838901612ef1565b9450604091508187015181811115612fb257600080fd5b87019050601f81018813612fc557600080fd5b8051612fd361279a82612f36565b81815260069190911b8201840190848101908a831115612ff257600080fd5b928501925b8284101561303b5784848c03121561300f5760008081fd5b613017612710565b84516130228161259b565b8152848701518782015282529284019290850190612ff7565b8096505050505050509250925092565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561307357600080fd5b81516003811061156657600080fd5b634e487b7160e01b600052602160045260246000fd5b602081526130b26020820183516001600160a01b03169052565b600060208301516130ce60408401826001600160a01b03169052565b506040830151606083015260608301516080830152608083015160a083015260a083015160c083015260c083015160e083015260e083015161010061313c8185018380516001600160a01b031682526020808201519083015260408082015190830152606090810151910152565b8401511515610180840152506101208301516101a08301526101408301516101e06101c084018190526131736102008501836128cf565b9150610160850151601f198584030182860152612ee783826128cf565b6000806000606084860312156131a557600080fd5b8351925060208085015167ffffffffffffffff808211156131c557600080fd5b6131d188838901612ef1565b94506040915081870151818111156131e857600080fd5b87019050601f810188136131fb57600080fd5b805161320961279a82612f36565b81815260069190911b8201840190848101908a83111561322857600080fd5b928501925b8284101561303b5784848c0312156132455760008081fd5b61324d612710565b84516132588161259b565b815284870151878201528252928401929085019061322d565b634e487b7160e01b600052601260045260246000fd5b6000602080838503121561329a57600080fd5b825167ffffffffffffffff8111156132b157600080fd5b8301601f810185136132c257600080fd5b80516132d061279a82612f36565b81815260059190911b820183019083810190878311156132ef57600080fd5b928401925b8284101561236c5783516133078161259b565b825292840192908401906132f4565b600081600019048311821515161561333057613330612bd3565b500290565b60008261335257634e487b7160e01b600052601260045260246000fd5b50049056fea2646970667358221220b7946353bb36b956c0e33bade6b03ba8a4ea378cf80ee03d1c4c5ccc83ebba0d64736f6c63430008100033", "devdoc": { diff --git a/deployments/mainnet/solcInputs/153d6bc38185326110a6246705507380.json b/deployments/mainnet/solcInputs/153d6bc38185326110a6246705507380.json index 374ed38ae..be959c33b 100644 --- a/deployments/mainnet/solcInputs/153d6bc38185326110a6246705507380.json +++ b/deployments/mainnet/solcInputs/153d6bc38185326110a6246705507380.json @@ -119,13 +119,13 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport './abstract/JBOperatable.sol';\nimport './interfaces/IJBDirectory.sol';\nimport './libraries/JBGlobalFundingCycleMetadataResolver.sol';\nimport './libraries/JBOperations.sol';\n\n/**\n @notice\n Keeps a reference of which terminal contracts each project is currently accepting funds through, and which controller contract is managing each project's tokens and funding cycles.\n\n @dev\n Adheres to -\n IJBDirectory: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\ncontract JBDirectory is IJBDirectory, JBOperatable, Ownable {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBGlobalFundingCycleMetadataResolver for uint8;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error DUPLICATE_TERMINALS();\n error INVALID_PROJECT_ID_IN_DIRECTORY();\n error SET_CONTROLLER_NOT_ALLOWED();\n error SET_TERMINALS_NOT_ALLOWED();\n error TOKEN_NOT_ACCEPTED();\n\n //*********************************************************************//\n // --------------------- private stored properties ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n For each project ID, the terminals that are currently managing its funds.\n\n _projectId The ID of the project to get terminals of.\n */\n mapping(uint256 => IJBPaymentTerminal[]) private _terminalsOf;\n\n /**\n @notice\n The project's primary terminal for a token.\n\n _projectId The ID of the project to get the primary terminal of.\n _token The token to get the project's primary terminal of.\n */\n mapping(uint256 => mapping(address => IJBPaymentTerminal)) private _primaryTerminalOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n For each project ID, the controller that manages how terminals interact with tokens and funding cycles.\n\n _projectId The ID of the project to get the controller of.\n */\n mapping(uint256 => address) public override controllerOf;\n\n /**\n @notice\n Addresses that can set a project's first controller on their behalf. These addresses/contracts have been vetted and verified by this contract's owner.\n\n _address The address that is either allowed or not.\n */\n mapping(address => bool) public override isAllowedToSetFirstController;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n For each project ID, the terminals that are currently managing its funds.\n\n @param _projectId The ID of the project to get terminals of.\n\n @return An array of terminal addresses.\n */\n function terminalsOf(uint256 _projectId)\n external\n view\n override\n returns (IJBPaymentTerminal[] memory)\n {\n return _terminalsOf[_projectId];\n }\n\n /**\n @notice\n The primary terminal that is managing funds for a project for a specified token.\n\n @dev\n The zero address is returned if a terminal isn't found for the specified token.\n\n @param _projectId The ID of the project to get a terminal for.\n @param _token The token the terminal accepts.\n\n @return The primary terminal for the project for the specified token.\n */\n function primaryTerminalOf(uint256 _projectId, address _token)\n external\n view\n override\n returns (IJBPaymentTerminal)\n {\n // If a primary terminal for the token was specifically set and its one of the project's terminals, return it.\n if (\n _primaryTerminalOf[_projectId][_token] != IJBPaymentTerminal(address(0)) &&\n isTerminalOf(_projectId, _primaryTerminalOf[_projectId][_token])\n ) return _primaryTerminalOf[_projectId][_token];\n\n // Return the first terminal which accepts the specified token.\n for (uint256 _i; _i < _terminalsOf[_projectId].length; _i++) {\n IJBPaymentTerminal _terminal = _terminalsOf[_projectId][_i];\n if (_terminal.acceptsToken(_token, _projectId)) return _terminal;\n }\n\n // Not found.\n return IJBPaymentTerminal(address(0));\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Whether or not a specified terminal is a terminal of the specified project.\n\n @param _projectId The ID of the project to check within.\n @param _terminal The address of the terminal to check for.\n\n @return A flag indicating whether or not the specified terminal is a terminal of the specified project.\n */\n function isTerminalOf(uint256 _projectId, IJBPaymentTerminal _terminal)\n public\n view\n override\n returns (bool)\n {\n for (uint256 _i; _i < _terminalsOf[_projectId].length; _i++)\n if (_terminalsOf[_projectId][_i] == _terminal) return true;\n return false;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _owner The address that will own the contract.\n */\n constructor(\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBFundingCycleStore _fundingCycleStore,\n address _owner\n ) JBOperatable(_operatorStore) {\n projects = _projects;\n fundingCycleStore = _fundingCycleStore;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Update the controller that manages how terminals interact with the ecosystem.\n\n @dev\n A controller can be set if:\n - the message sender is the project owner or an operator having the correct authorization.\n - the message sender is the project's current controller.\n - or, an allowedlisted address is setting a controller for a project that doesn't already have a controller.\n\n @param _projectId The ID of the project to set a new controller for.\n @param _controller The new controller to set.\n */\n function setControllerOf(uint256 _projectId, address _controller)\n external\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.SET_CONTROLLER,\n (msg.sender == address(controllerOf[_projectId]) ||\n (isAllowedToSetFirstController[msg.sender] && controllerOf[_projectId] == address(0)))\n )\n {\n // The project must exist.\n if (projects.count() < _projectId) revert INVALID_PROJECT_ID_IN_DIRECTORY();\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Setting controller is allowed if called from the current controller, or if the project doesn't have a current controller, or if the project's funding cycle allows setting the controller. Revert otherwise.\n if (\n msg.sender != address(controllerOf[_projectId]) &&\n controllerOf[_projectId] != address(0) &&\n !uint8(_fundingCycle.metadata >> 8).setControllerAllowed()\n ) revert SET_CONTROLLER_NOT_ALLOWED();\n\n // Set the new controller.\n controllerOf[_projectId] = _controller;\n\n emit SetController(_projectId, _controller, msg.sender);\n }\n\n /** \n @notice \n Set a project's terminals.\n\n @dev\n Only a project owner, an operator, or its controller can set its terminals.\n\n @param _projectId The ID of the project having terminals set.\n @param _terminals The terminal to set.\n */\n function setTerminalsOf(uint256 _projectId, IJBPaymentTerminal[] calldata _terminals)\n external\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.SET_TERMINALS,\n msg.sender == address(controllerOf[_projectId])\n )\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Setting terminals must be allowed if not called from the current controller.\n if (\n msg.sender != address(controllerOf[_projectId]) &&\n !uint8(_fundingCycle.metadata >> 8).setTerminalsAllowed()\n ) revert SET_TERMINALS_NOT_ALLOWED();\n\n // Delete the stored terminals for the project.\n _terminalsOf[_projectId] = _terminals;\n\n // Make sure duplicates were not added.\n if (_terminals.length > 1)\n for (uint256 _i; _i < _terminals.length; _i++)\n for (uint256 _j = _i + 1; _j < _terminals.length; _j++)\n if (_terminals[_i] == _terminals[_j]) revert DUPLICATE_TERMINALS();\n\n emit SetTerminals(_projectId, _terminals, msg.sender);\n }\n\n /**\n @notice\n Project's can set which terminal should be their primary for a particular token.\n This is useful in case a project has several terminals connected for a particular token.\n\n @dev\n The terminal will be set as the primary terminal where ecosystem contracts should route tokens.\n\n @dev\n If setting a newly added terminal and the funding cycle doesn't allow new terminals, the caller must be the current controller.\n\n @param _projectId The ID of the project for which a primary token is being set.\n @param _token The token to set the primary terminal of.\n @param _terminal The terminal to make primary.\n */\n function setPrimaryTerminalOf(\n uint256 _projectId,\n address _token,\n IJBPaymentTerminal _terminal\n )\n external\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.SET_PRIMARY_TERMINAL)\n {\n // Can't set the primary terminal for a token if it doesn't accept the token.\n if (!_terminal.acceptsToken(_token, _projectId)) revert TOKEN_NOT_ACCEPTED();\n\n // Add the terminal to the project if it hasn't been already.\n _addTerminalIfNeeded(_projectId, _terminal);\n\n // Store the terminal as the primary for the particular token.\n _primaryTerminalOf[_projectId][_token] = _terminal;\n\n emit SetPrimaryTerminal(_projectId, _token, _terminal, msg.sender);\n }\n\n /** \n @notice\t\n Set a contract to the list of trusted addresses that can set a first controller for any project.\t\n\n @dev\n The owner can add addresses which are allowed to change projects' first controllers. \n These addresses are known and vetted controllers as well as contracts designed to launch new projects. \n A project can set its own controller without it being on the allow list.\n\n @dev\n If you would like an address/contract allowlisted, please reach out to the contract owner.\n\n @param _address The address to allow or revoke allowance from.\n @param _flag Whether allowance is being added or revoked.\n */\n function setIsAllowedToSetFirstController(address _address, bool _flag)\n external\n override\n onlyOwner\n {\n // Set the flag in the allowlist.\n isAllowedToSetFirstController[_address] = _flag;\n\n emit SetIsAllowedToSetFirstController(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Add a terminal to a project's list of terminals if it hasn't been already.\n\n @param _projectId The ID of the project having a terminal added.\n @param _terminal The terminal to add.\n */\n function _addTerminalIfNeeded(uint256 _projectId, IJBPaymentTerminal _terminal) private {\n // Check that the terminal has not already been added.\n if (isTerminalOf(_projectId, _terminal)) return;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Setting terminals must be allowed if not called from the current controller.\n if (\n msg.sender != address(controllerOf[_projectId]) &&\n !uint8(_fundingCycle.metadata >> 8).setTerminalsAllowed()\n ) revert SET_TERMINALS_NOT_ALLOWED();\n\n // Add the new terminal.\n _terminalsOf[_projectId].push(_terminal);\n\n emit AddTerminal(_projectId, _terminal, msg.sender);\n }\n}\n" }, "contracts/JBETHPaymentTerminal.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n JBTokens.ETH,\n 18, // 18 decimals.\n JBCurrencies.ETH,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal pure override {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n JBTokens.GAS_TOKEN,\n 18, // 18 decimals.\n JBCurrencies.GAS_CURRENCY,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal pure override {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n}\n" }, "contracts/JBERC20PaymentTerminal.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\n\n/** \n @notice \n Manages the inflows and outflows of an ERC-20 token.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\ncontract JBERC20PaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n IERC20Metadata _token,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n address(_token),\n _token.decimals(),\n _currency,\n _baseWeightCurrency,\n _payoutSplitsGroup,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from == address(this)\n ? IERC20(token).transfer(_to, _amount)\n : IERC20(token).transferFrom(_from, _to, _amount);\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal override {\n IERC20(token).approve(_to, _amount);\n }\n}\n" }, "contracts/JBSingleTokenPaymentTerminalStore.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBSingleTokenPaymentTerminalStore is IJBSingleTokenPaymentTerminalStore, ReentrancyGuard {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n Mint's 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegate A delegate contract to use for subsequent calls.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n IJBPayDelegate delegate,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay()) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegate) = IJBFundingCycleDataSource(fundingCycle.dataSource()).payParams(\n _data\n );\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegate, memo);\n\n // Add the amount to the token balance of the project.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount.value;\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegate, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegate A delegate contract to use for subsequent calls.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n IJBRedemptionDelegate delegate,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\n _projectId,\n fundingCycle.reservedRate()\n );\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow > 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem()) {\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n fundingCycle.redemptionRate(),\n fundingCycle.ballotRedemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegate) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .redeemParams(_data);\n } else {\n memo = _memo;\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (reclaimAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (reclaimAmount > 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n reclaimAmount;\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n return _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i = 0; _i < _terminals.length; _i++)\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.ETH\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.ETH, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBSingleTokenPaymentTerminalStore is IJBSingleTokenPaymentTerminalStore, ReentrancyGuard {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n Mint's 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegate A delegate contract to use for subsequent calls.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n IJBPayDelegate delegate,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay()) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegate) = IJBFundingCycleDataSource(fundingCycle.dataSource()).payParams(\n _data\n );\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegate, memo);\n\n // Add the amount to the token balance of the project.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount.value;\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegate, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegate A delegate contract to use for subsequent calls.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n IJBRedemptionDelegate delegate,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\n _projectId,\n fundingCycle.reservedRate()\n );\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow > 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem()) {\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n fundingCycle.redemptionRate(),\n fundingCycle.ballotRedemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegate) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .redeemParams(_data);\n } else {\n memo = _memo;\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (reclaimAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (reclaimAmount > 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n reclaimAmount;\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n return _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i = 0; _i < _terminals.length; _i++)\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.GAS_CURRENCY\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.GAS_CURRENCY, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" }, "contracts/JBFundingCycleStore.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './abstract/JBControllerUtility.sol';\nimport './libraries/JBConstants.sol';\n\n/** \n @notice \n Manages funding cycle configurations and scheduling.\n\n @dev\n Adheres to -\n IJBTokenStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBControllerUtility: Includes convenience functionality for checking if the message sender is the current controller of the project whose data is being manipulated.\n*/\ncontract JBFundingCycleStore is IJBFundingCycleStore, JBControllerUtility {\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_DISCOUNT_RATE();\n error INVALID_DURATION();\n error INVALID_WEIGHT();\n error NO_SAME_BLOCK_RECONFIGURATION();\n\n //*********************************************************************//\n // --------------------- private stored properties ------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Stores the user defined properties of each funding cycle, packed into one storage slot.\n\n _projectId The ID of the project to get properties of.\n _configuration The funding cycle configuration to get properties of.\n */\n mapping(uint256 => mapping(uint256 => uint256)) private _packedUserPropertiesOf;\n\n /** \n @notice\n Stores the properties added by the mechanism to manage and schedule each funding cycle, packed into one storage slot.\n \n _projectId The ID of the project to get instrinsic properties of.\n _configuration The funding cycle configuration to get properties of.\n */\n mapping(uint256 => mapping(uint256 => uint256)) private _packedIntrinsicPropertiesOf;\n\n /** \n @notice\n Stores the metadata for each funding cycle configuration, packed into one storage slot.\n\n _projectId The ID of the project to get metadata of.\n _configuration The funding cycle configuration to get metadata of.\n */\n mapping(uint256 => mapping(uint256 => uint256)) private _metadataOf;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The latest funding cycle configuration for each project.\n\n _projectId The ID of the project to get the latest funding cycle configuration of.\n */\n mapping(uint256 => uint256) public override latestConfigurationOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice \n Get the funding cycle with the given configuration for the specified project.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n @param _configuration The configuration of the funding cycle to get.\n\n @return fundingCycle The funding cycle.\n */\n function get(uint256 _projectId, uint256 _configuration)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle)\n {\n return _getStructFor(_projectId, _configuration);\n }\n\n /**\n @notice \n The latest funding cycle to be configured for the specified project, and its current ballot state.\n\n @param _projectId The ID of the project to get the latest configured funding cycle of.\n\n @return fundingCycle The project's queued funding cycle.\n @return ballotState The state of the ballot for the reconfiguration.\n */\n function latestConfiguredOf(uint256 _projectId)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle, JBBallotState ballotState)\n {\n // Get a reference to the latest funding cycle configuration.\n uint256 _fundingCycleConfiguration = latestConfigurationOf[_projectId];\n\n // Resolve the funding cycle for the latest configuration.\n fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n // Resolve the ballot state.\n ballotState = _ballotStateOf(\n _projectId,\n fundingCycle.configuration,\n fundingCycle.start,\n fundingCycle.basedOn\n );\n }\n\n /**\n @notice \n The funding cycle that's next up for the specified project.\n\n @dev\n If a queued funding cycle of the project is not found, returns an empty funding cycle with all properties set to 0.\n\n @param _projectId The ID of the project to get the queued funding cycle of.\n\n @return fundingCycle The project's queued funding cycle.\n */\n function queuedOf(uint256 _projectId)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle)\n {\n // If the project does not have a funding cycle, return an empty struct.\n if (latestConfigurationOf[_projectId] == 0) return _getStructFor(0, 0);\n\n // Get a reference to the configuration of the standby funding cycle.\n uint256 _standbyFundingCycleConfiguration = _standbyOf(_projectId);\n\n // If it exists, return its funding cycle if it is approved.\n if (_standbyFundingCycleConfiguration > 0) {\n fundingCycle = _getStructFor(_projectId, _standbyFundingCycleConfiguration);\n\n if (_isApproved(_projectId, fundingCycle)) return fundingCycle;\n\n // Resolve the funding cycle for the latest configured funding cycle.\n fundingCycle = _getStructFor(_projectId, fundingCycle.basedOn);\n } else {\n // Resolve the funding cycle for the latest configured funding cycle.\n fundingCycle = _getStructFor(_projectId, latestConfigurationOf[_projectId]);\n\n // If the latest funding cycle starts in the future, it must start in the distant future\n // since its not in standby. In this case base the queued cycles on the base cycle.\n if (fundingCycle.start > block.timestamp)\n fundingCycle = _getStructFor(_projectId, fundingCycle.basedOn);\n }\n\n // There's no queued if the current has a duration of 0.\n if (fundingCycle.duration == 0) return _getStructFor(0, 0);\n\n // Check to see if this funding cycle's ballot is approved.\n // If so, return a funding cycle based on it.\n if (_isApproved(_projectId, fundingCycle)) return _mockFundingCycleBasedOn(fundingCycle, false);\n\n // Get the funding cycle of its base funding cycle, which carries the last approved configuration.\n fundingCycle = _getStructFor(_projectId, fundingCycle.basedOn);\n\n // There's no queued if the base, which must still be the current, has a duration of 0.\n if (fundingCycle.duration == 0) return _getStructFor(0, 0);\n\n // Return a mock of the next up funding cycle.\n return _mockFundingCycleBasedOn(fundingCycle, false);\n }\n\n /**\n @notice \n The funding cycle that is currently active for the specified project.\n\n @dev\n If a current funding cycle of the project is not found, returns an empty funding cycle with all properties set to 0.\n\n @param _projectId The ID of the project to get the current funding cycle of.\n\n @return fundingCycle The project's current funding cycle.\n */\n function currentOf(uint256 _projectId)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle)\n {\n // If the project does not have a funding cycle, return an empty struct.\n if (latestConfigurationOf[_projectId] == 0) return _getStructFor(0, 0);\n\n // Get a reference to the configuration of the eligible funding cycle.\n uint256 _fundingCycleConfiguration = _eligibleOf(_projectId);\n\n // Keep a reference to the eligible funding cycle.\n JBFundingCycle memory _fundingCycle;\n\n // If an eligible funding cycle exists...\n if (_fundingCycleConfiguration > 0) {\n // Resolve the funding cycle for the eligible configuration.\n _fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n // Check to see if this funding cycle's ballot is approved.\n // If so, return it.\n if (_isApproved(_projectId, _fundingCycle)) return _fundingCycle;\n\n // If it hasn't been approved, set the funding cycle configuration to be the configuration of the funding cycle that it's based on,\n // which carries the last approved configuration.\n _fundingCycleConfiguration = _fundingCycle.basedOn;\n } else {\n // No upcoming funding cycle found that is eligible to become active,\n // so use the last configuration.\n _fundingCycleConfiguration = latestConfigurationOf[_projectId];\n\n // Get the funding cycle for the latest ID.\n _fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n // If it's not approved or if it hasn't yet started, get a reference to the funding cycle that the latest is based on, which has the latest approved configuration.\n if (!_isApproved(_projectId, _fundingCycle) || block.timestamp < _fundingCycle.start)\n _fundingCycleConfiguration = _fundingCycle.basedOn;\n }\n\n // If there is not funding cycle to base the current one on, there can't be a current one.\n if (_fundingCycleConfiguration == 0) return _getStructFor(0, 0);\n\n // The funding cycle to base a current one on.\n _fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n // If the base has no duration, it's still the current one.\n if (_fundingCycle.duration == 0) return _fundingCycle;\n\n // Return a mock of the current funding cycle.\n return _mockFundingCycleBasedOn(_fundingCycle, true);\n }\n\n /** \n @notice \n The current ballot state of the project.\n\n @param _projectId The ID of the project to check the ballot state of.\n\n @return The project's current ballot's state.\n */\n function currentBallotStateOf(uint256 _projectId) external view override returns (JBBallotState) {\n // Get a reference to the latest funding cycle configuration.\n uint256 _fundingCycleConfiguration = latestConfigurationOf[_projectId];\n\n // Resolve the funding cycle for the latest configuration.\n JBFundingCycle memory _fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n return\n _ballotStateOf(\n _projectId,\n _fundingCycle.configuration,\n _fundingCycle.start,\n _fundingCycle.basedOn\n );\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _directory A contract storing directories of terminals and controllers for each project.\n */\n // solhint-disable-next-line no-empty-blocks\n constructor(IJBDirectory _directory) JBControllerUtility(_directory) {}\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice \n Configures the next eligible funding cycle for the specified project.\n\n @dev\n Only a project's current controller can configure its funding cycles.\n\n @param _projectId The ID of the project being configured.\n @param _data The funding cycle configuration data.\n @param _metadata Arbitrary extra data to associate with this funding cycle configuration that's not used within.\n @param _mustStartAtOrAfter The time before which the initialized funding cycle cannot start.\n\n @return The funding cycle that the configuration will take effect during.\n */\n function configureFor(\n uint256 _projectId,\n JBFundingCycleData calldata _data,\n uint256 _metadata,\n uint256 _mustStartAtOrAfter\n ) external override onlyController(_projectId) returns (JBFundingCycle memory) {\n // Duration must fit in a uint64.\n if (_data.duration > type(uint64).max) revert INVALID_DURATION();\n\n // Discount rate must be less than or equal to 100%.\n if (_data.discountRate > JBConstants.MAX_DISCOUNT_RATE) revert INVALID_DISCOUNT_RATE();\n\n // Weight must fit into a uint88.\n if (_data.weight > type(uint88).max) revert INVALID_WEIGHT();\n\n // The configuration timestamp is now.\n uint256 _configuration = block.timestamp;\n\n // Set up a reconfiguration by configuring intrinsic properties.\n _configureIntrinsicPropertiesFor(\n _projectId,\n _configuration,\n _data.weight,\n // Must start on or after the current timestamp.\n _mustStartAtOrAfter > block.timestamp ? _mustStartAtOrAfter : block.timestamp\n );\n\n // Efficiently stores a funding cycles provided user defined properties.\n // If all user config properties are zero, no need to store anything as the default value will have the same outcome.\n if (\n _data.ballot != IJBFundingCycleBallot(address(0)) ||\n _data.duration > 0 ||\n _data.discountRate > 0\n ) {\n // ballot in bits 0-159 bytes.\n uint256 packed = uint160(address(_data.ballot));\n\n // duration in bits 160-223 bytes.\n packed |= _data.duration << 160;\n\n // discountRate in bits 224-255 bytes.\n packed |= _data.discountRate << 224;\n\n // Set in storage.\n _packedUserPropertiesOf[_projectId][_configuration] = packed;\n }\n\n // Set the metadata if needed.\n if (_metadata > 0) _metadataOf[_projectId][_configuration] = _metadata;\n\n emit Configure(_configuration, _projectId, _data, _metadata, _mustStartAtOrAfter, msg.sender);\n\n // Return the funding cycle for the new configuration.\n return _getStructFor(_projectId, _configuration);\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice \n Updates the configurable funding cycle for this project if it exists, otherwise creates one.\n\n @param _projectId The ID of the project to find a configurable funding cycle for.\n @param _configuration The time at which the funding cycle was configured.\n @param _weight The weight to store in the configured funding cycle.\n @param _mustStartAtOrAfter The time before which the initialized funding cycle can't start.\n */\n function _configureIntrinsicPropertiesFor(\n uint256 _projectId,\n uint256 _configuration,\n uint256 _weight,\n uint256 _mustStartAtOrAfter\n ) private {\n // If there's not yet a funding cycle for the project, initialize one.\n if (latestConfigurationOf[_projectId] == 0)\n // Use an empty funding cycle as the base.\n return\n _initFor(_projectId, _getStructFor(0, 0), _configuration, _mustStartAtOrAfter, _weight);\n\n // Get the active funding cycle's configuration.\n uint256 _currentConfiguration = _eligibleOf(_projectId);\n\n // If an eligible funding cycle does not exist, get a reference to the latest funding cycle configuration for the project.\n if (_currentConfiguration == 0)\n // Get the latest funding cycle's configuration.\n _currentConfiguration = latestConfigurationOf[_projectId];\n\n // Get a reference to the funding cycle.\n JBFundingCycle memory _baseFundingCycle = _getStructFor(_projectId, _currentConfiguration);\n\n if (!_isApproved(_projectId, _baseFundingCycle) || block.timestamp < _baseFundingCycle.start)\n // If it hasn't been approved or hasn't yet started, set the ID to be the funding cycle it's based on,\n // which carries the latest approved configuration.\n _baseFundingCycle = _getStructFor(_projectId, _baseFundingCycle.basedOn);\n\n // The configuration can't be the same as the base configuration.\n if (_baseFundingCycle.configuration == _configuration) revert NO_SAME_BLOCK_RECONFIGURATION();\n\n // The time after the ballot of the provided funding cycle has expired.\n // If the provided funding cycle has no ballot, return the current timestamp.\n uint256 _timestampAfterBallot = _baseFundingCycle.ballot == IJBFundingCycleBallot(address(0))\n ? 0\n : _configuration + _baseFundingCycle.ballot.duration();\n\n _initFor(\n _projectId,\n _baseFundingCycle,\n _configuration,\n // Can only start after the ballot.\n _timestampAfterBallot > _mustStartAtOrAfter ? _timestampAfterBallot : _mustStartAtOrAfter,\n _weight\n );\n }\n\n /**\n @notice \n Initializes a funding cycle with the specified properties.\n\n @param _projectId The ID of the project to which the funding cycle being initialized belongs.\n @param _baseFundingCycle The funding cycle to base the initialized one on.\n @param _configuration The configuration of the funding cycle being initialized.\n @param _mustStartAtOrAfter The time before which the initialized funding cycle cannot start.\n @param _weight The weight to give the newly initialized funding cycle.\n */\n function _initFor(\n uint256 _projectId,\n JBFundingCycle memory _baseFundingCycle,\n uint256 _configuration,\n uint256 _mustStartAtOrAfter,\n uint256 _weight\n ) private {\n // If there is no base, initialize a first cycle.\n if (_baseFundingCycle.number == 0) {\n // The first number is 1.\n uint256 _number = 1;\n\n // Set fresh intrinsic properties.\n _packAndStoreIntrinsicPropertiesOf(\n _configuration,\n _projectId,\n _number,\n _weight,\n _baseFundingCycle.configuration,\n _mustStartAtOrAfter\n );\n } else {\n // Derive the correct next start time from the base.\n uint256 _start = _deriveStartFrom(_baseFundingCycle, _mustStartAtOrAfter);\n\n // A weight of 1 is treated as a weight of 0.\n // This is to allow a weight of 0 (default) to represent inheriting the discounted weight of the previous funding cycle.\n _weight = _weight > 0\n ? (_weight == 1 ? 0 : _weight)\n : _deriveWeightFrom(_baseFundingCycle, _start);\n\n // Derive the correct number.\n uint256 _number = _deriveNumberFrom(_baseFundingCycle, _start);\n\n // Update the intrinsic properties.\n _packAndStoreIntrinsicPropertiesOf(\n _configuration,\n _projectId,\n _number,\n _weight,\n _baseFundingCycle.configuration,\n _start\n );\n }\n\n // Set the project's latest funding cycle configuration.\n latestConfigurationOf[_projectId] = _configuration;\n\n emit Init(_configuration, _projectId, _baseFundingCycle.configuration);\n }\n\n /**\n @notice \n Efficiently stores a funding cycle's provided intrinsic properties.\n\n @param _configuration The configuration of the funding cycle to pack and store.\n @param _projectId The ID of the project to which the funding cycle belongs.\n @param _number The number of the funding cycle.\n @param _weight The weight of the funding cycle.\n @param _basedOn The configuration of the base funding cycle.\n @param _start The start time of this funding cycle.\n */\n function _packAndStoreIntrinsicPropertiesOf(\n uint256 _configuration,\n uint256 _projectId,\n uint256 _number,\n uint256 _weight,\n uint256 _basedOn,\n uint256 _start\n ) private {\n // weight in bits 0-87.\n uint256 packed = _weight;\n\n // basedOn in bits 88-143.\n packed |= _basedOn << 88;\n\n // start in bits 144-199.\n packed |= _start << 144;\n\n // number in bits 200-255.\n packed |= _number << 200;\n\n // Store the packed value.\n _packedIntrinsicPropertiesOf[_projectId][_configuration] = packed;\n }\n\n /**\n @notice \n The project's stored funding cycle that hasn't yet started and should be used next, if one exists.\n\n @dev\n A value of 0 is returned if no funding cycle was found.\n\n @dev\n Assumes the project has a latest configuration.\n \n @param _projectId The ID of a project to look through for a standby cycle.\n\n @return configuration The configuration of the standby funding cycle if one exists, or 0 if one doesn't exist.\n */\n function _standbyOf(uint256 _projectId) private view returns (uint256 configuration) {\n // Get a reference to the project's latest funding cycle.\n configuration = latestConfigurationOf[_projectId];\n\n // Get the necessary properties for the latest funding cycle.\n JBFundingCycle memory _fundingCycle = _getStructFor(_projectId, configuration);\n\n // There is no upcoming funding cycle if the latest funding cycle has already started.\n if (block.timestamp >= _fundingCycle.start) return 0;\n\n // If this is the first funding cycle, it is queued.\n if (_fundingCycle.number == 1) return configuration;\n\n // Get the necessary properties for the base funding cycle.\n JBFundingCycle memory _baseFundingCycle = _getStructFor(_projectId, _fundingCycle.basedOn);\n\n // If the latest configuration doesn't start until after another base cycle, return 0.\n if (\n _baseFundingCycle.duration > 0 &&\n block.timestamp < _fundingCycle.start - _baseFundingCycle.duration\n ) return 0;\n }\n\n /**\n @notice \n The project's stored funding cycle that has started and hasn't yet expired.\n \n @dev\n A value of 0 is returned if no funding cycle was found.\n\n @dev\n Assumes the project has a latest configuration.\n\n @param _projectId The ID of the project to look through.\n\n @return configuration The configuration of an eligible funding cycle if one exists, or 0 if one doesn't exist.\n */\n function _eligibleOf(uint256 _projectId) private view returns (uint256 configuration) {\n // Get a reference to the project's latest funding cycle.\n configuration = latestConfigurationOf[_projectId];\n\n // Get the latest funding cycle.\n JBFundingCycle memory _fundingCycle = _getStructFor(_projectId, configuration);\n\n // If the latest is expired, return an empty funding cycle.\n // A duration of 0 cannot be expired.\n if (\n _fundingCycle.duration > 0 && block.timestamp >= _fundingCycle.start + _fundingCycle.duration\n ) return 0;\n\n // Return the funding cycle's configuration if it has started.\n if (block.timestamp >= _fundingCycle.start) return _fundingCycle.configuration;\n\n // Get a reference to the cycle's base configuration.\n JBFundingCycle memory _baseFundingCycle = _getStructFor(_projectId, _fundingCycle.basedOn);\n\n // If the base cycle isn't eligible, the project has no eligible cycle.\n // A duration of 0 is always eligible.\n if (\n _baseFundingCycle.duration > 0 &&\n block.timestamp >= _baseFundingCycle.start + _baseFundingCycle.duration\n ) return 0;\n\n // Return the configuration that the latest funding cycle is based on.\n configuration = _fundingCycle.basedOn;\n }\n\n /** \n @notice \n A view of the funding cycle that would be created based on the provided one if the project doesn't make a reconfiguration.\n\n @dev\n Returns an empty funding cycle if there can't be a mock funding cycle based on the provided one.\n\n @dev\n Assumes a funding cycle with a duration of 0 will never be asked to be the base of a mock.\n\n @param _baseFundingCycle The funding cycle that the resulting funding cycle should follow.\n @param _allowMidCycle A flag indicating if the mocked funding cycle is allowed to already be mid cycle.\n\n @return A mock of what the next funding cycle will be.\n */\n function _mockFundingCycleBasedOn(JBFundingCycle memory _baseFundingCycle, bool _allowMidCycle)\n private\n view\n returns (JBFundingCycle memory)\n {\n // Get the distance of the current time to the start of the next possible funding cycle.\n // If the returned mock cycle must not yet have started, the start time of the mock must be in the future.\n uint256 _mustStartAtOrAfter = !_allowMidCycle\n ? block.timestamp + 1\n : block.timestamp - _baseFundingCycle.duration + 1;\n\n // Derive what the start time should be.\n uint256 _start = _deriveStartFrom(_baseFundingCycle, _mustStartAtOrAfter);\n\n // Derive what the number should be.\n uint256 _number = _deriveNumberFrom(_baseFundingCycle, _start);\n\n return\n JBFundingCycle(\n _number,\n _baseFundingCycle.configuration,\n _baseFundingCycle.basedOn,\n _start,\n _baseFundingCycle.duration,\n _deriveWeightFrom(_baseFundingCycle, _start),\n _baseFundingCycle.discountRate,\n _baseFundingCycle.ballot,\n _baseFundingCycle.metadata\n );\n }\n\n /** \n @notice \n The date that is the nearest multiple of the specified funding cycle's duration from its end.\n\n @param _baseFundingCycle The funding cycle to base the calculation on.\n @param _mustStartAtOrAfter A date that the derived start must be on or come after.\n\n @return start The next start time.\n */\n function _deriveStartFrom(JBFundingCycle memory _baseFundingCycle, uint256 _mustStartAtOrAfter)\n private\n pure\n returns (uint256 start)\n {\n // A subsequent cycle to one with a duration of 0 should start as soon as possible.\n if (_baseFundingCycle.duration == 0) return _mustStartAtOrAfter;\n\n // The time when the funding cycle immediately after the specified funding cycle starts.\n uint256 _nextImmediateStart = _baseFundingCycle.start + _baseFundingCycle.duration;\n\n // If the next immediate start is now or in the future, return it.\n if (_nextImmediateStart >= _mustStartAtOrAfter) return _nextImmediateStart;\n\n // The amount of seconds since the `_mustStartAtOrAfter` time which results in a start time that might satisfy the specified constraints.\n uint256 _timeFromImmediateStartMultiple = (_mustStartAtOrAfter - _nextImmediateStart) %\n _baseFundingCycle.duration;\n\n // A reference to the first possible start timestamp.\n start = _mustStartAtOrAfter - _timeFromImmediateStartMultiple;\n\n // Add increments of duration as necessary to satisfy the threshold.\n while (_mustStartAtOrAfter > start) start = start + _baseFundingCycle.duration;\n }\n\n /** \n @notice \n The accumulated weight change since the specified funding cycle.\n\n @param _baseFundingCycle The funding cycle to base the calculation on.\n @param _start The start time of the funding cycle to derive a number for.\n\n @return weight The derived weight, as a fixed point number with 18 decimals.\n */\n function _deriveWeightFrom(JBFundingCycle memory _baseFundingCycle, uint256 _start)\n private\n pure\n returns (uint256 weight)\n {\n // A subsequent cycle to one with a duration of 0 should have the next possible weight.\n if (_baseFundingCycle.duration == 0)\n return\n PRBMath.mulDiv(\n _baseFundingCycle.weight,\n JBConstants.MAX_DISCOUNT_RATE - _baseFundingCycle.discountRate,\n JBConstants.MAX_DISCOUNT_RATE\n );\n\n // The weight should be based off the base funding cycle's weight.\n weight = _baseFundingCycle.weight;\n\n // If the discount is 0, the weight doesn't change.\n if (_baseFundingCycle.discountRate == 0) return weight;\n\n // The difference between the start of the base funding cycle and the proposed start.\n uint256 _startDistance = _start - _baseFundingCycle.start;\n\n // Apply the base funding cycle's discount rate for each cycle that has passed.\n uint256 _discountMultiple = _startDistance / _baseFundingCycle.duration;\n\n for (uint256 i = 0; i < _discountMultiple; i++) {\n // The number of times to apply the discount rate.\n // Base the new weight on the specified funding cycle's weight.\n weight = PRBMath.mulDiv(\n weight,\n JBConstants.MAX_DISCOUNT_RATE - _baseFundingCycle.discountRate,\n JBConstants.MAX_DISCOUNT_RATE\n );\n // The calculation doesn't need to continue if the weight is 0.\n if (weight == 0) break;\n }\n }\n\n /** \n @notice \n The number of the next funding cycle given the specified funding cycle.\n\n @param _baseFundingCycle The funding cycle to base the calculation on.\n @param _start The start time of the funding cycle to derive a number for.\n\n @return The funding cycle number.\n */\n function _deriveNumberFrom(JBFundingCycle memory _baseFundingCycle, uint256 _start)\n private\n pure\n returns (uint256)\n {\n // A subsequent cycle to one with a duration of 0 should be the next number.\n if (_baseFundingCycle.duration == 0) return _baseFundingCycle.number + 1;\n\n // The difference between the start of the base funding cycle and the proposed start.\n uint256 _startDistance = _start - _baseFundingCycle.start;\n\n // Find the number of base cycles that fit in the start distance.\n return _baseFundingCycle.number + (_startDistance / _baseFundingCycle.duration);\n }\n\n /** \n @notice \n Checks to see if the provided funding cycle is approved according to the correct ballot.\n\n @param _projectId The ID of the project to which the funding cycle belongs. \n @param _fundingCycle The funding cycle to get an approval flag for.\n\n @return The approval flag.\n */\n function _isApproved(uint256 _projectId, JBFundingCycle memory _fundingCycle)\n private\n view\n returns (bool)\n {\n return\n _ballotStateOf(\n _projectId,\n _fundingCycle.configuration,\n _fundingCycle.start,\n _fundingCycle.basedOn\n ) == JBBallotState.Approved;\n }\n\n /**\n @notice \n A project's latest funding cycle configuration approval status.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n @param _configuration The funding cycle configuration to get the ballot state of.\n @param _start The start time of the funding cycle configuration to get the ballot state of.\n @param _ballotFundingCycleConfiguration The configuration of the funding cycle which is configured with the ballot that should be used.\n\n @return The ballot state of the project.\n */\n function _ballotStateOf(\n uint256 _projectId,\n uint256 _configuration,\n uint256 _start,\n uint256 _ballotFundingCycleConfiguration\n ) private view returns (JBBallotState) {\n // If there is no ballot funding cycle, implicitly approve.\n if (_ballotFundingCycleConfiguration == 0) return JBBallotState.Approved;\n\n // Get the ballot funding cycle.\n JBFundingCycle memory _ballotFundingCycle = _getStructFor(\n _projectId,\n _ballotFundingCycleConfiguration\n );\n\n // If there is no ballot, the ID is auto approved.\n // Otherwise if the ballot's duration hasn't passed, its still active.\n // Otherwise, return the ballot's state.\n if (_ballotFundingCycle.ballot == IJBFundingCycleBallot(address(0)))\n return JBBallotState.Approved;\n else if (_ballotFundingCycle.ballot.duration() >= block.timestamp - _configuration)\n return JBBallotState.Active;\n else return _ballotFundingCycle.ballot.stateOf(_projectId, _configuration, _start);\n }\n\n /**\n @notice \n Unpack a funding cycle's packed stored values into an easy-to-work-with funding cycle struct.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n @param _configuration The funding cycle configuration to get the full struct for.\n\n @return fundingCycle A funding cycle struct.\n */\n function _getStructFor(uint256 _projectId, uint256 _configuration)\n private\n view\n returns (JBFundingCycle memory fundingCycle)\n {\n // Return an empty funding cycle if the configuration specified is 0.\n if (_configuration == 0) return fundingCycle;\n\n fundingCycle.configuration = _configuration;\n\n uint256 _packedIntrinsicProperties = _packedIntrinsicPropertiesOf[_projectId][_configuration];\n\n // weight in bits 0-87 bits.\n fundingCycle.weight = uint256(uint88(_packedIntrinsicProperties));\n // basedOn in bits 88-143 bits.\n fundingCycle.basedOn = uint256(uint56(_packedIntrinsicProperties >> 88));\n // start in bits 144-199 bits.\n fundingCycle.start = uint256(uint56(_packedIntrinsicProperties >> 144));\n // number in bits 200-255 bits.\n fundingCycle.number = uint256(uint56(_packedIntrinsicProperties >> 200));\n\n uint256 _packedUserProperties = _packedUserPropertiesOf[_projectId][_configuration];\n\n // ballot in bits 0-159 bits.\n fundingCycle.ballot = IJBFundingCycleBallot(address(uint160(_packedUserProperties)));\n // duration in bits 160-223 bits.\n fundingCycle.duration = uint256(uint64(_packedUserProperties >> 160));\n // discountRate in bits 224-255 bits.\n fundingCycle.discountRate = uint256(uint32(_packedUserProperties >> 224));\n\n fundingCycle.metadata = _metadataOf[_projectId][_configuration];\n }\n}\n" @@ -170,7 +170,7 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './../interfaces/IJBSplitAllocator.sol';\n\n/** \n @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.\n @member preferAddToBalance A flag indicating if a distribution to a project should prefer triggering it's addToBalance function instead of its pay function.\n @member percent The percent of the whole group that this split occupies. This number is out of `JBConstants.SPLITS_TOTAL_PERCENT`.\n @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.\n @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.\n @member lockedUntil Specifies if the split should be unchangeable until the specified time, with the exception of extending the locked period.\n @member allocator If an allocator is specified, funds will be sent to the allocator contract along with all properties of this split.\n*/\nstruct JBSplit {\n bool preferClaimed;\n bool preferAddToBalance;\n uint256 percent;\n uint256 projectId;\n address payable beneficiary;\n uint256 lockedUntil;\n IJBSplitAllocator allocator;\n}\n" }, "contracts/system_tests/helpers/AccessJBLib.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '../../libraries/JBCurrencies.sol';\nimport '../../libraries/JBConstants.sol';\nimport '../../libraries/JBTokens.sol';\n\ncontract AccessJBLib {\n function ETH() external pure returns (uint256) {\n return JBCurrencies.ETH;\n }\n\n function USD() external pure returns (uint256) {\n return JBCurrencies.USD;\n }\n\n function ETHToken() external pure returns (address) {\n return JBTokens.ETH;\n }\n\n function MAX_FEE() external pure returns (uint256) {\n return JBConstants.MAX_FEE;\n }\n\n function MAX_RESERVED_RATE() external pure returns (uint256) {\n return JBConstants.MAX_RESERVED_RATE;\n }\n\n function MAX_REDEMPTION_RATE() external pure returns (uint256) {\n return JBConstants.MAX_REDEMPTION_RATE;\n }\n\n function MAX_DISCOUNT_RATE() external pure returns (uint256) {\n return JBConstants.MAX_DISCOUNT_RATE;\n }\n\n function SPLITS_TOTAL_PERCENT() external pure returns (uint256) {\n return JBConstants.SPLITS_TOTAL_PERCENT;\n }\n\n function MAX_FEE_DISCOUNT() external pure returns (uint256) {\n return JBConstants.MAX_FEE_DISCOUNT;\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '../../libraries/JBCurrencies.sol';\nimport '../../libraries/JBConstants.sol';\nimport '../../libraries/JBTokens.sol';\n\ncontract AccessJBLib {\n function ETH() external pure returns (uint256) {\n return JBCurrencies.GAS_CURRENCY;\n }\n\n function USD() external pure returns (uint256) {\n return JBCurrencies.USD;\n }\n\n function ETHToken() external pure returns (address) {\n return JBTokens.GAS_TOKEN;\n }\n\n function MAX_FEE() external pure returns (uint256) {\n return JBConstants.MAX_FEE;\n }\n\n function MAX_RESERVED_RATE() external pure returns (uint256) {\n return JBConstants.MAX_RESERVED_RATE;\n }\n\n function MAX_REDEMPTION_RATE() external pure returns (uint256) {\n return JBConstants.MAX_REDEMPTION_RATE;\n }\n\n function MAX_DISCOUNT_RATE() external pure returns (uint256) {\n return JBConstants.MAX_DISCOUNT_RATE;\n }\n\n function SPLITS_TOTAL_PERCENT() external pure returns (uint256) {\n return JBConstants.SPLITS_TOTAL_PERCENT;\n }\n\n function MAX_FEE_DISCOUNT() external pure returns (uint256) {\n return JBConstants.MAX_FEE_DISCOUNT;\n }\n}\n" }, "@paulrberg/contracts/math/PRBMath.sol": { "content": "// SPDX-License-Identifier: Unlicense\npragma solidity >=0.8.4;\n\nimport \"prb-math/contracts/PRBMath.sol\";\n" @@ -227,7 +227,7 @@ "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" }, "contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBSplitsGroups.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal is\n IJBPayoutRedemptionPaymentTerminal,\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n ReentrancyGuard\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The protocol project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _PROTOCOL_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.ETH)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.ETH, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.ETH) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i = 0; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @dev\n If the fee gauge reverts when called upon while a project is attempting to distribute its funds, a project's funds will be locked. This is a known risk.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual;\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual;\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegate` only used within scope.\n {\n IJBRedemptionDelegate _delegate;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegate, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If a delegate was returned by the data source, issue a callback to it.\n if (_delegate != IJBRedemptionDelegate(address(0))) {\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _beneficiary,\n _memo,\n _metadata\n );\n _delegate.didRedeem(_data);\n emit DelegateDidRedeem(_delegate, _data, msg.sender);\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convinience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n\n // Take the fee.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || _feeEligibleDistributionAmount == 0\n ? 0\n : _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n );\n\n // Get a reference to how much to distribute to the project owner, which is the leftover amount minus any fees.\n\n unchecked {\n netLeftoverDistributionAmount = _leftoverDistributionAmount == 0\n ? 0\n : _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n }\n\n // Transfer any remaining balance to the project owner.\n if (netLeftoverDistributionAmount > 0)\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convinience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i = 0; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount;\n\n if (_payoutAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (isFeelessAddress[address(_split.allocator)])\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _netPayoutAmount : 0;\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n _netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // Save gas if this contract is being used as the terminal.\n if (_terminal == this) {\n // This distribution does not incur a fee.\n _netPayoutAmount = _payoutAmount;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\n else\n _pay(\n _netPayoutAmount,\n address(this),\n _split.projectId,\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n } else {\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (isFeelessAddress[address(_terminal)])\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _netPayoutAmount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _terminal.addToBalanceOf{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n '',\n _projectMetadata\n );\n else\n _terminal.pay{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n }\n } else {\n unchecked {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(\n address(this),\n _split.beneficiary != address(0) ? _split.beneficiary : payable(msg.sender),\n _netPayoutAmount\n );\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _PROTOCOL_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n */\n function _processFee(uint256 _amount, address _beneficiary) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_PROTOCOL_PROJECT_ID, token);\n\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\n if (_terminal == this)\n _pay(_amount, address(this), _PROTOCOL_PROJECT_ID, _beneficiary, 0, false, '', bytes('')); // Use the local pay call.\n else {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _amount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _amount : 0;\n\n // Send the payment.\n _terminal.pay{value: _payableValue}(\n _PROTOCOL_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the external pay call of the correct terminal.\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegate` and `_tokenCount` only used within scope.\n {\n IJBPayDelegate _delegate;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegate, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If a delegate was returned by the data source, issue a callback to it.\n if (_delegate != IJBPayDelegate(address(0))) {\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n _delegate.didPay(_data);\n emit DelegateDidPay(_delegate, _data, msg.sender);\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i = 0; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n unchecked {\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256 feeDiscount) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (directory.primaryTerminalOf(_PROTOCOL_PROJECT_ID, token) == IJBPaymentTerminal(address(0)))\n return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge == IJBFeeGauge(address(0)))\n feeDiscount = 0;\n // If the guage reverts, set the discount to 0.\n else\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n feeDiscount = discount;\n } catch {\n feeDiscount = 0;\n }\n\n // If the fee discount is greater than the max, nullify the discount.\n if (feeDiscount > JBConstants.MAX_FEE_DISCOUNT) feeDiscount = 0;\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBSplitsGroups.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal is\n IJBPayoutRedemptionPaymentTerminal,\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n ReentrancyGuard\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The protocol project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _PROTOCOL_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.GAS_CURRENCY)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.GAS_CURRENCY, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.GAS_TOKEN) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i = 0; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @dev\n If the fee gauge reverts when called upon while a project is attempting to distribute its funds, a project's funds will be locked. This is a known risk.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual;\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual;\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegate` only used within scope.\n {\n IJBRedemptionDelegate _delegate;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegate, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If a delegate was returned by the data source, issue a callback to it.\n if (_delegate != IJBRedemptionDelegate(address(0))) {\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _beneficiary,\n _memo,\n _metadata\n );\n _delegate.didRedeem(_data);\n emit DelegateDidRedeem(_delegate, _data, msg.sender);\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convinience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n\n // Take the fee.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || _feeEligibleDistributionAmount == 0\n ? 0\n : _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n );\n\n // Get a reference to how much to distribute to the project owner, which is the leftover amount minus any fees.\n\n unchecked {\n netLeftoverDistributionAmount = _leftoverDistributionAmount == 0\n ? 0\n : _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n }\n\n // Transfer any remaining balance to the project owner.\n if (netLeftoverDistributionAmount > 0)\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convinience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i = 0; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount;\n\n if (_payoutAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (isFeelessAddress[address(_split.allocator)])\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0;\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n _netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // Save gas if this contract is being used as the terminal.\n if (_terminal == this) {\n // This distribution does not incur a fee.\n _netPayoutAmount = _payoutAmount;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\n else\n _pay(\n _netPayoutAmount,\n address(this),\n _split.projectId,\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n } else {\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (isFeelessAddress[address(_terminal)])\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _terminal.addToBalanceOf{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n '',\n _projectMetadata\n );\n else\n _terminal.pay{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n }\n } else {\n unchecked {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(\n address(this),\n _split.beneficiary != address(0) ? _split.beneficiary : payable(msg.sender),\n _netPayoutAmount\n );\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _PROTOCOL_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n */\n function _processFee(uint256 _amount, address _beneficiary) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_PROTOCOL_PROJECT_ID, token);\n\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\n if (_terminal == this)\n _pay(_amount, address(this), _PROTOCOL_PROJECT_ID, _beneficiary, 0, false, '', bytes('')); // Use the local pay call.\n else {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _amount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send the payment.\n _terminal.pay{value: _payableValue}(\n _PROTOCOL_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the external pay call of the correct terminal.\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegate` and `_tokenCount` only used within scope.\n {\n IJBPayDelegate _delegate;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegate, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If a delegate was returned by the data source, issue a callback to it.\n if (_delegate != IJBPayDelegate(address(0))) {\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n _delegate.didPay(_data);\n emit DelegateDidPay(_delegate, _data, msg.sender);\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i = 0; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n unchecked {\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256 feeDiscount) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (directory.primaryTerminalOf(_PROTOCOL_PROJECT_ID, token) == IJBPaymentTerminal(address(0)))\n return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge == IJBFeeGauge(address(0)))\n feeDiscount = 0;\n // If the guage reverts, set the discount to 0.\n else\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n feeDiscount = discount;\n } catch {\n feeDiscount = 0;\n }\n\n // If the fee discount is greater than the max, nullify the discount.\n if (feeDiscount > JBConstants.MAX_FEE_DISCOUNT) feeDiscount = 0;\n }\n}\n" }, "@openzeppelin/contracts/security/ReentrancyGuard.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n constructor() {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n // On the first call to nonReentrant, _notEntered will be true\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n\n _;\n\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n}\n" @@ -311,31 +311,31 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './IJBFundingCycleBallot.sol';\n\ninterface IJBReconfigurationBufferBallot is IJBFundingCycleBallot {\n event Finalize(\n uint256 indexed projectId,\n uint256 indexed configuration,\n JBBallotState indexed ballotState,\n address caller\n );\n\n function finalState(uint256 _projectId, uint256 _configuration)\n external\n view\n returns (JBBallotState);\n\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\n\n function finalize(uint256 _projectId, uint256 _configured) external returns (JBBallotState);\n}\n" }, "contracts/system_tests/TestEIP165.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './helpers/TestBaseWorkflow.sol';\nimport '../JBReconfigurationBufferBallot.sol';\nimport '../JBETHERC20SplitsPayer.sol';\n\ncontract TestEIP165 is TestBaseWorkflow {\n bytes4 constant notSupportedInterface = 0xffffffff;\n\n uint256 constant projectId = 2;\n uint256 constant splitsProjectID = 3;\n address payable constant splitsBeneficiary = payable(address(420));\n uint256 constant splitsDomain = 1;\n uint256 constant splitsGroup = 1;\n bool constant splitsPreferClaimedTokens = false;\n string constant splitsMemo = '';\n bytes constant splitsMetadata = '';\n bool constant splitsPreferAddToBalance = true;\n address constant splitsOwner = address(420);\n\n function testJBController() public {\n JBController controller = jbController();\n\n // Should support these interfaces\n assertTrue(controller.supportsInterface(type(IERC165).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBController).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBMigratable).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!controller.supportsInterface(notSupportedInterface));\n }\n\n function testJBERC20PaymentTerminal() public {\n JBERC20PaymentTerminal terminal = new JBERC20PaymentTerminal(\n jbToken(),\n jbLibraries().USD(), // currency\n jbLibraries().ETH(), // base weight currency\n 1, // JBSplitsGroupe\n jbOperatorStore(),\n jbProjects(),\n jbDirectory(),\n jbSplitsStore(),\n jbPrices(),\n jbPaymentTerminalStore(),\n multisig()\n );\n\n // Should support these interfaces\n assertTrue(terminal.supportsInterface(type(IERC165).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBRedemptionTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBSingleTokenPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!terminal.supportsInterface(notSupportedInterface));\n }\n\n function testJBETHPaymentTerminal() public {\n JBETHPaymentTerminal terminal = jbETHPaymentTerminal();\n\n // Should support these interfaces\n assertTrue(terminal.supportsInterface(type(IERC165).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBRedemptionTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBSingleTokenPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!terminal.supportsInterface(notSupportedInterface));\n }\n\n function testJBProjects() public {\n JBProjects projects = jbProjects();\n\n // Should support these interfaces\n assertTrue(projects.supportsInterface(type(IERC165).interfaceId));\n assertTrue(projects.supportsInterface(type(IERC721).interfaceId));\n assertTrue(projects.supportsInterface(type(IERC721Metadata).interfaceId));\n assertTrue(projects.supportsInterface(type(IJBProjects).interfaceId));\n assertTrue(projects.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!projects.supportsInterface(notSupportedInterface));\n }\n\n function testJBReconfigurationBufferBallot() public {\n JBReconfigurationBufferBallot ballot = new JBReconfigurationBufferBallot(\n 3000,\n jbFundingCycleStore()\n );\n\n // Should support these interfaces\n assertTrue(ballot.supportsInterface(type(IERC165).interfaceId));\n assertTrue(ballot.supportsInterface(type(IJBReconfigurationBufferBallot).interfaceId));\n assertTrue(ballot.supportsInterface(type(IJBFundingCycleBallot).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!ballot.supportsInterface(notSupportedInterface));\n }\n\n function testJBETHERC20SplitsPayer() public {\n JBETHERC20SplitsPayer splitsPayer = new JBETHERC20SplitsPayer(\n splitsProjectID,\n splitsDomain,\n splitsGroup,\n jbSplitsStore(),\n projectId,\n splitsBeneficiary,\n splitsPreferClaimedTokens,\n splitsMemo,\n splitsMetadata,\n splitsPreferAddToBalance,\n splitsOwner\n );\n\n // Should support these interfaces\n assertTrue(splitsPayer.supportsInterface(type(IERC165).interfaceId));\n assertTrue(splitsPayer.supportsInterface(type(IJBSplitsPayer).interfaceId));\n assertTrue(splitsPayer.supportsInterface(type(IJBProjectPayer).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!splitsPayer.supportsInterface(notSupportedInterface));\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './helpers/TestBaseWorkflow.sol';\nimport '../JBReconfigurationBufferBallot.sol';\nimport '../JBGasTokenERC20SplitsPayer.sol';\n\ncontract TestEIP165 is TestBaseWorkflow {\n bytes4 constant notSupportedInterface = 0xffffffff;\n\n uint256 constant projectId = 2;\n uint256 constant splitsProjectID = 3;\n address payable constant splitsBeneficiary = payable(address(420));\n uint256 constant splitsDomain = 1;\n uint256 constant splitsGroup = 1;\n bool constant splitsPreferClaimedTokens = false;\n string constant splitsMemo = '';\n bytes constant splitsMetadata = '';\n bool constant splitsPreferAddToBalance = true;\n address constant splitsOwner = address(420);\n\n function testJBController() public {\n JBController controller = jbController();\n\n // Should support these interfaces\n assertTrue(controller.supportsInterface(type(IERC165).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBController).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBMigratable).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!controller.supportsInterface(notSupportedInterface));\n }\n\n function testJBERC20PaymentTerminal() public {\n JBERC20PaymentTerminal terminal = new JBERC20PaymentTerminal(\n jbToken(),\n jbLibraries().USD(), // currency\n jbLibraries().ETH(), // base weight currency\n 1, // JBSplitsGroupe\n jbOperatorStore(),\n jbProjects(),\n jbDirectory(),\n jbSplitsStore(),\n jbPrices(),\n jbPaymentTerminalStore(),\n multisig()\n );\n\n // Should support these interfaces\n assertTrue(terminal.supportsInterface(type(IERC165).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBRedemptionTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBSingleTokenPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!terminal.supportsInterface(notSupportedInterface));\n }\n\n function testJBETHPaymentTerminal() public {\n JBETHPaymentTerminal terminal = jbETHPaymentTerminal();\n\n // Should support these interfaces\n assertTrue(terminal.supportsInterface(type(IERC165).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBRedemptionTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBSingleTokenPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!terminal.supportsInterface(notSupportedInterface));\n }\n\n function testJBProjects() public {\n JBProjects projects = jbProjects();\n\n // Should support these interfaces\n assertTrue(projects.supportsInterface(type(IERC165).interfaceId));\n assertTrue(projects.supportsInterface(type(IERC721).interfaceId));\n assertTrue(projects.supportsInterface(type(IERC721Metadata).interfaceId));\n assertTrue(projects.supportsInterface(type(IJBProjects).interfaceId));\n assertTrue(projects.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!projects.supportsInterface(notSupportedInterface));\n }\n\n function testJBReconfigurationBufferBallot() public {\n JBReconfigurationBufferBallot ballot = new JBReconfigurationBufferBallot(\n 3000,\n jbFundingCycleStore()\n );\n\n // Should support these interfaces\n assertTrue(ballot.supportsInterface(type(IERC165).interfaceId));\n assertTrue(ballot.supportsInterface(type(IJBReconfigurationBufferBallot).interfaceId));\n assertTrue(ballot.supportsInterface(type(IJBFundingCycleBallot).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!ballot.supportsInterface(notSupportedInterface));\n }\n\n function testJBGasTokenERC20SplitsPayer() public {\n JBGasTokenERC20SplitsPayer splitsPayer = new JBGasTokenERC20SplitsPayer(\n splitsProjectID,\n splitsDomain,\n splitsGroup,\n jbSplitsStore(),\n projectId,\n splitsBeneficiary,\n splitsPreferClaimedTokens,\n splitsMemo,\n splitsMetadata,\n splitsPreferAddToBalance,\n splitsOwner\n );\n\n // Should support these interfaces\n assertTrue(splitsPayer.supportsInterface(type(IERC165).interfaceId));\n assertTrue(splitsPayer.supportsInterface(type(IJBSplitsPayer).interfaceId));\n assertTrue(splitsPayer.supportsInterface(type(IJBProjectPayer).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!splitsPayer.supportsInterface(notSupportedInterface));\n }\n}\n" }, - "contracts/JBETHERC20SplitsPayer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBSplitsPayer.sol';\nimport './interfaces/IJBSplitsStore.sol';\nimport './libraries/JBConstants.sol';\nimport './JBETHERC20ProjectPayer.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\n\n @dev\n Adheres to -\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBETHERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBETHERC20SplitsPayer is IJBSplitsPayer, JBETHERC20ProjectPayer, ReentrancyGuard {\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The ID of project for which the default splits are stored. \n */\n uint256 public override defaultSplitsProjectId;\n\n /**\n @notice\n The domain within which the default splits are stored. \n */\n uint256 public override defaultSplitsDomain;\n\n /**\n @notice\n The group within which the default splits are stored. \n */\n uint256 public override defaultSplitsGroup;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBETHERC20ProjectPayer, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n )\n JBETHERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _preferAddToBalance,\n _splitsStore.directory(),\n _owner\n )\n {\n defaultSplitsProjectId = _defaultSplitsProjectId;\n defaultSplitsDomain = _defaultSplitsDomain;\n defaultSplitsGroup = _defaultSplitsGroup;\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default split group using the stored default properties.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override nonReentrant {\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n JBTokens.ETH,\n address(this).balance,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender\n );\n\n // If there is no leftover amount, nothing left to pay.\n if (_leftoverAmount == 0) return;\n\n // If there's a default project ID, try to pay it.\n if (defaultProjectId != 0)\n if (defaultPreferAddToBalance)\n // Pay the project by adding to its balance if prefered.\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.ETH,\n _leftoverAmount,\n 18, // decimals.\n defaultMemo,\n defaultMetadata\n );\n // Otherwise, issue a payment to the project.\n else\n _pay(\n defaultProjectId,\n JBTokens.ETH,\n _leftoverAmount,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n 0, // min returned tokens.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n // If no project was specified, send the funds directly to the beneficiary or the msg.sender.\n else\n Address.sendValue(\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(msg.sender),\n _leftoverAmount\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the location of the splits that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n */\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) external virtual override onlyOwner {\n // Set the default splits project ID if it's changing.\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\n\n // Set the default splits domain if it's changing.\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\n\n // Set the default splits group if it's changing.\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\n\n emit SetDefaultSplits(_projectId, _domain, _group, msg.sender);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender\n );\n\n // Pay any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to pay it.\n if (_projectId != 0) {\n _pay(\n _projectId,\n _token,\n _leftoverAmount,\n _decimals,\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n // If no project was specified, send the funds directly to the beneficiary or the msg.sender.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _beneficiary != address(0) ? payable(_beneficiary) : payable(msg.sender),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).transfer(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _leftoverAmount\n );\n }\n }\n\n emit Pay(\n _projectId,\n _beneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event. \n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender\n );\n\n // Distribute any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to add to its balance.\n if (_projectId != 0)\n // Add to the project's balance.\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\n\n // Otherwise, send a payment to the beneficiary.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(msg.sender),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).transfer(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _leftoverAmount\n );\n }\n }\n\n emit AddToBalance(\n _projectId,\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splitsProjectId The ID of the project to which the splits belong.\n @param _splitsDomain The splits domain to which the group belongs.\n @param _splitsGroup The splits group to pay.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payToSplits(\n uint256 _splitsProjectId,\n uint256 _splitsDomain,\n uint256 _splitsGroup,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Get a reference to the splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup);\n\n // Set the leftover amount to the initial balance.\n leftoverAmount = _amount;\n\n // Settle between all splits.\n for (uint256 i = 0; i < _splits.length; i++) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[i];\n\n // The amount to send towards the split.\n uint256 _splitAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n if (_splitAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n _token,\n _splitAmount,\n _decimals,\n defaultProjectId,\n 0,\n _split\n );\n\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\n if (_token != JBTokens.ETH)\n IERC20(_token).approve(address(_split.allocator), _splitAmount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _splitAmount : 0;\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n if (_split.preferAddToBalance)\n _addToBalanceOf(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n 0,\n _split.preferClaimed,\n defaultMemo,\n defaultMetadata\n );\n } else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _split.beneficiary != address(0) ? _split.beneficiary : payable(_defaultBeneficiary),\n _splitAmount\n );\n // Or, transfer the ERC20.\n else {\n IERC20(_token).transfer(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n _splitAmount\n );\n }\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _splitAmount;\n }\n\n emit DistributeToSplit(\n _splitsProjectId,\n _splitsDomain,\n _splitsGroup,\n _split,\n _splitAmount,\n _defaultBeneficiary,\n msg.sender\n );\n }\n }\n}\n" + "contracts/JBGasTokenERC20SplitsPayer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBSplitsPayer.sol';\nimport './interfaces/IJBSplitsStore.sol';\nimport './libraries/JBConstants.sol';\nimport './JBGasTokenERC20ProjectPayer.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\n\n @dev\n Adheres to -\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBGasTokenERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBGasTokenERC20SplitsPayer is IJBSplitsPayer, JBGasTokenERC20ProjectPayer, ReentrancyGuard {\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The ID of project for which the default splits are stored. \n */\n uint256 public override defaultSplitsProjectId;\n\n /**\n @notice\n The domain within which the default splits are stored. \n */\n uint256 public override defaultSplitsDomain;\n\n /**\n @notice\n The group within which the default splits are stored. \n */\n uint256 public override defaultSplitsGroup;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBGasTokenERC20ProjectPayer, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n )\n JBGasTokenERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _preferAddToBalance,\n _splitsStore.directory(),\n _owner\n )\n {\n defaultSplitsProjectId = _defaultSplitsProjectId;\n defaultSplitsDomain = _defaultSplitsDomain;\n defaultSplitsGroup = _defaultSplitsGroup;\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default split group using the stored default properties.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override nonReentrant {\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender\n );\n\n // If there is no leftover amount, nothing left to pay.\n if (_leftoverAmount == 0) return;\n\n // If there's a default project ID, try to pay it.\n if (defaultProjectId != 0)\n if (defaultPreferAddToBalance)\n // Pay the project by adding to its balance if prefered.\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n _leftoverAmount,\n 18, // decimals.\n defaultMemo,\n defaultMetadata\n );\n // Otherwise, issue a payment to the project.\n else\n _pay(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n _leftoverAmount,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n 0, // min returned tokens.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n // If no project was specified, send the funds directly to the beneficiary or the msg.sender.\n else\n Address.sendValue(\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(msg.sender),\n _leftoverAmount\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the location of the splits that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n */\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) external virtual override onlyOwner {\n // Set the default splits project ID if it's changing.\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\n\n // Set the default splits domain if it's changing.\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\n\n // Set the default splits group if it's changing.\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\n\n emit SetDefaultSplits(_projectId, _domain, _group, msg.sender);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender\n );\n\n // Pay any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to pay it.\n if (_projectId != 0) {\n _pay(\n _projectId,\n _token,\n _leftoverAmount,\n _decimals,\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n // If no project was specified, send the funds directly to the beneficiary or the msg.sender.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _beneficiary != address(0) ? payable(_beneficiary) : payable(msg.sender),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).transfer(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _leftoverAmount\n );\n }\n }\n\n emit Pay(\n _projectId,\n _beneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event. \n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender\n );\n\n // Distribute any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to add to its balance.\n if (_projectId != 0)\n // Add to the project's balance.\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\n\n // Otherwise, send a payment to the beneficiary.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(msg.sender),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).transfer(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _leftoverAmount\n );\n }\n }\n\n emit AddToBalance(\n _projectId,\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splitsProjectId The ID of the project to which the splits belong.\n @param _splitsDomain The splits domain to which the group belongs.\n @param _splitsGroup The splits group to pay.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payToSplits(\n uint256 _splitsProjectId,\n uint256 _splitsDomain,\n uint256 _splitsGroup,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Get a reference to the splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup);\n\n // Set the leftover amount to the initial balance.\n leftoverAmount = _amount;\n\n // Settle between all splits.\n for (uint256 i = 0; i < _splits.length; i++) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[i];\n\n // The amount to send towards the split.\n uint256 _splitAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n if (_splitAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n _token,\n _splitAmount,\n _decimals,\n defaultProjectId,\n 0,\n _split\n );\n\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN)\n IERC20(_token).approve(address(_split.allocator), _splitAmount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _splitAmount : 0;\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n if (_split.preferAddToBalance)\n _addToBalanceOf(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n 0,\n _split.preferClaimed,\n defaultMemo,\n defaultMetadata\n );\n } else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _split.beneficiary != address(0) ? _split.beneficiary : payable(_defaultBeneficiary),\n _splitAmount\n );\n // Or, transfer the ERC20.\n else {\n IERC20(_token).transfer(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n _splitAmount\n );\n }\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _splitAmount;\n }\n\n emit DistributeToSplit(\n _splitsProjectId,\n _splitsDomain,\n _splitsGroup,\n _split,\n _splitAmount,\n _defaultBeneficiary,\n msg.sender\n );\n }\n }\n}\n" }, "contracts/interfaces/IJBSplitsPayer.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './../structs/JBSplit.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBSplitsPayer is IERC165 {\n event SetDefaultSplits(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n address caller\n );\n event Pay(\n uint256 indexed projectId,\n address beneficiary,\n address token,\n uint256 amount,\n uint256 decimals,\n uint256 leftoverAmount,\n uint256 minReturnedTokens,\n bool preferClaimedTokens,\n string memo,\n bytes metadata,\n address caller\n );\n\n event AddToBalance(\n uint256 indexed projectId,\n address beneficiary,\n address token,\n uint256 amount,\n uint256 decimals,\n uint256 leftoverAmount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DistributeToSplit(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n JBSplit split,\n uint256 amount,\n address defaultBeneficiary,\n address caller\n );\n\n function defaultSplitsProjectId() external view returns (uint256);\n\n function defaultSplitsDomain() external view returns (uint256);\n\n function defaultSplitsGroup() external view returns (uint256);\n\n function splitsStore() external view returns (IJBSplitsStore);\n\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) external;\n}\n" }, - "contracts/JBETHERC20ProjectPayer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport './interfaces/IJBProjectPayer.sol';\nimport './libraries/JBTokens.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ERC165: Introspection on interface adherance. \n*/\ncontract JBETHERC20ProjectPayer is IJBProjectPayer, Ownable, ERC165 {\n //*********************************************************************//\n // -------------------------- custom errors -------------------------- //\n //*********************************************************************//\n error INCORRECT_DECIMAL_AMOUNT();\n error NO_MSG_VALUE_ALLOWED();\n error TERMINAL_NOT_FOUND();\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice \n A contract storing directories of terminals and controllers for each project.\n */\n IJBDirectory public immutable override directory;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The ID of the project that should be used to forward this contract's received payments.\n */\n uint256 public override defaultProjectId;\n\n /** \n @notice \n The beneficiary that should be used in the payment made when this contract receives payments.\n */\n address payable public override defaultBeneficiary;\n\n /** \n @notice \n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\n */\n bool public override defaultPreferClaimedTokens;\n\n /** \n @notice \n The memo that should be used in the payment made when this contract receives payments.\n */\n string public override defaultMemo;\n\n /** \n @notice \n The metadata that should be used in the payment made when this contract receives payments.\n */\n bytes public override defaultMetadata;\n\n /**\n @notice \n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n bool public override defaultPreferAddToBalance;\n\n //*********************************************************************//\n // ------------------------- public views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) {\n defaultProjectId = _defaultProjectId;\n defaultBeneficiary = _defaultBeneficiary;\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\n defaultMemo = _defaultMemo;\n defaultMetadata = _defaultMetadata;\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n directory = _directory;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default project ID using the stored default properties.\n\n @dev\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override {\n if (defaultPreferAddToBalance)\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.ETH,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n defaultProjectId,\n JBTokens.ETH,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultBeneficiary == address(0) ? msg.sender : defaultBeneficiary,\n 0, // Can't determine expectation of returned tokens ahead of time.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\n\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _beneficiary The address that'll receive the project's tokens. \n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _memo The memo that'll be used. \n @param _metadata The metadata that'll be sent. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external virtual override onlyOwner {\n // Set the default project ID if it has changed.\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\n\n // Set the default beneficiary if it has changed.\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\n\n // Set the default claimed token preference if it has changed.\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\n defaultPreferClaimedTokens = _preferClaimedTokens;\n\n // Set the default memo if it has changed.\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\n defaultMemo = _memo;\n\n // Set the default metadata if it has changed.\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\n defaultMetadata = _metadata;\n\n // Set the add to balance preference if it has changed.\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n\n emit SetDefaultValues(\n _projectId,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata,\n _defaultPreferAddToBalance,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _pay(\n _projectId,\n _token,\n _amount,\n _decimals,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. \n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source and delegate, if provided.\n */\n function _pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.ETH) IERC20(_token).approve(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\n\n // Send funds to the terminal.\n // If the token is ETH, send it in msg.value.\n _terminal.pay{value: _payableValue}(\n _projectId,\n _amount, // ignored if the token is JBTokens.ETH.\n _token,\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.ETH) IERC20(_token).approve(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\n\n // Add to balance so tokens don't get issued.\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\n }\n}\n" + "contracts/JBGasTokenERC20ProjectPayer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport './interfaces/IJBProjectPayer.sol';\nimport './libraries/JBTokens.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ERC165: Introspection on interface adherance. \n*/\ncontract JBGasTokenERC20ProjectPayer is IJBProjectPayer, Ownable, ERC165 {\n //*********************************************************************//\n // -------------------------- custom errors -------------------------- //\n //*********************************************************************//\n error INCORRECT_DECIMAL_AMOUNT();\n error NO_MSG_VALUE_ALLOWED();\n error TERMINAL_NOT_FOUND();\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice \n A contract storing directories of terminals and controllers for each project.\n */\n IJBDirectory public immutable override directory;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The ID of the project that should be used to forward this contract's received payments.\n */\n uint256 public override defaultProjectId;\n\n /** \n @notice \n The beneficiary that should be used in the payment made when this contract receives payments.\n */\n address payable public override defaultBeneficiary;\n\n /** \n @notice \n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\n */\n bool public override defaultPreferClaimedTokens;\n\n /** \n @notice \n The memo that should be used in the payment made when this contract receives payments.\n */\n string public override defaultMemo;\n\n /** \n @notice \n The metadata that should be used in the payment made when this contract receives payments.\n */\n bytes public override defaultMetadata;\n\n /**\n @notice \n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n bool public override defaultPreferAddToBalance;\n\n //*********************************************************************//\n // ------------------------- public views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) {\n defaultProjectId = _defaultProjectId;\n defaultBeneficiary = _defaultBeneficiary;\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\n defaultMemo = _defaultMemo;\n defaultMetadata = _defaultMetadata;\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n directory = _directory;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default project ID using the stored default properties.\n\n @dev\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override {\n if (defaultPreferAddToBalance)\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultBeneficiary == address(0) ? msg.sender : defaultBeneficiary,\n 0, // Can't determine expectation of returned tokens ahead of time.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\n\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _beneficiary The address that'll receive the project's tokens. \n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _memo The memo that'll be used. \n @param _metadata The metadata that'll be sent. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external virtual override onlyOwner {\n // Set the default project ID if it has changed.\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\n\n // Set the default beneficiary if it has changed.\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\n\n // Set the default claimed token preference if it has changed.\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\n defaultPreferClaimedTokens = _preferClaimedTokens;\n\n // Set the default memo if it has changed.\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\n defaultMemo = _memo;\n\n // Set the default metadata if it has changed.\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\n defaultMetadata = _metadata;\n\n // Set the add to balance preference if it has changed.\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n\n emit SetDefaultValues(\n _projectId,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata,\n _defaultPreferAddToBalance,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _pay(\n _projectId,\n _token,\n _amount,\n _decimals,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. \n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source and delegate, if provided.\n */\n function _pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).approve(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send funds to the terminal.\n // If the token is ETH, send it in msg.value.\n _terminal.pay{value: _payableValue}(\n _projectId,\n _amount, // ignored if the token is JBTokens.GAS_TOKEN.\n _token,\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).approve(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Add to balance so tokens don't get issued.\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\n }\n}\n" }, "contracts/interfaces/IJBProjectPayer.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './IJBDirectory.sol';\n\ninterface IJBProjectPayer is IERC165 {\n event SetDefaultValues(\n uint256 indexed projectId,\n address indexed beneficiary,\n bool preferClaimedTokens,\n string memo,\n bytes metadata,\n bool preferAddToBalance,\n address caller\n );\n\n function directory() external view returns (IJBDirectory);\n\n function defaultProjectId() external view returns (uint256);\n\n function defaultBeneficiary() external view returns (address payable);\n\n function defaultPreferClaimedTokens() external view returns (bool);\n\n function defaultMemo() external view returns (string memory);\n\n function defaultMetadata() external view returns (bytes memory);\n\n function defaultPreferAddToBalance() external view returns (bool);\n\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external;\n\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) external payable;\n\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) external payable;\n\n receive() external payable;\n}\n" }, - "contracts/JBETHERC20SplitsPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './interfaces/IJBETHERC20SplitsPayerDeployer.sol';\nimport './JBETHERC20SplitsPayer.sol';\n\n/** \n @notice \n Deploys splits payer contracts.\n\n @dev\n Adheres to -\n IJBETHERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBETHERC20SplitsPayerDeployer is IJBETHERC20SplitsPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBSplitsPayer splitsPayer) {\n // Deploy the splits payer.\n splitsPayer = new JBETHERC20SplitsPayer(\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeploySplitsPayer(\n splitsPayer,\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner,\n msg.sender\n );\n }\n}\n" + "contracts/JBGasTokenERC20SplitsPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './interfaces/IJBGasTokenERC20SplitsPayerDeployer.sol';\nimport './JBGasTokenERC20SplitsPayer.sol';\n\n/** \n @notice \n Deploys splits payer contracts.\n\n @dev\n Adheres to -\n IJBGasTokenERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBGasTokenERC20SplitsPayerDeployer is IJBGasTokenERC20SplitsPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBSplitsPayer splitsPayer) {\n // Deploy the splits payer.\n splitsPayer = new JBGasTokenERC20SplitsPayer(\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeploySplitsPayer(\n splitsPayer,\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner,\n msg.sender\n );\n }\n}\n" }, - "contracts/interfaces/IJBETHERC20SplitsPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './IJBSplitsPayer.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBETHERC20SplitsPayerDeployer {\n event DeploySplitsPayer(\n IJBSplitsPayer indexed splitsPayer,\n uint256 defaultSplitsProjectId,\n uint256 defaultSplitsDomain,\n uint256 defaultSplitsGroup,\n IJBSplitsStore splitsStore,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n address owner,\n address caller\n );\n\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string calldata _defaultMemo,\n bytes calldata _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n}\n" + "contracts/interfaces/IJBGasTokenERC20SplitsPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './IJBSplitsPayer.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBGasTokenERC20SplitsPayerDeployer {\n event DeploySplitsPayer(\n IJBSplitsPayer indexed splitsPayer,\n uint256 defaultSplitsProjectId,\n uint256 defaultSplitsDomain,\n uint256 defaultSplitsGroup,\n IJBSplitsStore splitsStore,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n address owner,\n address caller\n );\n\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string calldata _defaultMemo,\n bytes calldata _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n}\n" }, - "contracts/JBETHERC20ProjectPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './interfaces/IJBETHERC20ProjectPayerDeployer.sol';\nimport './JBETHERC20ProjectPayer.sol';\n\n/** \n @notice \n Deploys project payer contracts.\n\n @dev\n Adheres to -\n IJBETHERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBETHERC20ProjectPayerDeployer is IJBETHERC20ProjectPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new project payer contract.\n\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the project payer contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the project payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the project payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the project payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the project payer.\n\n @return projectPayer The project payer contract.\n */\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external override returns (IJBProjectPayer projectPayer) {\n // Deploy the project payer.\n projectPayer = new JBETHERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner\n );\n\n emit DeployProjectPayer(\n projectPayer,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner,\n msg.sender\n );\n }\n}\n" + "contracts/JBGasTokenERC20ProjectPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './interfaces/IJBGasTokenERC20ProjectPayerDeployer.sol';\nimport './JBGasTokenERC20ProjectPayer.sol';\n\n/** \n @notice \n Deploys project payer contracts.\n\n @dev\n Adheres to -\n IJBGasTokenERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBGasTokenERC20ProjectPayerDeployer is IJBGasTokenERC20ProjectPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new project payer contract.\n\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the project payer contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the project payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the project payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the project payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the project payer.\n\n @return projectPayer The project payer contract.\n */\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external override returns (IJBProjectPayer projectPayer) {\n // Deploy the project payer.\n projectPayer = new JBGasTokenERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner\n );\n\n emit DeployProjectPayer(\n projectPayer,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner,\n msg.sender\n );\n }\n}\n" }, - "contracts/interfaces/IJBETHERC20ProjectPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './IJBDirectory.sol';\nimport './IJBProjectPayer.sol';\n\ninterface IJBETHERC20ProjectPayerDeployer {\n event DeployProjectPayer(\n IJBProjectPayer indexed projectPayer,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n IJBDirectory directory,\n address owner,\n address caller\n );\n\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external returns (IJBProjectPayer projectPayer);\n}\n" + "contracts/interfaces/IJBGasTokenERC20ProjectPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './IJBDirectory.sol';\nimport './IJBProjectPayer.sol';\n\ninterface IJBGasTokenERC20ProjectPayerDeployer {\n event DeployProjectPayer(\n IJBProjectPayer indexed projectPayer,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n IJBDirectory directory,\n address owner,\n address caller\n );\n\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external returns (IJBProjectPayer projectPayer);\n}\n" }, "contracts/system_tests/TestPayBurnRedeemFlow.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport '@paulrberg/contracts/math/PRBMathUD60x18.sol';\n\nimport './helpers/TestBaseWorkflow.sol';\n\n/**\n * This system test file verifies the following flow:\n * launch project → issue token → pay project (claimed tokens) → burn some of the claimed tokens → redeem rest of tokens\n */\ncontract TestPayBurnRedeemFlow is TestBaseWorkflow {\n JBController private _controller;\n JBETHPaymentTerminal private _terminal;\n JBTokenStore private _tokenStore;\n\n JBProjectMetadata private _projectMetadata;\n JBFundingCycleData private _data;\n JBFundingCycleMetadata private _metadata;\n JBGroupedSplits[] private _groupedSplits; // Default empty\n JBFundAccessConstraints[] private _fundAccessConstraints; // Default empty\n IJBPaymentTerminal[] private _terminals; // Default empty\n\n uint256 private _projectId;\n address private _projectOwner;\n uint256 private _weight = 1000 * 10**18;\n uint256 private _targetInWei = 10 * 10**18;\n\n function setUp() public override {\n super.setUp();\n\n _controller = jbController();\n _terminal = jbETHPaymentTerminal();\n _tokenStore = jbTokenStore();\n\n _projectMetadata = JBProjectMetadata({content: 'myIPFSHash', domain: 1});\n\n _data = JBFundingCycleData({\n duration: 14,\n weight: _weight,\n discountRate: 450000000,\n ballot: IJBFundingCycleBallot(address(0))\n });\n\n _metadata = JBFundingCycleMetadata({\n global: JBGlobalFundingCycleMetadata({allowSetTerminals: false, allowSetController: false}),\n reservedRate: 0,\n redemptionRate: 10000, //100%\n ballotRedemptionRate: 0,\n pausePay: false,\n pauseDistributions: false,\n pauseRedeem: false,\n pauseBurn: false,\n allowMinting: false,\n allowChangeToken: false,\n allowTerminalMigration: false,\n allowControllerMigration: false,\n holdFees: false,\n useTotalOverflowForRedemptions: false,\n useDataSourceForPay: false,\n useDataSourceForRedeem: false,\n dataSource: address(0)\n });\n\n _terminals.push(_terminal);\n\n _fundAccessConstraints.push(\n JBFundAccessConstraints({\n terminal: _terminal,\n token: jbLibraries().ETHToken(),\n distributionLimit: _targetInWei, // 10 ETH target\n overflowAllowance: 5 ether,\n distributionLimitCurrency: 1, // Currency = ETH\n overflowAllowanceCurrency: 1\n })\n );\n\n _projectOwner = multisig();\n\n _projectId = _controller.launchProjectFor(\n _projectOwner,\n _projectMetadata,\n _data,\n _metadata,\n block.timestamp,\n _groupedSplits,\n _fundAccessConstraints,\n _terminals,\n ''\n );\n }\n\n function testFuzzPayBurnRedeemFlow(\n bool payPreferClaimed, //false\n bool burnPreferClaimed, //false\n uint96 payAmountInWei, // 1\n uint256 burnTokenAmount, // 0\n uint256 redeemTokenAmount // 0\n ) external {\n // issue an ERC-20 token for project\n evm.prank(_projectOwner);\n _controller.issueTokenFor(_projectId, 'TestName', 'TestSymbol');\n\n address _userWallet = address(1234);\n\n // pay terminal\n _terminal.pay{value: payAmountInWei}(\n _projectId,\n payAmountInWei,\n address(0),\n _userWallet,\n /* _minReturnedTokens */\n 0,\n /* _preferClaimedTokens */\n payPreferClaimed,\n /* _memo */\n 'Take my money!',\n /* _delegateMetadata */\n new bytes(0)\n );\n\n // verify: beneficiary should have a balance of JBTokens\n uint256 _userTokenBalance = PRBMathUD60x18.mul(payAmountInWei, _weight);\n assertEq(_tokenStore.balanceOf(_userWallet, _projectId), _userTokenBalance);\n\n // verify: ETH balance in terminal should be up to date\n uint256 _terminalBalanceInWei = payAmountInWei;\n assertEq(jbPaymentTerminalStore().balanceOf(_terminal, _projectId), _terminalBalanceInWei);\n\n // burn tokens from beneficiary addr\n if (burnTokenAmount == 0) evm.expectRevert(abi.encodeWithSignature('NO_BURNABLE_TOKENS()'));\n else if (burnTokenAmount > _userTokenBalance)\n evm.expectRevert(abi.encodeWithSignature('INSUFFICIENT_FUNDS()'));\n else if (burnTokenAmount > uint256(type(int256).max))\n evm.expectRevert(abi.encodeWithSignature('Panic(uint256)', 0x11));\n else _userTokenBalance = _userTokenBalance - burnTokenAmount;\n\n evm.prank(_userWallet);\n _controller.burnTokensOf(\n _userWallet,\n _projectId,\n /* _tokenCount */\n burnTokenAmount,\n /* _memo */\n 'I hate tokens!',\n /* _preferClaimedTokens */\n burnPreferClaimed\n );\n\n // verify: beneficiary should have a new balance of JBTokens\n assertEq(_tokenStore.balanceOf(_userWallet, _projectId), _userTokenBalance);\n\n // redeem tokens\n if (redeemTokenAmount > _userTokenBalance)\n evm.expectRevert(abi.encodeWithSignature('INSUFFICIENT_TOKENS()'));\n else _userTokenBalance = _userTokenBalance - redeemTokenAmount;\n\n evm.prank(_userWallet);\n uint256 _reclaimAmtInWei = _terminal.redeemTokensOf(\n /* _holder */\n _userWallet,\n /* _projectId */\n _projectId,\n /* _tokenCount */\n redeemTokenAmount,\n /* token (unused) */\n address(0),\n /* _minReturnedWei */\n 0,\n /* _beneficiary */\n payable(_userWallet),\n /* _memo */\n 'Refund me now!',\n /* _delegateMetadata */\n new bytes(0)\n );\n\n // verify: beneficiary should have a new balance of JBTokens\n assertEq(_tokenStore.balanceOf(_userWallet, _projectId), _userTokenBalance);\n\n // verify: ETH balance in terminal should be up to date\n assertEq(\n jbPaymentTerminalStore().balanceOf(_terminal, _projectId),\n _terminalBalanceInWei - _reclaimAmtInWei\n );\n }\n}\n" diff --git a/deployments/mainnet/solcInputs/2558f6dc599ebc1f13c79797e151bc24.json b/deployments/mainnet/solcInputs/2558f6dc599ebc1f13c79797e151bc24.json index 86e4d44e0..837126a10 100644 --- a/deployments/mainnet/solcInputs/2558f6dc599ebc1f13c79797e151bc24.json +++ b/deployments/mainnet/solcInputs/2558f6dc599ebc1f13c79797e151bc24.json @@ -164,7 +164,7 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './JBSplit.sol';\n\n/** \n @member token The token being sent to the split allocator.\n @member amount The amount being sent to the split allocator, as a fixed point number.\n @member decimals The number of decimals in the amount.\n @member projectId The project to which the split belongs.\n @member group The group to which the split belongs.\n @member split The split that caused the allocation.\n*/\nstruct JBSplitAllocationData {\n address token;\n uint256 amount;\n uint256 decimals;\n uint256 projectId;\n uint256 group;\n JBSplit split;\n}\n" }, "contracts/JBSingleTokenPaymentTerminalStore.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBSingleTokenPaymentTerminalStore is IJBSingleTokenPaymentTerminalStore, ReentrancyGuard {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegate A delegate contract to use for subsequent calls.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n IJBPayDelegate delegate,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay()) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegate) = IJBFundingCycleDataSource(fundingCycle.dataSource()).payParams(\n _data\n );\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegate, memo);\n\n // Add the amount to the token balance of the project.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount.value;\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegate, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegate A delegate contract to use for subsequent calls.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n IJBRedemptionDelegate delegate,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\n _projectId,\n fundingCycle.reservedRate()\n );\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow > 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem()) {\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n fundingCycle.redemptionRate(),\n fundingCycle.ballotRedemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegate) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .redeemParams(_data);\n } else {\n memo = _memo;\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (reclaimAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (reclaimAmount > 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n reclaimAmount;\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n return _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i = 0; _i < _terminals.length; _i++)\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.ETH\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.ETH, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBSingleTokenPaymentTerminalStore is IJBSingleTokenPaymentTerminalStore, ReentrancyGuard {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegate A delegate contract to use for subsequent calls.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n IJBPayDelegate delegate,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay()) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegate) = IJBFundingCycleDataSource(fundingCycle.dataSource()).payParams(\n _data\n );\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegate, memo);\n\n // Add the amount to the token balance of the project.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount.value;\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegate, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegate A delegate contract to use for subsequent calls.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n IJBRedemptionDelegate delegate,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\n _projectId,\n fundingCycle.reservedRate()\n );\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow > 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem()) {\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n fundingCycle.redemptionRate(),\n fundingCycle.ballotRedemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegate) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .redeemParams(_data);\n } else {\n memo = _memo;\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (reclaimAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (reclaimAmount > 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n reclaimAmount;\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n return _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i = 0; _i < _terminals.length; _i++)\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.GAS_CURRENCY\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.GAS_CURRENCY, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" }, "@openzeppelin/contracts/security/ReentrancyGuard.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n constructor() {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n // On the first call to nonReentrant, _notEntered will be true\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n\n _;\n\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n}\n" @@ -245,7 +245,7 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nlibrary JBSplitsGroups {\n uint256 public constant ETH_PAYOUT = 1;\n uint256 public constant RESERVED_TOKENS = 2;\n}\n" }, "contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBSplitsGroups.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal is\n IJBPayoutRedemptionPaymentTerminal,\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The protocol project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _PROTOCOL_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n @dev\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds set outside the ecosystem may incur fees despite being stored as feeless.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.ETH)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.ETH, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance.\n */\n function _balance() internal view virtual returns (uint256);\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.ETH) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i = 0; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual {\n _from; // Prevents unused var compiler and natspec complaints.\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegate` only used within scope.\n {\n IJBRedemptionDelegate _delegate;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegate, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If a delegate was returned by the data source, issue a callback to it.\n if (_delegate != IJBRedemptionDelegate(address(0))) {\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _beneficiary,\n _memo,\n _metadata\n );\n _delegate.didRedeem(_data);\n emit DelegateDidRedeem(_delegate, _data, msg.sender);\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n }\n\n // Take the fee.\n _fee = _feeEligibleDistributionAmount == 0\n ? 0\n : _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n );\n\n // Transfer any remaining balance to the project owner.\n if (netLeftoverDistributionAmount > 0)\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i = 0; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount;\n\n if (_payoutAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\n isFeelessAddress[address(_split.allocator)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _netPayoutAmount : 0;\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n _netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // Save gas if this contract is being used as the terminal.\n if (_terminal == this) {\n // This distribution does not incur a fee.\n _netPayoutAmount = _payoutAmount;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\n else\n _pay(\n _netPayoutAmount,\n address(this),\n _split.projectId,\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n } else {\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_terminal)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _netPayoutAmount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _terminal.addToBalanceOf{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n '',\n _projectMetadata\n );\n else\n _terminal.pay{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n }\n } else {\n // Keep a reference to the beneficiary.\n address payable _beneficiary = _split.beneficiary != address(0)\n ? _split.beneficiary\n : payable(msg.sender);\n\n // If there's a full discount, this distribution is not eligible for a fee.\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(address(this), _beneficiary, _netPayoutAmount);\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _PROTOCOL_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n */\n function _processFee(uint256 _amount, address _beneficiary) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_PROTOCOL_PROJECT_ID, token);\n\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\n if (_terminal == this)\n _pay(_amount, address(this), _PROTOCOL_PROJECT_ID, _beneficiary, 0, false, '', bytes('')); // Use the local pay call.\n else {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _amount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _amount : 0;\n\n // Send the payment.\n _terminal.pay{value: _payableValue}(\n _PROTOCOL_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the external pay call of the correct terminal.\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegate` and `_tokenCount` only used within scope.\n {\n IJBPayDelegate _delegate;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegate, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If a delegate was returned by the data source, issue a callback to it.\n if (_delegate != IJBPayDelegate(address(0))) {\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n _delegate.didPay(_data);\n emit DelegateDidPay(_delegate, _data, msg.sender);\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i = 0; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n unchecked {\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256 feeDiscount) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (directory.primaryTerminalOf(_PROTOCOL_PROJECT_ID, token) == IJBPaymentTerminal(address(0)))\n return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge == IJBFeeGauge(address(0)))\n feeDiscount = 0;\n // If the guage reverts, set the discount to 0.\n else\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n feeDiscount = discount;\n } catch {\n feeDiscount = 0;\n }\n\n // If the fee discount is greater than the max, nullify the discount.\n if (feeDiscount > JBConstants.MAX_FEE_DISCOUNT) feeDiscount = 0;\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBSplitsGroups.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal is\n IJBPayoutRedemptionPaymentTerminal,\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The protocol project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _PROTOCOL_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n @dev\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds set outside the ecosystem may incur fees despite being stored as feeless.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.GAS_CURRENCY)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.GAS_CURRENCY, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance.\n */\n function _balance() internal view virtual returns (uint256);\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.GAS_TOKEN) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i = 0; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual {\n _from; // Prevents unused var compiler and natspec complaints.\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegate` only used within scope.\n {\n IJBRedemptionDelegate _delegate;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegate, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If a delegate was returned by the data source, issue a callback to it.\n if (_delegate != IJBRedemptionDelegate(address(0))) {\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _beneficiary,\n _memo,\n _metadata\n );\n _delegate.didRedeem(_data);\n emit DelegateDidRedeem(_delegate, _data, msg.sender);\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n }\n\n // Take the fee.\n _fee = _feeEligibleDistributionAmount == 0\n ? 0\n : _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n );\n\n // Transfer any remaining balance to the project owner.\n if (netLeftoverDistributionAmount > 0)\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i = 0; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount;\n\n if (_payoutAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\n isFeelessAddress[address(_split.allocator)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0;\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n _netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // Save gas if this contract is being used as the terminal.\n if (_terminal == this) {\n // This distribution does not incur a fee.\n _netPayoutAmount = _payoutAmount;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\n else\n _pay(\n _netPayoutAmount,\n address(this),\n _split.projectId,\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n } else {\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_terminal)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _terminal.addToBalanceOf{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n '',\n _projectMetadata\n );\n else\n _terminal.pay{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n }\n } else {\n // Keep a reference to the beneficiary.\n address payable _beneficiary = _split.beneficiary != address(0)\n ? _split.beneficiary\n : payable(msg.sender);\n\n // If there's a full discount, this distribution is not eligible for a fee.\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(address(this), _beneficiary, _netPayoutAmount);\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _PROTOCOL_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n */\n function _processFee(uint256 _amount, address _beneficiary) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_PROTOCOL_PROJECT_ID, token);\n\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\n if (_terminal == this)\n _pay(_amount, address(this), _PROTOCOL_PROJECT_ID, _beneficiary, 0, false, '', bytes('')); // Use the local pay call.\n else {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _amount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send the payment.\n _terminal.pay{value: _payableValue}(\n _PROTOCOL_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the external pay call of the correct terminal.\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegate` and `_tokenCount` only used within scope.\n {\n IJBPayDelegate _delegate;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegate, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If a delegate was returned by the data source, issue a callback to it.\n if (_delegate != IJBPayDelegate(address(0))) {\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n _delegate.didPay(_data);\n emit DelegateDidPay(_delegate, _data, msg.sender);\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i = 0; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n unchecked {\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256 feeDiscount) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (directory.primaryTerminalOf(_PROTOCOL_PROJECT_ID, token) == IJBPaymentTerminal(address(0)))\n return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge == IJBFeeGauge(address(0)))\n feeDiscount = 0;\n // If the guage reverts, set the discount to 0.\n else\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n feeDiscount = discount;\n } catch {\n feeDiscount = 0;\n }\n\n // If the fee discount is greater than the max, nullify the discount.\n if (feeDiscount > JBConstants.MAX_FEE_DISCOUNT) feeDiscount = 0;\n }\n}\n" }, "contracts/interfaces/IJBPayoutRedemptionPaymentTerminal.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\nimport './../structs/JBFee.sol';\nimport './IJBAllowanceTerminal.sol';\nimport './IJBDirectory.sol';\nimport './IJBFeeGauge.sol';\nimport './IJBPayDelegate.sol';\nimport './IJBPaymentTerminal.sol';\nimport './IJBPayoutTerminal.sol';\nimport './IJBPrices.sol';\nimport './IJBProjects.sol';\nimport './IJBRedemptionDelegate.sol';\nimport './IJBRedemptionTerminal.sol';\nimport './IJBSingleTokenPaymentTerminal.sol';\nimport './IJBSingleTokenPaymentTerminalStore.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBPayoutRedemptionPaymentTerminal is\n IJBPaymentTerminal,\n IJBPayoutTerminal,\n IJBAllowanceTerminal,\n IJBRedemptionTerminal\n{\n event AddToBalance(\n uint256 indexed projectId,\n uint256 amount,\n uint256 refundedFees,\n string memo,\n bytes metadata,\n address caller\n );\n\n event Migrate(\n uint256 indexed projectId,\n IJBPaymentTerminal indexed to,\n uint256 amount,\n address caller\n );\n\n event DistributePayouts(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address beneficiary,\n uint256 amount,\n uint256 distributedAmount,\n uint256 fee,\n uint256 beneficiaryDistributionAmount,\n string memo,\n address caller\n );\n\n event UseAllowance(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address beneficiary,\n uint256 amount,\n uint256 distributedAmount,\n uint256 netDistributedamount,\n string memo,\n address caller\n );\n\n event HoldFee(\n uint256 indexed projectId,\n uint256 indexed amount,\n uint256 indexed fee,\n uint256 feeDiscount,\n address beneficiary,\n address caller\n );\n\n event ProcessFee(\n uint256 indexed projectId,\n uint256 indexed amount,\n bool indexed wasHeld,\n address beneficiary,\n address caller\n );\n\n event RefundHeldFees(\n uint256 indexed projectId,\n uint256 indexed amount,\n uint256 indexed refundedFees,\n uint256 leftoverAmount,\n address caller\n );\n\n event Pay(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address payer,\n address beneficiary,\n uint256 amount,\n uint256 beneficiaryTokenCount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DelegateDidPay(IJBPayDelegate indexed delegate, JBDidPayData data, address caller);\n\n event RedeemTokens(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address holder,\n address beneficiary,\n uint256 tokenCount,\n uint256 reclaimedAmount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DelegateDidRedeem(\n IJBRedemptionDelegate indexed delegate,\n JBDidRedeemData data,\n address caller\n );\n\n event DistributeToPayoutSplit(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n JBSplit split,\n uint256 amount,\n address caller\n );\n\n event SetFee(uint256 fee, address caller);\n\n event SetFeeGauge(IJBFeeGauge indexed feeGauge, address caller);\n\n event SetFeelessAddress(address indexed addrs, bool indexed flag, address caller);\n\n function projects() external view returns (IJBProjects);\n\n function splitsStore() external view returns (IJBSplitsStore);\n\n function directory() external view returns (IJBDirectory);\n\n function prices() external view returns (IJBPrices);\n\n function store() external view returns (IJBSingleTokenPaymentTerminalStore);\n\n function baseWeightCurrency() external view returns (uint256);\n\n function payoutSplitsGroup() external view returns (uint256);\n\n function heldFeesOf(uint256 _projectId) external view returns (JBFee[] memory);\n\n function fee() external view returns (uint256);\n\n function feeGauge() external view returns (IJBFeeGauge);\n\n function isFeelessAddress(address _contract) external view returns (bool);\n\n function migrate(uint256 _projectId, IJBPaymentTerminal _to) external returns (uint256 balance);\n\n function processFees(uint256 _projectId) external;\n\n function setFee(uint256 _fee) external;\n\n function setFeeGauge(IJBFeeGauge _feeGauge) external;\n\n function setFeelessAddress(address _contract, bool _flag) external;\n}\n" @@ -272,7 +272,7 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\ninterface IJBRedemptionTerminal {\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string calldata _memo,\n bytes calldata _metadata\n ) external returns (uint256 reclaimAmount);\n}\n" }, "contracts/JBETHPaymentTerminal.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance.\n */\n function _balance() internal view override returns (uint256) {\n return address(this).balance;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n JBTokens.ETH,\n 18, // 18 decimals.\n JBCurrencies.ETH,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance.\n */\n function _balance() internal view override returns (uint256) {\n return address(this).balance;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n JBTokens.GAS_TOKEN,\n 18, // 18 decimals.\n JBCurrencies.GAS_CURRENCY,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n}\n" }, "contracts/JBReconfigurationBufferBallot.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport './interfaces/IJBReconfigurationBufferBallot.sol';\nimport './structs/JBFundingCycle.sol';\n\n/** \n @notice \n Manages approving funding cycle reconfigurations automatically after a buffer period.\n\n @dev\n Adheres to -\n IJBReconfigurationBufferBallot: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ERC165: Introspection on interface adherance. \n*/\ncontract JBReconfigurationBufferBallot is IJBReconfigurationBufferBallot, ERC165 {\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice \n The number of seconds that must pass for a funding cycle reconfiguration to become either `Approved` or `Failed`.\n */\n uint256 public immutable override duration;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice \n The finalized state.\n\n @dev\n If `Active`, the ballot for the provided configuration can still be finalized whenever its state settles.\n\n _projectId The ID of the project to check the final ballot state of.\n _configuration The configuration of the funding cycle to check the final ballot state of.\n */\n mapping(uint256 => mapping(uint256 => JBBallotState)) public override finalState;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice \n The approval state of a particular funding cycle.\n\n @param _projectId The ID of the project to which the funding cycle being checked belongs.\n @param _configured The configuration of the funding cycle to check the state of.\n @param _start The start timestamp of the funding cycle to check the state of.\n\n @return The state of the provided ballot.\n */\n function stateOf(\n uint256 _projectId,\n uint256 _configured,\n uint256 _start\n ) public view override returns (JBBallotState) {\n // If there is a finalized state, return it.\n if (finalState[_projectId][_configured] != JBBallotState.Active)\n return finalState[_projectId][_configured];\n\n // If the delay hasn't yet passed, the ballot is either failed or active.\n if (block.timestamp < _configured + duration)\n // If the current timestamp is past the start, the ballot is failed.\n return (block.timestamp >= _start) ? JBBallotState.Failed : JBBallotState.Active;\n\n // The ballot is otherwise approved.\n return JBBallotState.Approved;\n }\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBReconfigurationBufferBallot).interfaceId ||\n _interfaceId == type(IJBFundingCycleBallot).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _duration The number of seconds to wait until a reconfiguration can be either `Approved` or `Failed`.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n */\n constructor(uint256 _duration, IJBFundingCycleStore _fundingCycleStore) {\n duration = _duration;\n fundingCycleStore = _fundingCycleStore;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice \n Finalizes a configuration state if the current state has settled.\n\n @param _projectId The ID of the project to which the funding cycle being checked belongs.\n @param _configured The configuration of the funding cycle to check the state of.\n\n @return ballotState The state of the finalized ballot. If `Active`, the ballot can still later be finalized when it's state resolves.\n */\n function finalize(uint256 _projectId, uint256 _configured)\n external\n override\n returns (JBBallotState ballotState)\n {\n // Get the funding cycle for the configuration in question.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.get(_projectId, _configured);\n\n // Get the current ballot state.\n ballotState = finalState[_projectId][_configured];\n\n // If the final ballot state is still `Active`.\n if (ballotState == JBBallotState.Active) {\n ballotState = stateOf(_projectId, _configured, _fundingCycle.start);\n // If the ballot is active after the cycle has started, it should be finalized as failed.\n if (ballotState != JBBallotState.Active) {\n // Store the updated value.\n finalState[_projectId][_configured] = ballotState;\n\n emit Finalize(_projectId, _configured, ballotState, msg.sender);\n }\n }\n }\n}\n" @@ -280,8 +280,8 @@ "contracts/interfaces/IJBReconfigurationBufferBallot.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './IJBFundingCycleBallot.sol';\n\ninterface IJBReconfigurationBufferBallot is IJBFundingCycleBallot {\n event Finalize(\n uint256 indexed projectId,\n uint256 indexed configuration,\n JBBallotState indexed ballotState,\n address caller\n );\n\n function finalState(uint256 _projectId, uint256 _configuration)\n external\n view\n returns (JBBallotState);\n\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\n\n function finalize(uint256 _projectId, uint256 _configured) external returns (JBBallotState);\n}\n" }, - "contracts/JBETHERC20SplitsPayer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBSplitsPayer.sol';\nimport './interfaces/IJBSplitsStore.sol';\nimport './libraries/JBConstants.sol';\nimport './JBETHERC20ProjectPayer.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\n\n @dev\n Adheres to -\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBETHERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBETHERC20SplitsPayer is IJBSplitsPayer, JBETHERC20ProjectPayer, ReentrancyGuard {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The ID of project for which the default splits are stored. \n */\n uint256 public override defaultSplitsProjectId;\n\n /**\n @notice\n The domain within which the default splits are stored. \n */\n uint256 public override defaultSplitsDomain;\n\n /**\n @notice\n The group within which the default splits are stored. \n */\n uint256 public override defaultSplitsGroup;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBETHERC20ProjectPayer, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n )\n JBETHERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _preferAddToBalance,\n _splitsStore.directory(),\n _owner\n )\n {\n defaultSplitsProjectId = _defaultSplitsProjectId;\n defaultSplitsDomain = _defaultSplitsDomain;\n defaultSplitsGroup = _defaultSplitsGroup;\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default split group using the stored default properties.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override nonReentrant {\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n JBTokens.ETH,\n address(this).balance,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender\n );\n\n // If there is no leftover amount, nothing left to pay.\n if (_leftoverAmount == 0) return;\n\n // If there's a default project ID, try to pay it.\n if (defaultProjectId != 0)\n if (defaultPreferAddToBalance)\n // Pay the project by adding to its balance if prefered.\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.ETH,\n _leftoverAmount,\n 18, // decimals.\n defaultMemo,\n defaultMetadata\n );\n // Otherwise, issue a payment to the project.\n else\n _pay(\n defaultProjectId,\n JBTokens.ETH,\n _leftoverAmount,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n 0, // min returned tokens.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n // If no project was specified, send the funds directly to the beneficiary or the msg.sender.\n else\n Address.sendValue(\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(msg.sender),\n _leftoverAmount\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the location of the splits that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n */\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) external virtual override onlyOwner {\n // Set the default splits project ID if it's changing.\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\n\n // Set the default splits domain if it's changing.\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\n\n // Set the default splits group if it's changing.\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\n\n emit SetDefaultSplits(_projectId, _domain, _group, msg.sender);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender\n );\n\n // Pay any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to pay it.\n if (_projectId != 0) {\n _pay(\n _projectId,\n _token,\n _leftoverAmount,\n _decimals,\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n // If no project was specified, send the funds directly to the beneficiary or the msg.sender.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _beneficiary != address(0) ? payable(_beneficiary) : payable(msg.sender),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _leftoverAmount\n );\n }\n }\n\n emit Pay(\n _projectId,\n _beneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event. \n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender\n );\n\n // Distribute any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to add to its balance.\n if (_projectId != 0)\n // Add to the project's balance.\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\n\n // Otherwise, send a payment to the beneficiary.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(msg.sender),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _leftoverAmount\n );\n }\n }\n\n emit AddToBalance(\n _projectId,\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splitsProjectId The ID of the project to which the splits belong.\n @param _splitsDomain The splits domain to which the group belongs.\n @param _splitsGroup The splits group to pay.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payToSplits(\n uint256 _splitsProjectId,\n uint256 _splitsDomain,\n uint256 _splitsGroup,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Pay the splits.\n leftoverAmount = _payTo(\n splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup),\n _token,\n _amount,\n _decimals,\n _defaultBeneficiary\n );\n emit DistributeToSplitGroup(_splitsProjectId, _splitsDomain, _splitsGroup, msg.sender);\n }\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splits The splits.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payTo(\n JBSplit[] memory _splits,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Set the leftover amount to the initial balance.\n leftoverAmount = _amount;\n\n // Settle between all splits.\n for (uint256 i = 0; i < _splits.length; i++) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[i];\n\n // The amount to send towards the split.\n uint256 _splitAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n if (_splitAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n _token,\n _splitAmount,\n _decimals,\n defaultProjectId,\n 0,\n _split\n );\n\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\n if (_token != JBTokens.ETH)\n IERC20(_token).approve(address(_split.allocator), _splitAmount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _splitAmount : 0;\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n if (_split.preferAddToBalance)\n _addToBalanceOf(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n 0,\n _split.preferClaimed,\n defaultMemo,\n defaultMetadata\n );\n } else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : payable(_defaultBeneficiary),\n _splitAmount\n );\n // Or, transfer the ERC20.\n else {\n IERC20(_token).safeTransfer(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n _splitAmount\n );\n }\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _splitAmount;\n }\n\n emit DistributeToSplit(_split, _splitAmount, _defaultBeneficiary, msg.sender);\n }\n }\n}\n" + "contracts/JBGasTokenERC20SplitsPayer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBSplitsPayer.sol';\nimport './interfaces/IJBSplitsStore.sol';\nimport './libraries/JBConstants.sol';\nimport './JBGasTokenERC20ProjectPayer.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\n\n @dev\n Adheres to -\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBGasTokenERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBGasTokenERC20SplitsPayer is IJBSplitsPayer, JBGasTokenERC20ProjectPayer, ReentrancyGuard {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The ID of project for which the default splits are stored. \n */\n uint256 public override defaultSplitsProjectId;\n\n /**\n @notice\n The domain within which the default splits are stored. \n */\n uint256 public override defaultSplitsDomain;\n\n /**\n @notice\n The group within which the default splits are stored. \n */\n uint256 public override defaultSplitsGroup;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBGasTokenERC20ProjectPayer, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n )\n JBGasTokenERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _preferAddToBalance,\n _splitsStore.directory(),\n _owner\n )\n {\n defaultSplitsProjectId = _defaultSplitsProjectId;\n defaultSplitsDomain = _defaultSplitsDomain;\n defaultSplitsGroup = _defaultSplitsGroup;\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default split group using the stored default properties.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override nonReentrant {\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender\n );\n\n // If there is no leftover amount, nothing left to pay.\n if (_leftoverAmount == 0) return;\n\n // If there's a default project ID, try to pay it.\n if (defaultProjectId != 0)\n if (defaultPreferAddToBalance)\n // Pay the project by adding to its balance if prefered.\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n _leftoverAmount,\n 18, // decimals.\n defaultMemo,\n defaultMetadata\n );\n // Otherwise, issue a payment to the project.\n else\n _pay(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n _leftoverAmount,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n 0, // min returned tokens.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n // If no project was specified, send the funds directly to the beneficiary or the msg.sender.\n else\n Address.sendValue(\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(msg.sender),\n _leftoverAmount\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the location of the splits that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n */\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) external virtual override onlyOwner {\n // Set the default splits project ID if it's changing.\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\n\n // Set the default splits domain if it's changing.\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\n\n // Set the default splits group if it's changing.\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\n\n emit SetDefaultSplits(_projectId, _domain, _group, msg.sender);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender\n );\n\n // Pay any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to pay it.\n if (_projectId != 0) {\n _pay(\n _projectId,\n _token,\n _leftoverAmount,\n _decimals,\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n // If no project was specified, send the funds directly to the beneficiary or the msg.sender.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _beneficiary != address(0) ? payable(_beneficiary) : payable(msg.sender),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _leftoverAmount\n );\n }\n }\n\n emit Pay(\n _projectId,\n _beneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event. \n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender\n );\n\n // Distribute any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to add to its balance.\n if (_projectId != 0)\n // Add to the project's balance.\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\n\n // Otherwise, send a payment to the beneficiary.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(msg.sender),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _leftoverAmount\n );\n }\n }\n\n emit AddToBalance(\n _projectId,\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splitsProjectId The ID of the project to which the splits belong.\n @param _splitsDomain The splits domain to which the group belongs.\n @param _splitsGroup The splits group to pay.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payToSplits(\n uint256 _splitsProjectId,\n uint256 _splitsDomain,\n uint256 _splitsGroup,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Pay the splits.\n leftoverAmount = _payTo(\n splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup),\n _token,\n _amount,\n _decimals,\n _defaultBeneficiary\n );\n emit DistributeToSplitGroup(_splitsProjectId, _splitsDomain, _splitsGroup, msg.sender);\n }\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splits The splits.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payTo(\n JBSplit[] memory _splits,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Set the leftover amount to the initial balance.\n leftoverAmount = _amount;\n\n // Settle between all splits.\n for (uint256 i = 0; i < _splits.length; i++) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[i];\n\n // The amount to send towards the split.\n uint256 _splitAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n if (_splitAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n _token,\n _splitAmount,\n _decimals,\n defaultProjectId,\n 0,\n _split\n );\n\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN)\n IERC20(_token).approve(address(_split.allocator), _splitAmount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _splitAmount : 0;\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n if (_split.preferAddToBalance)\n _addToBalanceOf(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n 0,\n _split.preferClaimed,\n defaultMemo,\n defaultMetadata\n );\n } else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : payable(_defaultBeneficiary),\n _splitAmount\n );\n // Or, transfer the ERC20.\n else {\n IERC20(_token).safeTransfer(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n _splitAmount\n );\n }\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _splitAmount;\n }\n\n emit DistributeToSplit(_split, _splitAmount, _defaultBeneficiary, msg.sender);\n }\n }\n}\n" }, "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n function safeTransfer(\n IERC20 token,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(\n IERC20 token,\n address from,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n uint256 newAllowance = token.allowance(address(this), spender) + value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n uint256 newAllowance = oldAllowance - value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) {\n // Return data is optional\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" @@ -289,23 +289,23 @@ "contracts/interfaces/IJBSplitsPayer.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './../structs/JBSplit.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBSplitsPayer is IERC165 {\n event SetDefaultSplits(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n address caller\n );\n event Pay(\n uint256 indexed projectId,\n address beneficiary,\n address token,\n uint256 amount,\n uint256 decimals,\n uint256 leftoverAmount,\n uint256 minReturnedTokens,\n bool preferClaimedTokens,\n string memo,\n bytes metadata,\n address caller\n );\n\n event AddToBalance(\n uint256 indexed projectId,\n address beneficiary,\n address token,\n uint256 amount,\n uint256 decimals,\n uint256 leftoverAmount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DistributeToSplitGroup(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n address caller\n );\n\n event DistributeToSplit(\n JBSplit split,\n uint256 amount,\n address defaultBeneficiary,\n address caller\n );\n\n function defaultSplitsProjectId() external view returns (uint256);\n\n function defaultSplitsDomain() external view returns (uint256);\n\n function defaultSplitsGroup() external view returns (uint256);\n\n function splitsStore() external view returns (IJBSplitsStore);\n\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) external;\n}\n" }, - "contracts/JBETHERC20ProjectPayer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport './interfaces/IJBProjectPayer.sol';\nimport './libraries/JBTokens.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ERC165: Introspection on interface adherance. \n*/\ncontract JBETHERC20ProjectPayer is IJBProjectPayer, Ownable, ERC165 {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // -------------------------- custom errors -------------------------- //\n //*********************************************************************//\n error INCORRECT_DECIMAL_AMOUNT();\n error NO_MSG_VALUE_ALLOWED();\n error TERMINAL_NOT_FOUND();\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice \n A contract storing directories of terminals and controllers for each project.\n */\n IJBDirectory public immutable override directory;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The ID of the project that should be used to forward this contract's received payments.\n */\n uint256 public override defaultProjectId;\n\n /** \n @notice \n The beneficiary that should be used in the payment made when this contract receives payments.\n */\n address payable public override defaultBeneficiary;\n\n /** \n @notice \n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\n */\n bool public override defaultPreferClaimedTokens;\n\n /** \n @notice \n The memo that should be used in the payment made when this contract receives payments.\n */\n string public override defaultMemo;\n\n /** \n @notice \n The metadata that should be used in the payment made when this contract receives payments.\n */\n bytes public override defaultMetadata;\n\n /**\n @notice \n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n bool public override defaultPreferAddToBalance;\n\n //*********************************************************************//\n // ------------------------- public views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) {\n defaultProjectId = _defaultProjectId;\n defaultBeneficiary = _defaultBeneficiary;\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\n defaultMemo = _defaultMemo;\n defaultMetadata = _defaultMetadata;\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n directory = _directory;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default project ID using the stored default properties.\n\n @dev\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override {\n if (defaultPreferAddToBalance)\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.ETH,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n defaultProjectId,\n JBTokens.ETH,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultBeneficiary == address(0) ? tx.origin : defaultBeneficiary,\n 0, // Can't determine expectation of returned tokens ahead of time.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\n\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _beneficiary The address that'll receive the project's tokens. \n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _memo The memo that'll be used. \n @param _metadata The metadata that'll be sent. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external virtual override onlyOwner {\n // Set the default project ID if it has changed.\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\n\n // Set the default beneficiary if it has changed.\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\n\n // Set the default claimed token preference if it has changed.\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\n defaultPreferClaimedTokens = _preferClaimedTokens;\n\n // Set the default memo if it has changed.\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\n defaultMemo = _memo;\n\n // Set the default metadata if it has changed.\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\n defaultMetadata = _metadata;\n\n // Set the add to balance preference if it has changed.\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n\n emit SetDefaultValues(\n _projectId,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata,\n _defaultPreferAddToBalance,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _pay(\n _projectId,\n _token,\n _amount,\n _decimals,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. \n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source and delegate, if provided.\n */\n function _pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.ETH) IERC20(_token).approve(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\n\n // Send funds to the terminal.\n // If the token is ETH, send it in msg.value.\n _terminal.pay{value: _payableValue}(\n _projectId,\n _amount, // ignored if the token is JBTokens.ETH.\n _token,\n _beneficiary != address(0) ? _beneficiary : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.ETH) IERC20(_token).approve(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\n\n // Add to balance so tokens don't get issued.\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\n }\n}\n" + "contracts/JBGasTokenERC20ProjectPayer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport './interfaces/IJBProjectPayer.sol';\nimport './libraries/JBTokens.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ERC165: Introspection on interface adherance. \n*/\ncontract JBGasTokenERC20ProjectPayer is IJBProjectPayer, Ownable, ERC165 {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // -------------------------- custom errors -------------------------- //\n //*********************************************************************//\n error INCORRECT_DECIMAL_AMOUNT();\n error NO_MSG_VALUE_ALLOWED();\n error TERMINAL_NOT_FOUND();\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice \n A contract storing directories of terminals and controllers for each project.\n */\n IJBDirectory public immutable override directory;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The ID of the project that should be used to forward this contract's received payments.\n */\n uint256 public override defaultProjectId;\n\n /** \n @notice \n The beneficiary that should be used in the payment made when this contract receives payments.\n */\n address payable public override defaultBeneficiary;\n\n /** \n @notice \n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\n */\n bool public override defaultPreferClaimedTokens;\n\n /** \n @notice \n The memo that should be used in the payment made when this contract receives payments.\n */\n string public override defaultMemo;\n\n /** \n @notice \n The metadata that should be used in the payment made when this contract receives payments.\n */\n bytes public override defaultMetadata;\n\n /**\n @notice \n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n bool public override defaultPreferAddToBalance;\n\n //*********************************************************************//\n // ------------------------- public views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) {\n defaultProjectId = _defaultProjectId;\n defaultBeneficiary = _defaultBeneficiary;\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\n defaultMemo = _defaultMemo;\n defaultMetadata = _defaultMetadata;\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n directory = _directory;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default project ID using the stored default properties.\n\n @dev\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override {\n if (defaultPreferAddToBalance)\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultBeneficiary == address(0) ? tx.origin : defaultBeneficiary,\n 0, // Can't determine expectation of returned tokens ahead of time.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\n\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _beneficiary The address that'll receive the project's tokens. \n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _memo The memo that'll be used. \n @param _metadata The metadata that'll be sent. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external virtual override onlyOwner {\n // Set the default project ID if it has changed.\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\n\n // Set the default beneficiary if it has changed.\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\n\n // Set the default claimed token preference if it has changed.\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\n defaultPreferClaimedTokens = _preferClaimedTokens;\n\n // Set the default memo if it has changed.\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\n defaultMemo = _memo;\n\n // Set the default metadata if it has changed.\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\n defaultMetadata = _metadata;\n\n // Set the add to balance preference if it has changed.\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n\n emit SetDefaultValues(\n _projectId,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata,\n _defaultPreferAddToBalance,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _pay(\n _projectId,\n _token,\n _amount,\n _decimals,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. \n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source and delegate, if provided.\n */\n function _pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).approve(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send funds to the terminal.\n // If the token is ETH, send it in msg.value.\n _terminal.pay{value: _payableValue}(\n _projectId,\n _amount, // ignored if the token is JBTokens.GAS_TOKEN.\n _token,\n _beneficiary != address(0) ? _beneficiary : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).approve(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Add to balance so tokens don't get issued.\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\n }\n}\n" }, "contracts/interfaces/IJBProjectPayer.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './IJBDirectory.sol';\n\ninterface IJBProjectPayer is IERC165 {\n event SetDefaultValues(\n uint256 indexed projectId,\n address indexed beneficiary,\n bool preferClaimedTokens,\n string memo,\n bytes metadata,\n bool preferAddToBalance,\n address caller\n );\n\n function directory() external view returns (IJBDirectory);\n\n function defaultProjectId() external view returns (uint256);\n\n function defaultBeneficiary() external view returns (address payable);\n\n function defaultPreferClaimedTokens() external view returns (bool);\n\n function defaultMemo() external view returns (string memory);\n\n function defaultMetadata() external view returns (bytes memory);\n\n function defaultPreferAddToBalance() external view returns (bool);\n\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external;\n\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) external payable;\n\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) external payable;\n\n receive() external payable;\n}\n" }, - "contracts/JBETHERC20SplitsPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './interfaces/IJBETHERC20SplitsPayerDeployer.sol';\nimport './JBETHERC20SplitsPayer.sol';\n\n/** \n @notice \n Deploys splits payer contracts.\n\n @dev\n Adheres to -\n IJBETHERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBETHERC20SplitsPayerDeployer is IJBETHERC20SplitsPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBSplitsPayer splitsPayer) {\n // Deploy the splits payer.\n splitsPayer = new JBETHERC20SplitsPayer(\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeploySplitsPayer(\n splitsPayer,\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner,\n msg.sender\n );\n }\n}\n" + "contracts/JBGasTokenERC20SplitsPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './interfaces/IJBGasTokenERC20SplitsPayerDeployer.sol';\nimport './JBGasTokenERC20SplitsPayer.sol';\n\n/** \n @notice \n Deploys splits payer contracts.\n\n @dev\n Adheres to -\n IJBGasTokenERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBGasTokenERC20SplitsPayerDeployer is IJBGasTokenERC20SplitsPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBSplitsPayer splitsPayer) {\n // Deploy the splits payer.\n splitsPayer = new JBGasTokenERC20SplitsPayer(\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeploySplitsPayer(\n splitsPayer,\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner,\n msg.sender\n );\n }\n}\n" }, - "contracts/interfaces/IJBETHERC20SplitsPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './IJBSplitsPayer.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBETHERC20SplitsPayerDeployer {\n event DeploySplitsPayer(\n IJBSplitsPayer indexed splitsPayer,\n uint256 defaultSplitsProjectId,\n uint256 defaultSplitsDomain,\n uint256 defaultSplitsGroup,\n IJBSplitsStore splitsStore,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n address owner,\n address caller\n );\n\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string calldata _defaultMemo,\n bytes calldata _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n}\n" + "contracts/interfaces/IJBGasTokenERC20SplitsPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './IJBSplitsPayer.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBGasTokenERC20SplitsPayerDeployer {\n event DeploySplitsPayer(\n IJBSplitsPayer indexed splitsPayer,\n uint256 defaultSplitsProjectId,\n uint256 defaultSplitsDomain,\n uint256 defaultSplitsGroup,\n IJBSplitsStore splitsStore,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n address owner,\n address caller\n );\n\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string calldata _defaultMemo,\n bytes calldata _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n}\n" }, - "contracts/JBETHERC20ProjectPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './interfaces/IJBETHERC20ProjectPayerDeployer.sol';\nimport './JBETHERC20ProjectPayer.sol';\n\n/** \n @notice \n Deploys project payer contracts.\n\n @dev\n Adheres to -\n IJBETHERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBETHERC20ProjectPayerDeployer is IJBETHERC20ProjectPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new project payer contract.\n\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the project payer contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the project payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the project payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the project payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the project payer.\n\n @return projectPayer The project payer contract.\n */\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external override returns (IJBProjectPayer projectPayer) {\n // Deploy the project payer.\n projectPayer = new JBETHERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner\n );\n\n emit DeployProjectPayer(\n projectPayer,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner,\n msg.sender\n );\n }\n}\n" + "contracts/JBGasTokenERC20ProjectPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './interfaces/IJBGasTokenERC20ProjectPayerDeployer.sol';\nimport './JBGasTokenERC20ProjectPayer.sol';\n\n/** \n @notice \n Deploys project payer contracts.\n\n @dev\n Adheres to -\n IJBGasTokenERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBGasTokenERC20ProjectPayerDeployer is IJBGasTokenERC20ProjectPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new project payer contract.\n\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the project payer contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the project payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the project payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the project payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the project payer.\n\n @return projectPayer The project payer contract.\n */\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external override returns (IJBProjectPayer projectPayer) {\n // Deploy the project payer.\n projectPayer = new JBGasTokenERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner\n );\n\n emit DeployProjectPayer(\n projectPayer,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner,\n msg.sender\n );\n }\n}\n" }, - "contracts/interfaces/IJBETHERC20ProjectPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './IJBDirectory.sol';\nimport './IJBProjectPayer.sol';\n\ninterface IJBETHERC20ProjectPayerDeployer {\n event DeployProjectPayer(\n IJBProjectPayer indexed projectPayer,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n IJBDirectory directory,\n address owner,\n address caller\n );\n\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external returns (IJBProjectPayer projectPayer);\n}\n" + "contracts/interfaces/IJBGasTokenERC20ProjectPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './IJBDirectory.sol';\nimport './IJBProjectPayer.sol';\n\ninterface IJBGasTokenERC20ProjectPayerDeployer {\n event DeployProjectPayer(\n IJBProjectPayer indexed projectPayer,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n IJBDirectory directory,\n address owner,\n address caller\n );\n\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external returns (IJBProjectPayer projectPayer);\n}\n" }, "contracts/JBDirectory.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport './abstract/JBOperatable.sol';\nimport './interfaces/IJBDirectory.sol';\nimport './libraries/JBGlobalFundingCycleMetadataResolver.sol';\nimport './libraries/JBOperations.sol';\n\n/**\n @notice\n Keeps a reference of which terminal contracts each project is currently accepting funds through, and which controller contract is managing each project's tokens and funding cycles.\n\n @dev\n Adheres to -\n IJBDirectory: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\ncontract JBDirectory is IJBDirectory, JBOperatable, Ownable {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBGlobalFundingCycleMetadataResolver for uint8;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error DUPLICATE_TERMINALS();\n error INVALID_PROJECT_ID_IN_DIRECTORY();\n error SET_CONTROLLER_NOT_ALLOWED();\n error SET_TERMINALS_NOT_ALLOWED();\n error TOKEN_NOT_ACCEPTED();\n\n //*********************************************************************//\n // --------------------- private stored properties ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n For each project ID, the terminals that are currently managing its funds.\n\n _projectId The ID of the project to get terminals of.\n */\n mapping(uint256 => IJBPaymentTerminal[]) private _terminalsOf;\n\n /**\n @notice\n The project's primary terminal for a token.\n\n _projectId The ID of the project to get the primary terminal of.\n _token The token to get the project's primary terminal of.\n */\n mapping(uint256 => mapping(address => IJBPaymentTerminal)) private _primaryTerminalOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n For each project ID, the controller that manages how terminals interact with tokens and funding cycles.\n\n _projectId The ID of the project to get the controller of.\n */\n mapping(uint256 => address) public override controllerOf;\n\n /**\n @notice\n Addresses that can set a project's first controller on their behalf. These addresses/contracts have been vetted and verified by this contract's owner.\n\n _address The address that is either allowed or not.\n */\n mapping(address => bool) public override isAllowedToSetFirstController;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n For each project ID, the terminals that are currently managing its funds.\n\n @param _projectId The ID of the project to get terminals of.\n\n @return An array of terminal addresses.\n */\n function terminalsOf(uint256 _projectId)\n external\n view\n override\n returns (IJBPaymentTerminal[] memory)\n {\n return _terminalsOf[_projectId];\n }\n\n /**\n @notice\n The primary terminal that is managing funds for a project for a specified token.\n\n @dev\n The zero address is returned if a terminal isn't found for the specified token.\n\n @param _projectId The ID of the project to get a terminal for.\n @param _token The token the terminal accepts.\n\n @return The primary terminal for the project for the specified token.\n */\n function primaryTerminalOf(uint256 _projectId, address _token)\n external\n view\n override\n returns (IJBPaymentTerminal)\n {\n // If a primary terminal for the token was specifically set and it's one of the project's terminals, return it.\n if (\n _primaryTerminalOf[_projectId][_token] != IJBPaymentTerminal(address(0)) &&\n isTerminalOf(_projectId, _primaryTerminalOf[_projectId][_token])\n ) return _primaryTerminalOf[_projectId][_token];\n\n // Return the first terminal which accepts the specified token.\n for (uint256 _i; _i < _terminalsOf[_projectId].length; _i++) {\n IJBPaymentTerminal _terminal = _terminalsOf[_projectId][_i];\n if (_terminal.acceptsToken(_token, _projectId)) return _terminal;\n }\n\n // Not found.\n return IJBPaymentTerminal(address(0));\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Whether or not a specified terminal is a terminal of the specified project.\n\n @param _projectId The ID of the project to check within.\n @param _terminal The address of the terminal to check for.\n\n @return A flag indicating whether or not the specified terminal is a terminal of the specified project.\n */\n function isTerminalOf(uint256 _projectId, IJBPaymentTerminal _terminal)\n public\n view\n override\n returns (bool)\n {\n for (uint256 _i; _i < _terminalsOf[_projectId].length; _i++)\n if (_terminalsOf[_projectId][_i] == _terminal) return true;\n return false;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _owner The address that will own the contract.\n */\n constructor(\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBFundingCycleStore _fundingCycleStore,\n address _owner\n ) JBOperatable(_operatorStore) {\n projects = _projects;\n fundingCycleStore = _fundingCycleStore;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Update the controller that manages how terminals interact with the ecosystem.\n\n @dev\n A controller can be set if:\n - the message sender is the project owner or an operator having the correct authorization.\n - the message sender is the project's current controller.\n - or, an allowedlisted address is setting a controller for a project that doesn't already have a controller.\n\n @param _projectId The ID of the project to set a new controller for.\n @param _controller The new controller to set.\n */\n function setControllerOf(uint256 _projectId, address _controller)\n external\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.SET_CONTROLLER,\n (msg.sender == address(controllerOf[_projectId]) ||\n (isAllowedToSetFirstController[msg.sender] && controllerOf[_projectId] == address(0)))\n )\n {\n // The project must exist.\n if (projects.count() < _projectId) revert INVALID_PROJECT_ID_IN_DIRECTORY();\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Setting controller is allowed if called from the current controller, or if the project doesn't have a current controller, or if the project's funding cycle allows setting the controller. Revert otherwise.\n if (\n msg.sender != address(controllerOf[_projectId]) &&\n controllerOf[_projectId] != address(0) &&\n !uint8(_fundingCycle.metadata >> 8).setControllerAllowed()\n ) revert SET_CONTROLLER_NOT_ALLOWED();\n\n // Set the new controller.\n controllerOf[_projectId] = _controller;\n\n emit SetController(_projectId, _controller, msg.sender);\n }\n\n /** \n @notice \n Set a project's terminals.\n\n @dev\n Only a project owner, an operator, or its controller can set its terminals.\n\n @param _projectId The ID of the project having terminals set.\n @param _terminals The terminal to set.\n */\n function setTerminalsOf(uint256 _projectId, IJBPaymentTerminal[] calldata _terminals)\n external\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.SET_TERMINALS,\n msg.sender == address(controllerOf[_projectId])\n )\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Setting terminals must be allowed if not called from the current controller.\n if (\n msg.sender != address(controllerOf[_projectId]) &&\n !uint8(_fundingCycle.metadata >> 8).setTerminalsAllowed()\n ) revert SET_TERMINALS_NOT_ALLOWED();\n\n // Set the stored terminals for the project.\n _terminalsOf[_projectId] = _terminals;\n\n // Make sure duplicates were not added.\n if (_terminals.length > 1)\n for (uint256 _i; _i < _terminals.length; _i++)\n for (uint256 _j = _i + 1; _j < _terminals.length; _j++)\n if (_terminals[_i] == _terminals[_j]) revert DUPLICATE_TERMINALS();\n\n emit SetTerminals(_projectId, _terminals, msg.sender);\n }\n\n /**\n @notice\n Project's can set which terminal should be their primary for a particular token.\n This is useful in case a project has several terminals connected for a particular token.\n\n @dev\n The terminal will be set as the primary terminal where ecosystem contracts should route tokens.\n\n @dev\n If setting a newly added terminal and the funding cycle doesn't allow new terminals, the caller must be the current controller.\n\n @param _projectId The ID of the project for which a primary token is being set.\n @param _token The token to set the primary terminal of.\n @param _terminal The terminal to make primary.\n */\n function setPrimaryTerminalOf(\n uint256 _projectId,\n address _token,\n IJBPaymentTerminal _terminal\n )\n external\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.SET_PRIMARY_TERMINAL)\n {\n // Can't set the primary terminal for a token if it doesn't accept the token.\n if (!_terminal.acceptsToken(_token, _projectId)) revert TOKEN_NOT_ACCEPTED();\n\n // Add the terminal to the project if it hasn't been already.\n _addTerminalIfNeeded(_projectId, _terminal);\n\n // Store the terminal as the primary for the particular token.\n _primaryTerminalOf[_projectId][_token] = _terminal;\n\n emit SetPrimaryTerminal(_projectId, _token, _terminal, msg.sender);\n }\n\n /** \n @notice\t\n Set a contract to the list of trusted addresses that can set a first controller for any project.\t\n\n @dev\n The owner can add addresses which are allowed to change projects' first controllers. \n These addresses are known and vetted controllers as well as contracts designed to launch new projects. \n A project can set its own controller without it being on the allow list.\n\n @dev\n If you would like an address/contract allowlisted, please reach out to the contract owner.\n\n @param _address The address to allow or revoke allowance from.\n @param _flag Whether allowance is being added or revoked.\n */\n function setIsAllowedToSetFirstController(address _address, bool _flag)\n external\n override\n onlyOwner\n {\n // Set the flag in the allowlist.\n isAllowedToSetFirstController[_address] = _flag;\n\n emit SetIsAllowedToSetFirstController(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Add a terminal to a project's list of terminals if it hasn't been already.\n\n @param _projectId The ID of the project having a terminal added.\n @param _terminal The terminal to add.\n */\n function _addTerminalIfNeeded(uint256 _projectId, IJBPaymentTerminal _terminal) private {\n // Check that the terminal has not already been added.\n if (isTerminalOf(_projectId, _terminal)) return;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Setting terminals must be allowed if not called from the current controller.\n if (\n msg.sender != address(controllerOf[_projectId]) &&\n !uint8(_fundingCycle.metadata >> 8).setTerminalsAllowed()\n ) revert SET_TERMINALS_NOT_ALLOWED();\n\n // Add the new terminal.\n _terminalsOf[_projectId].push(_terminal);\n\n emit AddTerminal(_projectId, _terminal, msg.sender);\n }\n}\n" diff --git a/deployments/mainnet/solcInputs/36426b5abae189028f71abc80f5dc8b7.json b/deployments/mainnet/solcInputs/36426b5abae189028f71abc80f5dc8b7.json index 8e4e22b2d..589100343 100644 --- a/deployments/mainnet/solcInputs/36426b5abae189028f71abc80f5dc8b7.json +++ b/deployments/mainnet/solcInputs/36426b5abae189028f71abc80f5dc8b7.json @@ -119,13 +119,13 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport './abstract/JBOperatable.sol';\nimport './interfaces/IJBDirectory.sol';\nimport './libraries/JBGlobalFundingCycleMetadataResolver.sol';\nimport './libraries/JBOperations.sol';\n\n/**\n @notice\n Keeps a reference of which terminal contracts each project is currently accepting funds through, and which controller contract is managing each project's tokens and funding cycles.\n\n @dev\n Adheres to -\n IJBDirectory: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\ncontract JBDirectory is IJBDirectory, JBOperatable, Ownable {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBGlobalFundingCycleMetadataResolver for uint8;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error DUPLICATE_TERMINALS();\n error INVALID_PROJECT_ID_IN_DIRECTORY();\n error SET_CONTROLLER_NOT_ALLOWED();\n error SET_TERMINALS_NOT_ALLOWED();\n error TOKEN_NOT_ACCEPTED();\n\n //*********************************************************************//\n // --------------------- private stored properties ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n For each project ID, the terminals that are currently managing its funds.\n\n _projectId The ID of the project to get terminals of.\n */\n mapping(uint256 => IJBPaymentTerminal[]) private _terminalsOf;\n\n /**\n @notice\n The project's primary terminal for a token.\n\n _projectId The ID of the project to get the primary terminal of.\n _token The token to get the project's primary terminal of.\n */\n mapping(uint256 => mapping(address => IJBPaymentTerminal)) private _primaryTerminalOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n For each project ID, the controller that manages how terminals interact with tokens and funding cycles.\n\n _projectId The ID of the project to get the controller of.\n */\n mapping(uint256 => address) public override controllerOf;\n\n /**\n @notice\n Addresses that can set a project's first controller on their behalf. These addresses/contracts have been vetted and verified by this contract's owner.\n\n _address The address that is either allowed or not.\n */\n mapping(address => bool) public override isAllowedToSetFirstController;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n For each project ID, the terminals that are currently managing its funds.\n\n @param _projectId The ID of the project to get terminals of.\n\n @return An array of terminal addresses.\n */\n function terminalsOf(uint256 _projectId)\n external\n view\n override\n returns (IJBPaymentTerminal[] memory)\n {\n return _terminalsOf[_projectId];\n }\n\n /**\n @notice\n The primary terminal that is managing funds for a project for a specified token.\n\n @dev\n The zero address is returned if a terminal isn't found for the specified token.\n\n @param _projectId The ID of the project to get a terminal for.\n @param _token The token the terminal accepts.\n\n @return The primary terminal for the project for the specified token.\n */\n function primaryTerminalOf(uint256 _projectId, address _token)\n external\n view\n override\n returns (IJBPaymentTerminal)\n {\n // If a primary terminal for the token was specifically set and its one of the project's terminals, return it.\n if (\n _primaryTerminalOf[_projectId][_token] != IJBPaymentTerminal(address(0)) &&\n isTerminalOf(_projectId, _primaryTerminalOf[_projectId][_token])\n ) return _primaryTerminalOf[_projectId][_token];\n\n // Return the first terminal which accepts the specified token.\n for (uint256 _i; _i < _terminalsOf[_projectId].length; _i++) {\n IJBPaymentTerminal _terminal = _terminalsOf[_projectId][_i];\n if (_terminal.acceptsToken(_token, _projectId)) return _terminal;\n }\n\n // Not found.\n return IJBPaymentTerminal(address(0));\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Whether or not a specified terminal is a terminal of the specified project.\n\n @param _projectId The ID of the project to check within.\n @param _terminal The address of the terminal to check for.\n\n @return A flag indicating whether or not the specified terminal is a terminal of the specified project.\n */\n function isTerminalOf(uint256 _projectId, IJBPaymentTerminal _terminal)\n public\n view\n override\n returns (bool)\n {\n for (uint256 _i; _i < _terminalsOf[_projectId].length; _i++)\n if (_terminalsOf[_projectId][_i] == _terminal) return true;\n return false;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _owner The address that will own the contract.\n */\n constructor(\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBFundingCycleStore _fundingCycleStore,\n address _owner\n ) JBOperatable(_operatorStore) {\n projects = _projects;\n fundingCycleStore = _fundingCycleStore;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Update the controller that manages how terminals interact with the ecosystem.\n\n @dev\n A controller can be set if:\n - the message sender is the project owner or an operator having the correct authorization.\n - the message sender is the project's current controller.\n - or, an allowedlisted address is setting a controller for a project that doesn't already have a controller.\n\n @param _projectId The ID of the project to set a new controller for.\n @param _controller The new controller to set.\n */\n function setControllerOf(uint256 _projectId, address _controller)\n external\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.SET_CONTROLLER,\n (msg.sender == address(controllerOf[_projectId]) ||\n (isAllowedToSetFirstController[msg.sender] && controllerOf[_projectId] == address(0)))\n )\n {\n // The project must exist.\n if (projects.count() < _projectId) revert INVALID_PROJECT_ID_IN_DIRECTORY();\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Setting controller is allowed if called from the current controller, or if the project doesn't have a current controller, or if the project's funding cycle allows setting the controller. Revert otherwise.\n if (\n msg.sender != address(controllerOf[_projectId]) &&\n controllerOf[_projectId] != address(0) &&\n !uint8(_fundingCycle.metadata >> 8).setControllerAllowed()\n ) revert SET_CONTROLLER_NOT_ALLOWED();\n\n // Set the new controller.\n controllerOf[_projectId] = _controller;\n\n emit SetController(_projectId, _controller, msg.sender);\n }\n\n /** \n @notice \n Set a project's terminals.\n\n @dev\n Only a project owner, an operator, or its controller can set its terminals.\n\n @param _projectId The ID of the project having terminals set.\n @param _terminals The terminal to set.\n */\n function setTerminalsOf(uint256 _projectId, IJBPaymentTerminal[] calldata _terminals)\n external\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.SET_TERMINALS,\n msg.sender == address(controllerOf[_projectId])\n )\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Setting terminals must be allowed if not called from the current controller.\n if (\n msg.sender != address(controllerOf[_projectId]) &&\n !uint8(_fundingCycle.metadata >> 8).setTerminalsAllowed()\n ) revert SET_TERMINALS_NOT_ALLOWED();\n\n // Delete the stored terminals for the project.\n _terminalsOf[_projectId] = _terminals;\n\n // Make sure duplicates were not added.\n if (_terminals.length > 1)\n for (uint256 _i; _i < _terminals.length; _i++)\n for (uint256 _j = _i + 1; _j < _terminals.length; _j++)\n if (_terminals[_i] == _terminals[_j]) revert DUPLICATE_TERMINALS();\n\n emit SetTerminals(_projectId, _terminals, msg.sender);\n }\n\n /**\n @notice\n Project's can set which terminal should be their primary for a particular token.\n This is useful in case a project has several terminals connected for a particular token.\n\n @dev\n The terminal will be set as the primary terminal where ecosystem contracts should route tokens.\n\n @dev\n If setting a newly added terminal and the funding cycle doesn't allow new terminals, the caller must be the current controller.\n\n @param _projectId The ID of the project for which a primary token is being set.\n @param _token The token to set the primary terminal of.\n @param _terminal The terminal to make primary.\n */\n function setPrimaryTerminalOf(\n uint256 _projectId,\n address _token,\n IJBPaymentTerminal _terminal\n )\n external\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.SET_PRIMARY_TERMINAL)\n {\n // Can't set the primary terminal for a token if it doesn't accept the token.\n if (!_terminal.acceptsToken(_token, _projectId)) revert TOKEN_NOT_ACCEPTED();\n\n // Add the terminal to the project if it hasn't been already.\n _addTerminalIfNeeded(_projectId, _terminal);\n\n // Store the terminal as the primary for the particular token.\n _primaryTerminalOf[_projectId][_token] = _terminal;\n\n emit SetPrimaryTerminal(_projectId, _token, _terminal, msg.sender);\n }\n\n /** \n @notice\t\n Set a contract to the list of trusted addresses that can set a first controller for any project.\t\n\n @dev\n The owner can add addresses which are allowed to change projects' first controllers. \n These addresses are known and vetted controllers as well as contracts designed to launch new projects. \n A project can set its own controller without it being on the allow list.\n\n @dev\n If you would like an address/contract allowlisted, please reach out to the contract owner.\n\n @param _address The address to allow or revoke allowance from.\n @param _flag Whether allowance is being added or revoked.\n */\n function setIsAllowedToSetFirstController(address _address, bool _flag)\n external\n override\n onlyOwner\n {\n // Set the flag in the allowlist.\n isAllowedToSetFirstController[_address] = _flag;\n\n emit SetIsAllowedToSetFirstController(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Add a terminal to a project's list of terminals if it hasn't been already.\n\n @param _projectId The ID of the project having a terminal added.\n @param _terminal The terminal to add.\n */\n function _addTerminalIfNeeded(uint256 _projectId, IJBPaymentTerminal _terminal) private {\n // Check that the terminal has not already been added.\n if (isTerminalOf(_projectId, _terminal)) return;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Setting terminals must be allowed if not called from the current controller.\n if (\n msg.sender != address(controllerOf[_projectId]) &&\n !uint8(_fundingCycle.metadata >> 8).setTerminalsAllowed()\n ) revert SET_TERMINALS_NOT_ALLOWED();\n\n // Add the new terminal.\n _terminalsOf[_projectId].push(_terminal);\n\n emit AddTerminal(_projectId, _terminal, msg.sender);\n }\n}\n" }, "contracts/JBETHPaymentTerminal/1.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './../abstract/JBPayoutRedemptionPaymentTerminal/1.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n JBTokens.ETH,\n 18, // 18 decimals.\n JBCurrencies.ETH,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal pure override {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './../abstract/JBPayoutRedemptionPaymentTerminal/1.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n JBTokens.GAS_TOKEN,\n 18, // 18 decimals.\n JBCurrencies.GAS_CURRENCY,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal pure override {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n}\n" }, "contracts/JBERC20PaymentTerminal/1.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol';\nimport './../abstract/JBPayoutRedemptionPaymentTerminal/1.sol';\n\n/** \n @notice \n Manages the inflows and outflows of an ERC-20 token.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\ncontract JBERC20PaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n IERC20Metadata _token,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n address(_token),\n _token.decimals(),\n _currency,\n _baseWeightCurrency,\n _payoutSplitsGroup,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from == address(this)\n ? IERC20(token).transfer(_to, _amount)\n : IERC20(token).transferFrom(_from, _to, _amount);\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal override {\n IERC20(token).approve(_to, _amount);\n }\n}\n" }, "contracts/JBSingleTokenPaymentTerminalStore/1.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController/1.sol';\nimport './../interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBSingleTokenPaymentTerminalStore is IJBSingleTokenPaymentTerminalStore, ReentrancyGuard {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n Mint's 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegate A delegate contract to use for subsequent calls.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n IJBPayDelegate delegate,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay()) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegate) = IJBFundingCycleDataSource(fundingCycle.dataSource()).payParams(\n _data\n );\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegate, memo);\n\n // Add the amount to the token balance of the project.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount.value;\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegate, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegate A delegate contract to use for subsequent calls.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n IJBRedemptionDelegate delegate,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\n _projectId,\n fundingCycle.reservedRate()\n );\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow > 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem()) {\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n fundingCycle.redemptionRate(),\n fundingCycle.ballotRedemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegate) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .redeemParams(_data);\n } else {\n memo = _memo;\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (reclaimAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (reclaimAmount > 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n reclaimAmount;\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n return _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i = 0; _i < _terminals.length; _i++)\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.ETH\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.ETH, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController/1.sol';\nimport './../interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBSingleTokenPaymentTerminalStore is IJBSingleTokenPaymentTerminalStore, ReentrancyGuard {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n Mint's 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegate A delegate contract to use for subsequent calls.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n IJBPayDelegate delegate,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay()) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegate) = IJBFundingCycleDataSource(fundingCycle.dataSource()).payParams(\n _data\n );\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegate, memo);\n\n // Add the amount to the token balance of the project.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount.value;\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegate, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegate A delegate contract to use for subsequent calls.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n IJBRedemptionDelegate delegate,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\n _projectId,\n fundingCycle.reservedRate()\n );\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow > 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem()) {\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n fundingCycle.redemptionRate(),\n fundingCycle.ballotRedemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegate) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .redeemParams(_data);\n } else {\n memo = _memo;\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (reclaimAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (reclaimAmount > 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n reclaimAmount;\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n return _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i = 0; _i < _terminals.length; _i++)\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.GAS_CURRENCY\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.GAS_CURRENCY, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" }, "contracts/JBFundingCycleStore/1.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../abstract/JBControllerUtility.sol';\nimport './../libraries/JBConstants.sol';\n\n/** \n @notice \n Manages funding cycle configurations and scheduling.\n\n @dev\n Adheres to -\n IJBTokenStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBControllerUtility: Includes convenience functionality for checking if the message sender is the current controller of the project whose data is being manipulated.\n*/\ncontract JBFundingCycleStore is IJBFundingCycleStore, JBControllerUtility {\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_DISCOUNT_RATE();\n error INVALID_DURATION();\n error INVALID_WEIGHT();\n error NO_SAME_BLOCK_RECONFIGURATION();\n\n //*********************************************************************//\n // --------------------- private stored properties ------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Stores the user defined properties of each funding cycle, packed into one storage slot.\n\n _projectId The ID of the project to get properties of.\n _configuration The funding cycle configuration to get properties of.\n */\n mapping(uint256 => mapping(uint256 => uint256)) private _packedUserPropertiesOf;\n\n /** \n @notice\n Stores the properties added by the mechanism to manage and schedule each funding cycle, packed into one storage slot.\n \n _projectId The ID of the project to get instrinsic properties of.\n _configuration The funding cycle configuration to get properties of.\n */\n mapping(uint256 => mapping(uint256 => uint256)) private _packedIntrinsicPropertiesOf;\n\n /** \n @notice\n Stores the metadata for each funding cycle configuration, packed into one storage slot.\n\n _projectId The ID of the project to get metadata of.\n _configuration The funding cycle configuration to get metadata of.\n */\n mapping(uint256 => mapping(uint256 => uint256)) private _metadataOf;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The latest funding cycle configuration for each project.\n\n _projectId The ID of the project to get the latest funding cycle configuration of.\n */\n mapping(uint256 => uint256) public override latestConfigurationOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice \n Get the funding cycle with the given configuration for the specified project.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n @param _configuration The configuration of the funding cycle to get.\n\n @return fundingCycle The funding cycle.\n */\n function get(uint256 _projectId, uint256 _configuration)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle)\n {\n return _getStructFor(_projectId, _configuration);\n }\n\n /**\n @notice \n The latest funding cycle to be configured for the specified project, and its current ballot state.\n\n @param _projectId The ID of the project to get the latest configured funding cycle of.\n\n @return fundingCycle The project's queued funding cycle.\n @return ballotState The state of the ballot for the reconfiguration.\n */\n function latestConfiguredOf(uint256 _projectId)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle, JBBallotState ballotState)\n {\n // Get a reference to the latest funding cycle configuration.\n uint256 _fundingCycleConfiguration = latestConfigurationOf[_projectId];\n\n // Resolve the funding cycle for the latest configuration.\n fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n // Resolve the ballot state.\n ballotState = _ballotStateOf(\n _projectId,\n fundingCycle.configuration,\n fundingCycle.start,\n fundingCycle.basedOn\n );\n }\n\n /**\n @notice \n The funding cycle that's next up for the specified project.\n\n @dev\n If a queued funding cycle of the project is not found, returns an empty funding cycle with all properties set to 0.\n\n @param _projectId The ID of the project to get the queued funding cycle of.\n\n @return fundingCycle The project's queued funding cycle.\n */\n function queuedOf(uint256 _projectId)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle)\n {\n // If the project does not have a funding cycle, return an empty struct.\n if (latestConfigurationOf[_projectId] == 0) return _getStructFor(0, 0);\n\n // Get a reference to the configuration of the standby funding cycle.\n uint256 _standbyFundingCycleConfiguration = _standbyOf(_projectId);\n\n // If it exists, return its funding cycle if it is approved.\n if (_standbyFundingCycleConfiguration > 0) {\n fundingCycle = _getStructFor(_projectId, _standbyFundingCycleConfiguration);\n\n if (_isApproved(_projectId, fundingCycle)) return fundingCycle;\n\n // Resolve the funding cycle for the latest configured funding cycle.\n fundingCycle = _getStructFor(_projectId, fundingCycle.basedOn);\n } else {\n // Resolve the funding cycle for the latest configured funding cycle.\n fundingCycle = _getStructFor(_projectId, latestConfigurationOf[_projectId]);\n\n // If the latest funding cycle starts in the future, it must start in the distant future\n // since its not in standby. In this case base the queued cycles on the base cycle.\n if (fundingCycle.start > block.timestamp)\n fundingCycle = _getStructFor(_projectId, fundingCycle.basedOn);\n }\n\n // There's no queued if the current has a duration of 0.\n if (fundingCycle.duration == 0) return _getStructFor(0, 0);\n\n // Check to see if this funding cycle's ballot is approved.\n // If so, return a funding cycle based on it.\n if (_isApproved(_projectId, fundingCycle)) return _mockFundingCycleBasedOn(fundingCycle, false);\n\n // Get the funding cycle of its base funding cycle, which carries the last approved configuration.\n fundingCycle = _getStructFor(_projectId, fundingCycle.basedOn);\n\n // There's no queued if the base, which must still be the current, has a duration of 0.\n if (fundingCycle.duration == 0) return _getStructFor(0, 0);\n\n // Return a mock of the next up funding cycle.\n return _mockFundingCycleBasedOn(fundingCycle, false);\n }\n\n /**\n @notice \n The funding cycle that is currently active for the specified project.\n\n @dev\n If a current funding cycle of the project is not found, returns an empty funding cycle with all properties set to 0.\n\n @param _projectId The ID of the project to get the current funding cycle of.\n\n @return fundingCycle The project's current funding cycle.\n */\n function currentOf(uint256 _projectId)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle)\n {\n // If the project does not have a funding cycle, return an empty struct.\n if (latestConfigurationOf[_projectId] == 0) return _getStructFor(0, 0);\n\n // Get a reference to the configuration of the eligible funding cycle.\n uint256 _fundingCycleConfiguration = _eligibleOf(_projectId);\n\n // Keep a reference to the eligible funding cycle.\n JBFundingCycle memory _fundingCycle;\n\n // If an eligible funding cycle exists...\n if (_fundingCycleConfiguration > 0) {\n // Resolve the funding cycle for the eligible configuration.\n _fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n // Check to see if this funding cycle's ballot is approved.\n // If so, return it.\n if (_isApproved(_projectId, _fundingCycle)) return _fundingCycle;\n\n // If it hasn't been approved, set the funding cycle configuration to be the configuration of the funding cycle that it's based on,\n // which carries the last approved configuration.\n _fundingCycleConfiguration = _fundingCycle.basedOn;\n } else {\n // No upcoming funding cycle found that is eligible to become active,\n // so use the last configuration.\n _fundingCycleConfiguration = latestConfigurationOf[_projectId];\n\n // Get the funding cycle for the latest ID.\n _fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n // If it's not approved or if it hasn't yet started, get a reference to the funding cycle that the latest is based on, which has the latest approved configuration.\n if (!_isApproved(_projectId, _fundingCycle) || block.timestamp < _fundingCycle.start)\n _fundingCycleConfiguration = _fundingCycle.basedOn;\n }\n\n // If there is not funding cycle to base the current one on, there can't be a current one.\n if (_fundingCycleConfiguration == 0) return _getStructFor(0, 0);\n\n // The funding cycle to base a current one on.\n _fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n // If the base has no duration, it's still the current one.\n if (_fundingCycle.duration == 0) return _fundingCycle;\n\n // Return a mock of the current funding cycle.\n return _mockFundingCycleBasedOn(_fundingCycle, true);\n }\n\n /** \n @notice \n The current ballot state of the project.\n\n @param _projectId The ID of the project to check the ballot state of.\n\n @return The project's current ballot's state.\n */\n function currentBallotStateOf(uint256 _projectId) external view override returns (JBBallotState) {\n // Get a reference to the latest funding cycle configuration.\n uint256 _fundingCycleConfiguration = latestConfigurationOf[_projectId];\n\n // Resolve the funding cycle for the latest configuration.\n JBFundingCycle memory _fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n return\n _ballotStateOf(\n _projectId,\n _fundingCycle.configuration,\n _fundingCycle.start,\n _fundingCycle.basedOn\n );\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _directory A contract storing directories of terminals and controllers for each project.\n */\n // solhint-disable-next-line no-empty-blocks\n constructor(IJBDirectory _directory) JBControllerUtility(_directory) {}\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice \n Configures the next eligible funding cycle for the specified project.\n\n @dev\n Only a project's current controller can configure its funding cycles.\n\n @param _projectId The ID of the project being configured.\n @param _data The funding cycle configuration data.\n @param _metadata Arbitrary extra data to associate with this funding cycle configuration that's not used within.\n @param _mustStartAtOrAfter The time before which the initialized funding cycle cannot start.\n\n @return The funding cycle that the configuration will take effect during.\n */\n function configureFor(\n uint256 _projectId,\n JBFundingCycleData calldata _data,\n uint256 _metadata,\n uint256 _mustStartAtOrAfter\n ) external override onlyController(_projectId) returns (JBFundingCycle memory) {\n // Duration must fit in a uint64.\n if (_data.duration > type(uint64).max) revert INVALID_DURATION();\n\n // Discount rate must be less than or equal to 100%.\n if (_data.discountRate > JBConstants.MAX_DISCOUNT_RATE) revert INVALID_DISCOUNT_RATE();\n\n // Weight must fit into a uint88.\n if (_data.weight > type(uint88).max) revert INVALID_WEIGHT();\n\n // The configuration timestamp is now.\n uint256 _configuration = block.timestamp;\n\n // Set up a reconfiguration by configuring intrinsic properties.\n _configureIntrinsicPropertiesFor(\n _projectId,\n _configuration,\n _data.weight,\n // Must start on or after the current timestamp.\n _mustStartAtOrAfter > block.timestamp ? _mustStartAtOrAfter : block.timestamp\n );\n\n // Efficiently stores a funding cycles provided user defined properties.\n // If all user config properties are zero, no need to store anything as the default value will have the same outcome.\n if (\n _data.ballot != IJBFundingCycleBallot(address(0)) ||\n _data.duration > 0 ||\n _data.discountRate > 0\n ) {\n // ballot in bits 0-159 bytes.\n uint256 packed = uint160(address(_data.ballot));\n\n // duration in bits 160-223 bytes.\n packed |= _data.duration << 160;\n\n // discountRate in bits 224-255 bytes.\n packed |= _data.discountRate << 224;\n\n // Set in storage.\n _packedUserPropertiesOf[_projectId][_configuration] = packed;\n }\n\n // Set the metadata if needed.\n if (_metadata > 0) _metadataOf[_projectId][_configuration] = _metadata;\n\n emit Configure(_configuration, _projectId, _data, _metadata, _mustStartAtOrAfter, msg.sender);\n\n // Return the funding cycle for the new configuration.\n return _getStructFor(_projectId, _configuration);\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice \n Updates the configurable funding cycle for this project if it exists, otherwise creates one.\n\n @param _projectId The ID of the project to find a configurable funding cycle for.\n @param _configuration The time at which the funding cycle was configured.\n @param _weight The weight to store in the configured funding cycle.\n @param _mustStartAtOrAfter The time before which the initialized funding cycle can't start.\n */\n function _configureIntrinsicPropertiesFor(\n uint256 _projectId,\n uint256 _configuration,\n uint256 _weight,\n uint256 _mustStartAtOrAfter\n ) private {\n // If there's not yet a funding cycle for the project, initialize one.\n if (latestConfigurationOf[_projectId] == 0)\n // Use an empty funding cycle as the base.\n return\n _initFor(_projectId, _getStructFor(0, 0), _configuration, _mustStartAtOrAfter, _weight);\n\n // Get the active funding cycle's configuration.\n uint256 _currentConfiguration = _eligibleOf(_projectId);\n\n // If an eligible funding cycle does not exist, get a reference to the latest funding cycle configuration for the project.\n if (_currentConfiguration == 0)\n // Get the latest funding cycle's configuration.\n _currentConfiguration = latestConfigurationOf[_projectId];\n\n // Get a reference to the funding cycle.\n JBFundingCycle memory _baseFundingCycle = _getStructFor(_projectId, _currentConfiguration);\n\n if (!_isApproved(_projectId, _baseFundingCycle))\n // If it hasn't been approved, set the ID to be the funding cycle it's based on,\n // which carries the latest approved configuration.\n _baseFundingCycle = _getStructFor(_projectId, _baseFundingCycle.basedOn);\n\n // The configuration can't be the same as the base configuration.\n if (_baseFundingCycle.configuration == _configuration) revert NO_SAME_BLOCK_RECONFIGURATION();\n\n // The time after the ballot of the provided funding cycle has expired.\n // If the provided funding cycle has no ballot, return the current timestamp.\n uint256 _timestampAfterBallot = _baseFundingCycle.ballot == IJBFundingCycleBallot(address(0))\n ? 0\n : _configuration + _baseFundingCycle.ballot.duration();\n\n _initFor(\n _projectId,\n _baseFundingCycle,\n _configuration,\n // Can only start after the ballot.\n _timestampAfterBallot > _mustStartAtOrAfter ? _timestampAfterBallot : _mustStartAtOrAfter,\n _weight\n );\n }\n\n /**\n @notice \n Initializes a funding cycle with the specified properties.\n\n @param _projectId The ID of the project to which the funding cycle being initialized belongs.\n @param _baseFundingCycle The funding cycle to base the initialized one on.\n @param _configuration The configuration of the funding cycle being initialized.\n @param _mustStartAtOrAfter The time before which the initialized funding cycle cannot start.\n @param _weight The weight to give the newly initialized funding cycle.\n */\n function _initFor(\n uint256 _projectId,\n JBFundingCycle memory _baseFundingCycle,\n uint256 _configuration,\n uint256 _mustStartAtOrAfter,\n uint256 _weight\n ) private {\n // If there is no base, initialize a first cycle.\n if (_baseFundingCycle.number == 0) {\n // The first number is 1.\n uint256 _number = 1;\n\n // Set fresh intrinsic properties.\n _packAndStoreIntrinsicPropertiesOf(\n _configuration,\n _projectId,\n _number,\n _weight,\n _baseFundingCycle.configuration,\n _mustStartAtOrAfter\n );\n } else {\n // Derive the correct next start time from the base.\n uint256 _start = _deriveStartFrom(_baseFundingCycle, _mustStartAtOrAfter);\n\n // A weight of 1 is treated as a weight of 0.\n // This is to allow a weight of 0 (default) to represent inheriting the discounted weight of the previous funding cycle.\n _weight = _weight > 0\n ? (_weight == 1 ? 0 : _weight)\n : _deriveWeightFrom(_baseFundingCycle, _start);\n\n // Derive the correct number.\n uint256 _number = _deriveNumberFrom(_baseFundingCycle, _start);\n\n // Update the intrinsic properties.\n _packAndStoreIntrinsicPropertiesOf(\n _configuration,\n _projectId,\n _number,\n _weight,\n _baseFundingCycle.configuration,\n _start\n );\n }\n\n // Set the project's latest funding cycle configuration.\n latestConfigurationOf[_projectId] = _configuration;\n\n emit Init(_configuration, _projectId, _baseFundingCycle.configuration);\n }\n\n /**\n @notice \n Efficiently stores a funding cycle's provided intrinsic properties.\n\n @param _configuration The configuration of the funding cycle to pack and store.\n @param _projectId The ID of the project to which the funding cycle belongs.\n @param _number The number of the funding cycle.\n @param _weight The weight of the funding cycle.\n @param _basedOn The configuration of the base funding cycle.\n @param _start The start time of this funding cycle.\n */\n function _packAndStoreIntrinsicPropertiesOf(\n uint256 _configuration,\n uint256 _projectId,\n uint256 _number,\n uint256 _weight,\n uint256 _basedOn,\n uint256 _start\n ) private {\n // weight in bits 0-87.\n uint256 packed = _weight;\n\n // basedOn in bits 88-143.\n packed |= _basedOn << 88;\n\n // start in bits 144-199.\n packed |= _start << 144;\n\n // number in bits 200-255.\n packed |= _number << 200;\n\n // Store the packed value.\n _packedIntrinsicPropertiesOf[_projectId][_configuration] = packed;\n }\n\n /**\n @notice \n The project's stored funding cycle that hasn't yet started and should be used next, if one exists.\n\n @dev\n A value of 0 is returned if no funding cycle was found.\n\n @dev\n Assumes the project has a latest configuration.\n \n @param _projectId The ID of a project to look through for a standby cycle.\n\n @return configuration The configuration of the standby funding cycle if one exists, or 0 if one doesn't exist.\n */\n function _standbyOf(uint256 _projectId) private view returns (uint256 configuration) {\n // Get a reference to the project's latest funding cycle.\n configuration = latestConfigurationOf[_projectId];\n\n // Get the necessary properties for the latest funding cycle.\n JBFundingCycle memory _fundingCycle = _getStructFor(_projectId, configuration);\n\n // There is no upcoming funding cycle if the latest funding cycle has already started.\n if (block.timestamp >= _fundingCycle.start) return 0;\n\n // If this is the first funding cycle, it is queued.\n if (_fundingCycle.number == 1) return configuration;\n\n // Get the necessary properties for the base funding cycle.\n JBFundingCycle memory _baseFundingCycle = _getStructFor(_projectId, _fundingCycle.basedOn);\n\n // If the latest configuration doesn't start until after another base cycle, return 0.\n if (\n _baseFundingCycle.duration > 0 &&\n block.timestamp < _fundingCycle.start - _baseFundingCycle.duration\n ) return 0;\n }\n\n /**\n @notice \n The project's stored funding cycle that has started and hasn't yet expired.\n \n @dev\n A value of 0 is returned if no funding cycle was found.\n\n @dev\n Assumes the project has a latest configuration.\n\n @param _projectId The ID of the project to look through.\n\n @return configuration The configuration of an eligible funding cycle if one exists, or 0 if one doesn't exist.\n */\n function _eligibleOf(uint256 _projectId) private view returns (uint256 configuration) {\n // Get a reference to the project's latest funding cycle.\n configuration = latestConfigurationOf[_projectId];\n\n // Get the latest funding cycle.\n JBFundingCycle memory _fundingCycle = _getStructFor(_projectId, configuration);\n\n // If the latest is expired, return an empty funding cycle.\n // A duration of 0 cannot be expired.\n if (\n _fundingCycle.duration > 0 && block.timestamp >= _fundingCycle.start + _fundingCycle.duration\n ) return 0;\n\n // Return the funding cycle's configuration if it has started.\n if (block.timestamp >= _fundingCycle.start) return _fundingCycle.configuration;\n\n // Get a reference to the cycle's base configuration.\n JBFundingCycle memory _baseFundingCycle = _getStructFor(_projectId, _fundingCycle.basedOn);\n\n // If the base cycle isn't eligible, the project has no eligible cycle.\n // A duration of 0 is always eligible.\n if (\n _baseFundingCycle.duration > 0 &&\n block.timestamp >= _baseFundingCycle.start + _baseFundingCycle.duration\n ) return 0;\n\n // Return the configuration that the latest funding cycle is based on.\n configuration = _fundingCycle.basedOn;\n }\n\n /** \n @notice \n A view of the funding cycle that would be created based on the provided one if the project doesn't make a reconfiguration.\n\n @dev\n Returns an empty funding cycle if there can't be a mock funding cycle based on the provided one.\n\n @dev\n Assumes a funding cycle with a duration of 0 will never be asked to be the base of a mock.\n\n @param _baseFundingCycle The funding cycle that the resulting funding cycle should follow.\n @param _allowMidCycle A flag indicating if the mocked funding cycle is allowed to already be mid cycle.\n\n @return A mock of what the next funding cycle will be.\n */\n function _mockFundingCycleBasedOn(JBFundingCycle memory _baseFundingCycle, bool _allowMidCycle)\n private\n view\n returns (JBFundingCycle memory)\n {\n // Get the distance of the current time to the start of the next possible funding cycle.\n // If the returned mock cycle must not yet have started, the start time of the mock must be in the future.\n uint256 _mustStartAtOrAfter = !_allowMidCycle\n ? block.timestamp + 1\n : block.timestamp - _baseFundingCycle.duration + 1;\n\n // Derive what the start time should be.\n uint256 _start = _deriveStartFrom(_baseFundingCycle, _mustStartAtOrAfter);\n\n // Derive what the number should be.\n uint256 _number = _deriveNumberFrom(_baseFundingCycle, _start);\n\n return\n JBFundingCycle(\n _number,\n _baseFundingCycle.configuration,\n _baseFundingCycle.basedOn,\n _start,\n _baseFundingCycle.duration,\n _deriveWeightFrom(_baseFundingCycle, _start),\n _baseFundingCycle.discountRate,\n _baseFundingCycle.ballot,\n _baseFundingCycle.metadata\n );\n }\n\n /** \n @notice \n The date that is the nearest multiple of the specified funding cycle's duration from its end.\n\n @param _baseFundingCycle The funding cycle to base the calculation on.\n @param _mustStartAtOrAfter A date that the derived start must be on or come after.\n\n @return start The next start time.\n */\n function _deriveStartFrom(JBFundingCycle memory _baseFundingCycle, uint256 _mustStartAtOrAfter)\n private\n pure\n returns (uint256 start)\n {\n // A subsequent cycle to one with a duration of 0 should start as soon as possible.\n if (_baseFundingCycle.duration == 0) return _mustStartAtOrAfter;\n\n // The time when the funding cycle immediately after the specified funding cycle starts.\n uint256 _nextImmediateStart = _baseFundingCycle.start + _baseFundingCycle.duration;\n\n // If the next immediate start is now or in the future, return it.\n if (_nextImmediateStart >= _mustStartAtOrAfter) return _nextImmediateStart;\n\n // The amount of seconds since the `_mustStartAtOrAfter` time which results in a start time that might satisfy the specified constraints.\n uint256 _timeFromImmediateStartMultiple = (_mustStartAtOrAfter - _nextImmediateStart) %\n _baseFundingCycle.duration;\n\n // A reference to the first possible start timestamp.\n start = _mustStartAtOrAfter - _timeFromImmediateStartMultiple;\n\n // Add increments of duration as necessary to satisfy the threshold.\n while (_mustStartAtOrAfter > start) start = start + _baseFundingCycle.duration;\n }\n\n /** \n @notice \n The accumulated weight change since the specified funding cycle.\n\n @param _baseFundingCycle The funding cycle to base the calculation on.\n @param _start The start time of the funding cycle to derive a number for.\n\n @return weight The derived weight, as a fixed point number with 18 decimals.\n */\n function _deriveWeightFrom(JBFundingCycle memory _baseFundingCycle, uint256 _start)\n private\n pure\n returns (uint256 weight)\n {\n // A subsequent cycle to one with a duration of 0 should have the next possible weight.\n if (_baseFundingCycle.duration == 0)\n return\n PRBMath.mulDiv(\n _baseFundingCycle.weight,\n JBConstants.MAX_DISCOUNT_RATE - _baseFundingCycle.discountRate,\n JBConstants.MAX_DISCOUNT_RATE\n );\n\n // The weight should be based off the base funding cycle's weight.\n weight = _baseFundingCycle.weight;\n\n // If the discount is 0, the weight doesn't change.\n if (_baseFundingCycle.discountRate == 0) return weight;\n\n // The difference between the start of the base funding cycle and the proposed start.\n uint256 _startDistance = _start - _baseFundingCycle.start;\n\n // Apply the base funding cycle's discount rate for each cycle that has passed.\n uint256 _discountMultiple = _startDistance / _baseFundingCycle.duration;\n\n for (uint256 i = 0; i < _discountMultiple; i++) {\n // The number of times to apply the discount rate.\n // Base the new weight on the specified funding cycle's weight.\n weight = PRBMath.mulDiv(\n weight,\n JBConstants.MAX_DISCOUNT_RATE - _baseFundingCycle.discountRate,\n JBConstants.MAX_DISCOUNT_RATE\n );\n // The calculation doesn't need to continue if the weight is 0.\n if (weight == 0) break;\n }\n }\n\n /** \n @notice \n The number of the next funding cycle given the specified funding cycle.\n\n @param _baseFundingCycle The funding cycle to base the calculation on.\n @param _start The start time of the funding cycle to derive a number for.\n\n @return The funding cycle number.\n */\n function _deriveNumberFrom(JBFundingCycle memory _baseFundingCycle, uint256 _start)\n private\n pure\n returns (uint256)\n {\n // A subsequent cycle to one with a duration of 0 should be the next number.\n if (_baseFundingCycle.duration == 0) return _baseFundingCycle.number + 1;\n\n // The difference between the start of the base funding cycle and the proposed start.\n uint256 _startDistance = _start - _baseFundingCycle.start;\n\n // Find the number of base cycles that fit in the start distance.\n return _baseFundingCycle.number + (_startDistance / _baseFundingCycle.duration);\n }\n\n /** \n @notice \n Checks to see if the provided funding cycle is approved according to the correct ballot.\n\n @param _projectId The ID of the project to which the funding cycle belongs. \n @param _fundingCycle The funding cycle to get an approval flag for.\n\n @return The approval flag.\n */\n function _isApproved(uint256 _projectId, JBFundingCycle memory _fundingCycle)\n private\n view\n returns (bool)\n {\n return\n _ballotStateOf(\n _projectId,\n _fundingCycle.configuration,\n _fundingCycle.start,\n _fundingCycle.basedOn\n ) == JBBallotState.Approved;\n }\n\n /**\n @notice \n A project's latest funding cycle configuration approval status.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n @param _configuration The funding cycle configuration to get the ballot state of.\n @param _start The start time of the funding cycle configuration to get the ballot state of.\n @param _ballotFundingCycleConfiguration The configuration of the funding cycle which is configured with the ballot that should be used.\n\n @return The ballot state of the project.\n */\n function _ballotStateOf(\n uint256 _projectId,\n uint256 _configuration,\n uint256 _start,\n uint256 _ballotFundingCycleConfiguration\n ) private view returns (JBBallotState) {\n // If there is no ballot funding cycle, implicitly approve.\n if (_ballotFundingCycleConfiguration == 0) return JBBallotState.Approved;\n\n // Get the ballot funding cycle.\n JBFundingCycle memory _ballotFundingCycle = _getStructFor(\n _projectId,\n _ballotFundingCycleConfiguration\n );\n\n // If there is no ballot, the ID is auto approved.\n // Otherwise if the ballot's duration hasn't passed, its still active.\n // Otherwise, return the ballot's state.\n if (_ballotFundingCycle.ballot == IJBFundingCycleBallot(address(0)))\n return JBBallotState.Approved;\n else if (_ballotFundingCycle.ballot.duration() >= block.timestamp - _configuration)\n return JBBallotState.Active;\n else return _ballotFundingCycle.ballot.stateOf(_projectId, _configuration, _start);\n }\n\n /**\n @notice \n Unpack a funding cycle's packed stored values into an easy-to-work-with funding cycle struct.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n @param _configuration The funding cycle configuration to get the full struct for.\n\n @return fundingCycle A funding cycle struct.\n */\n function _getStructFor(uint256 _projectId, uint256 _configuration)\n private\n view\n returns (JBFundingCycle memory fundingCycle)\n {\n // Return an empty funding cycle if the configuration specified is 0.\n if (_configuration == 0) return fundingCycle;\n\n fundingCycle.configuration = _configuration;\n\n uint256 _packedIntrinsicProperties = _packedIntrinsicPropertiesOf[_projectId][_configuration];\n\n // weight in bits 0-87 bits.\n fundingCycle.weight = uint256(uint88(_packedIntrinsicProperties));\n // basedOn in bits 88-143 bits.\n fundingCycle.basedOn = uint256(uint56(_packedIntrinsicProperties >> 88));\n // start in bits 144-199 bits.\n fundingCycle.start = uint256(uint56(_packedIntrinsicProperties >> 144));\n // number in bits 200-255 bits.\n fundingCycle.number = uint256(uint56(_packedIntrinsicProperties >> 200));\n\n uint256 _packedUserProperties = _packedUserPropertiesOf[_projectId][_configuration];\n\n // ballot in bits 0-159 bits.\n fundingCycle.ballot = IJBFundingCycleBallot(address(uint160(_packedUserProperties)));\n // duration in bits 160-223 bits.\n fundingCycle.duration = uint256(uint64(_packedUserProperties >> 160));\n // discountRate in bits 224-255 bits.\n fundingCycle.discountRate = uint256(uint32(_packedUserProperties >> 224));\n\n fundingCycle.metadata = _metadataOf[_projectId][_configuration];\n }\n}\n" @@ -170,7 +170,7 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './../interfaces/IJBSplitAllocator.sol';\n\n/** \n @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.\n @member preferAddToBalance A flag indicating if a distribution to a project should prefer triggering it's addToBalance function instead of its pay function.\n @member percent The percent of the whole group that this split occupies. This number is out of `JBConstants.SPLITS_TOTAL_PERCENT`.\n @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.\n @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.\n @member lockedUntil Specifies if the split should be unchangeable until the specified time, with the exception of extending the locked period.\n @member allocator If an allocator is specified, funds will be sent to the allocator contract along with all properties of this split.\n*/\nstruct JBSplit {\n bool preferClaimed;\n bool preferAddToBalance;\n uint256 percent;\n uint256 projectId;\n address payable beneficiary;\n uint256 lockedUntil;\n IJBSplitAllocator allocator;\n}\n" }, "contracts/system_tests/helpers/AccessJBLib.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '../../libraries/JBCurrencies.sol';\nimport '../../libraries/JBConstants.sol';\nimport '../../libraries/JBTokens.sol';\n\ncontract AccessJBLib {\n function ETH() external pure returns (uint256) {\n return JBCurrencies.ETH;\n }\n\n function USD() external pure returns (uint256) {\n return JBCurrencies.USD;\n }\n\n function ETHToken() external pure returns (address) {\n return JBTokens.ETH;\n }\n\n function MAX_FEE() external pure returns (uint256) {\n return JBConstants.MAX_FEE;\n }\n\n function MAX_RESERVED_RATE() external pure returns (uint256) {\n return JBConstants.MAX_RESERVED_RATE;\n }\n\n function MAX_REDEMPTION_RATE() external pure returns (uint256) {\n return JBConstants.MAX_REDEMPTION_RATE;\n }\n\n function MAX_DISCOUNT_RATE() external pure returns (uint256) {\n return JBConstants.MAX_DISCOUNT_RATE;\n }\n\n function SPLITS_TOTAL_PERCENT() external pure returns (uint256) {\n return JBConstants.SPLITS_TOTAL_PERCENT;\n }\n\n function MAX_FEE_DISCOUNT() external pure returns (uint256) {\n return JBConstants.MAX_FEE_DISCOUNT;\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '../../libraries/JBCurrencies.sol';\nimport '../../libraries/JBConstants.sol';\nimport '../../libraries/JBTokens.sol';\n\ncontract AccessJBLib {\n function ETH() external pure returns (uint256) {\n return JBCurrencies.GAS_CURRENCY;\n }\n\n function USD() external pure returns (uint256) {\n return JBCurrencies.USD;\n }\n\n function ETHToken() external pure returns (address) {\n return JBTokens.GAS_TOKEN;\n }\n\n function MAX_FEE() external pure returns (uint256) {\n return JBConstants.MAX_FEE;\n }\n\n function MAX_RESERVED_RATE() external pure returns (uint256) {\n return JBConstants.MAX_RESERVED_RATE;\n }\n\n function MAX_REDEMPTION_RATE() external pure returns (uint256) {\n return JBConstants.MAX_REDEMPTION_RATE;\n }\n\n function MAX_DISCOUNT_RATE() external pure returns (uint256) {\n return JBConstants.MAX_DISCOUNT_RATE;\n }\n\n function SPLITS_TOTAL_PERCENT() external pure returns (uint256) {\n return JBConstants.SPLITS_TOTAL_PERCENT;\n }\n\n function MAX_FEE_DISCOUNT() external pure returns (uint256) {\n return JBConstants.MAX_FEE_DISCOUNT;\n }\n}\n" }, "@paulrberg/contracts/math/PRBMath.sol": { "content": "// SPDX-License-Identifier: Unlicense\npragma solidity >=0.8.4;\n\nimport \"prb-math/contracts/PRBMath.sol\";\n" @@ -227,7 +227,7 @@ "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" }, "contracts/abstract/JBPayoutRedemptionPaymentTerminal/1.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../../interfaces/IJBController/1.sol';\nimport './../../interfaces/IJBPayoutRedemptionPaymentTerminal/1.sol';\nimport './../../libraries/JBConstants.sol';\nimport './../../libraries/JBCurrencies.sol';\nimport './../../libraries/JBFixedPointNumber.sol';\nimport './../../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../../libraries/JBOperations.sol';\nimport './../../libraries/JBSplitsGroups.sol';\nimport './../../libraries/JBTokens.sol';\nimport './../../structs/JBTokenAmount.sol';\nimport './../JBOperatable.sol';\nimport './../JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal is\n IJBPayoutRedemptionPaymentTerminal,\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n ReentrancyGuard\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- private stored constants -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 private constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The protocol project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 private constant _PROTOCOL_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- private stored properties ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) private _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId) external view override returns (uint256) {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.ETH)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.ETH, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n ) JBSingleTokenPaymentTerminal(_token, _decimals, _currency) JBOperatable(_operatorStore) {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.ETH) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Process each fee.\n for (uint256 _i = 0; _i < _heldFees.length; _i++) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @dev\n If the fee gauge reverts when called upon while a project is attempting to distribute its funds, a project's funds will be locked. This is a known risk.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual;\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual;\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) private returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegate` only used within scope.\n {\n IJBRedemptionDelegate _delegate;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegate, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If a delegate was returned by the data source, issue a callback to it.\n if (_delegate != IJBRedemptionDelegate(address(0))) {\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _beneficiary,\n _memo,\n _metadata\n );\n _delegate.didRedeem(_data);\n emit DelegateDidRedeem(_delegate, _data, msg.sender);\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) private returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convinience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n\n // Take the fee.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || _feeEligibleDistributionAmount == 0\n ? 0\n : _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n );\n\n // Get a reference to how much to distribute to the project owner, which is the leftover amount minus any fees.\n netLeftoverDistributionAmount = _leftoverDistributionAmount == 0\n ? 0\n : _leftoverDistributionAmount - _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n\n // Transfer any remaining balance to the project owner.\n if (netLeftoverDistributionAmount > 0)\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n ) private returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convinience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) private returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i = 0; _i < _splits.length; _i++) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount;\n\n if (_payoutAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (isFeelessAddress[address(_split.allocator)])\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _netPayoutAmount : 0;\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n _netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // Save gas if this contract is being used as the terminal.\n if (_terminal == this) {\n // This distribution does not incur a fee.\n _netPayoutAmount = _payoutAmount;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\n else\n _pay(\n _netPayoutAmount,\n address(this),\n _split.projectId,\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n } else {\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (isFeelessAddress[address(_terminal)])\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _netPayoutAmount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _terminal.addToBalanceOf{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n '',\n _projectMetadata\n );\n else\n _terminal.pay{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n }\n } else {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(\n address(this),\n _split.beneficiary != address(0) ? _split.beneficiary : payable(msg.sender),\n _netPayoutAmount\n );\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _netPayoutAmount,\n msg.sender\n );\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _PROTOCOL_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) private returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n */\n function _processFee(uint256 _amount, address _beneficiary) private {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_PROTOCOL_PROJECT_ID, token);\n\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\n if (_terminal == this)\n _pay(_amount, address(this), _PROTOCOL_PROJECT_ID, _beneficiary, 0, false, '', bytes('')); // Use the local pay call.\n else {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _amount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _amount : 0;\n\n // Send the payment.\n _terminal.pay{value: _payableValue}(\n _PROTOCOL_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the external pay call of the correct terminal.\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) private returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegate` and `_tokenCount` only used within scope.\n {\n IJBPayDelegate _delegate;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegate, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If a delegate was returned by the data source, issue a callback to it.\n if (_delegate != IJBPayDelegate(address(0))) {\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n _delegate.didPay(_data);\n emit DelegateDidPay(_delegate, _data, msg.sender);\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) private {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n private\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Process each fee.\n for (uint256 _i = 0; _i < _heldFees.length; _i++) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n } else {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n leftoverAmount = 0;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) private pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) private view returns (uint256 feeDiscount) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (directory.primaryTerminalOf(_PROTOCOL_PROJECT_ID, token) == IJBPaymentTerminal(address(0)))\n return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge == IJBFeeGauge(address(0)))\n feeDiscount = 0;\n // If the guage reverts, set the discount to 0.\n else\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n feeDiscount = discount;\n } catch {\n feeDiscount = 0;\n }\n\n // If the fee discount is greater than the max, nullify the discount.\n if (feeDiscount > JBConstants.MAX_FEE_DISCOUNT) feeDiscount = 0;\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../../interfaces/IJBController/1.sol';\nimport './../../interfaces/IJBPayoutRedemptionPaymentTerminal/1.sol';\nimport './../../libraries/JBConstants.sol';\nimport './../../libraries/JBCurrencies.sol';\nimport './../../libraries/JBFixedPointNumber.sol';\nimport './../../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../../libraries/JBOperations.sol';\nimport './../../libraries/JBSplitsGroups.sol';\nimport './../../libraries/JBTokens.sol';\nimport './../../structs/JBTokenAmount.sol';\nimport './../JBOperatable.sol';\nimport './../JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal is\n IJBPayoutRedemptionPaymentTerminal,\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n ReentrancyGuard\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- private stored constants -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 private constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The protocol project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 private constant _PROTOCOL_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- private stored properties ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) private _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId) external view override returns (uint256) {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.GAS_CURRENCY)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.GAS_CURRENCY, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n ) JBSingleTokenPaymentTerminal(_token, _decimals, _currency) JBOperatable(_operatorStore) {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.GAS_TOKEN) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Process each fee.\n for (uint256 _i = 0; _i < _heldFees.length; _i++) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @dev\n If the fee gauge reverts when called upon while a project is attempting to distribute its funds, a project's funds will be locked. This is a known risk.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual;\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual;\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) private returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegate` only used within scope.\n {\n IJBRedemptionDelegate _delegate;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegate, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If a delegate was returned by the data source, issue a callback to it.\n if (_delegate != IJBRedemptionDelegate(address(0))) {\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _beneficiary,\n _memo,\n _metadata\n );\n _delegate.didRedeem(_data);\n emit DelegateDidRedeem(_delegate, _data, msg.sender);\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) private returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convinience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n\n // Take the fee.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || _feeEligibleDistributionAmount == 0\n ? 0\n : _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n );\n\n // Get a reference to how much to distribute to the project owner, which is the leftover amount minus any fees.\n netLeftoverDistributionAmount = _leftoverDistributionAmount == 0\n ? 0\n : _leftoverDistributionAmount - _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n\n // Transfer any remaining balance to the project owner.\n if (netLeftoverDistributionAmount > 0)\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n ) private returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convinience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) private returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i = 0; _i < _splits.length; _i++) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount;\n\n if (_payoutAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (isFeelessAddress[address(_split.allocator)])\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0;\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n _netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // Save gas if this contract is being used as the terminal.\n if (_terminal == this) {\n // This distribution does not incur a fee.\n _netPayoutAmount = _payoutAmount;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\n else\n _pay(\n _netPayoutAmount,\n address(this),\n _split.projectId,\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n } else {\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (isFeelessAddress[address(_terminal)])\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _terminal.addToBalanceOf{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n '',\n _projectMetadata\n );\n else\n _terminal.pay{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n }\n } else {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(\n address(this),\n _split.beneficiary != address(0) ? _split.beneficiary : payable(msg.sender),\n _netPayoutAmount\n );\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _netPayoutAmount,\n msg.sender\n );\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _PROTOCOL_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) private returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n */\n function _processFee(uint256 _amount, address _beneficiary) private {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_PROTOCOL_PROJECT_ID, token);\n\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\n if (_terminal == this)\n _pay(_amount, address(this), _PROTOCOL_PROJECT_ID, _beneficiary, 0, false, '', bytes('')); // Use the local pay call.\n else {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _amount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send the payment.\n _terminal.pay{value: _payableValue}(\n _PROTOCOL_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the external pay call of the correct terminal.\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) private returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegate` and `_tokenCount` only used within scope.\n {\n IJBPayDelegate _delegate;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegate, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If a delegate was returned by the data source, issue a callback to it.\n if (_delegate != IJBPayDelegate(address(0))) {\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n _delegate.didPay(_data);\n emit DelegateDidPay(_delegate, _data, msg.sender);\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) private {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n private\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Process each fee.\n for (uint256 _i = 0; _i < _heldFees.length; _i++) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n } else {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n leftoverAmount = 0;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) private pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) private view returns (uint256 feeDiscount) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (directory.primaryTerminalOf(_PROTOCOL_PROJECT_ID, token) == IJBPaymentTerminal(address(0)))\n return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge == IJBFeeGauge(address(0)))\n feeDiscount = 0;\n // If the guage reverts, set the discount to 0.\n else\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n feeDiscount = discount;\n } catch {\n feeDiscount = 0;\n }\n\n // If the fee discount is greater than the max, nullify the discount.\n if (feeDiscount > JBConstants.MAX_FEE_DISCOUNT) feeDiscount = 0;\n }\n}\n" }, "@openzeppelin/contracts/security/ReentrancyGuard.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n constructor() {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n // On the first call to nonReentrant, _notEntered will be true\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n\n _;\n\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n}\n" @@ -311,25 +311,25 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './IJBFundingCycleBallot.sol';\n\ninterface IJBReconfigurationBufferBallot is IJBFundingCycleBallot {\n event Finalize(\n uint256 indexed projectId,\n uint256 indexed configuration,\n JBBallotState indexed ballotState,\n address caller\n );\n\n function finalState(uint256 _projectId, uint256 _configuration)\n external\n view\n returns (JBBallotState);\n\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\n\n function finalize(uint256 _projectId, uint256 _configured) external returns (JBBallotState);\n}\n" }, "contracts/system_tests/TestEIP165.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './helpers/TestBaseWorkflow.sol';\nimport '../JBReconfigurationBufferBallot.sol';\nimport '../JBETHERC20SplitsPayer/1.sol';\n\ncontract TestEIP165 is TestBaseWorkflow {\n bytes4 constant notSupportedInterface = 0xffffffff;\n\n uint256 constant projectId = 2;\n uint256 constant splitsProjectID = 3;\n address payable constant splitsBeneficiary = payable(address(420));\n uint256 constant splitsDomain = 1;\n uint256 constant splitsGroup = 1;\n bool constant splitsPreferClaimedTokens = false;\n string constant splitsMemo = '';\n bytes constant splitsMetadata = '';\n bool constant splitsPreferAddToBalance = true;\n address constant splitsOwner = address(420);\n\n function testJBController() public {\n JBController controller = jbController();\n\n // Should support these interfaces\n assertTrue(controller.supportsInterface(type(IERC165).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBController).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBMigratable).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!controller.supportsInterface(notSupportedInterface));\n }\n\n function testJBERC20PaymentTerminal() public {\n JBERC20PaymentTerminal terminal = new JBERC20PaymentTerminal(\n jbToken(),\n jbLibraries().USD(), // currency\n jbLibraries().ETH(), // base weight currency\n 1, // JBSplitsGroupe\n jbOperatorStore(),\n jbProjects(),\n jbDirectory(),\n jbSplitsStore(),\n jbPrices(),\n jbPaymentTerminalStore(),\n multisig()\n );\n\n // Should support these interfaces\n assertTrue(terminal.supportsInterface(type(IERC165).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBRedemptionTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBSingleTokenPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!terminal.supportsInterface(notSupportedInterface));\n }\n\n function testJBETHPaymentTerminal() public {\n JBETHPaymentTerminal terminal = jbETHPaymentTerminal();\n\n // Should support these interfaces\n assertTrue(terminal.supportsInterface(type(IERC165).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBRedemptionTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBSingleTokenPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!terminal.supportsInterface(notSupportedInterface));\n }\n\n function testJBProjects() public {\n JBProjects projects = jbProjects();\n\n // Should support these interfaces\n assertTrue(projects.supportsInterface(type(IERC165).interfaceId));\n assertTrue(projects.supportsInterface(type(IERC721).interfaceId));\n assertTrue(projects.supportsInterface(type(IERC721Metadata).interfaceId));\n assertTrue(projects.supportsInterface(type(IJBProjects).interfaceId));\n assertTrue(projects.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!projects.supportsInterface(notSupportedInterface));\n }\n\n function testJBReconfigurationBufferBallot() public {\n JBReconfigurationBufferBallot ballot = new JBReconfigurationBufferBallot(\n 3000,\n jbFundingCycleStore()\n );\n\n // Should support these interfaces\n assertTrue(ballot.supportsInterface(type(IERC165).interfaceId));\n assertTrue(ballot.supportsInterface(type(IJBReconfigurationBufferBallot).interfaceId));\n assertTrue(ballot.supportsInterface(type(IJBFundingCycleBallot).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!ballot.supportsInterface(notSupportedInterface));\n }\n\n function testJBETHERC20SplitsPayer() public {\n JBETHERC20SplitsPayer splitsPayer = new JBETHERC20SplitsPayer(\n splitsProjectID,\n splitsDomain,\n splitsGroup,\n jbSplitsStore(),\n projectId,\n splitsBeneficiary,\n splitsPreferClaimedTokens,\n splitsMemo,\n splitsMetadata,\n splitsPreferAddToBalance,\n splitsOwner\n );\n\n // Should support these interfaces\n assertTrue(splitsPayer.supportsInterface(type(IERC165).interfaceId));\n assertTrue(splitsPayer.supportsInterface(type(IJBSplitsPayer).interfaceId));\n assertTrue(splitsPayer.supportsInterface(type(IJBProjectPayer).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!splitsPayer.supportsInterface(notSupportedInterface));\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './helpers/TestBaseWorkflow.sol';\nimport '../JBReconfigurationBufferBallot.sol';\nimport '../JBGasTokenERC20SplitsPayer/1.sol';\n\ncontract TestEIP165 is TestBaseWorkflow {\n bytes4 constant notSupportedInterface = 0xffffffff;\n\n uint256 constant projectId = 2;\n uint256 constant splitsProjectID = 3;\n address payable constant splitsBeneficiary = payable(address(420));\n uint256 constant splitsDomain = 1;\n uint256 constant splitsGroup = 1;\n bool constant splitsPreferClaimedTokens = false;\n string constant splitsMemo = '';\n bytes constant splitsMetadata = '';\n bool constant splitsPreferAddToBalance = true;\n address constant splitsOwner = address(420);\n\n function testJBController() public {\n JBController controller = jbController();\n\n // Should support these interfaces\n assertTrue(controller.supportsInterface(type(IERC165).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBController).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBMigratable).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!controller.supportsInterface(notSupportedInterface));\n }\n\n function testJBERC20PaymentTerminal() public {\n JBERC20PaymentTerminal terminal = new JBERC20PaymentTerminal(\n jbToken(),\n jbLibraries().USD(), // currency\n jbLibraries().ETH(), // base weight currency\n 1, // JBSplitsGroupe\n jbOperatorStore(),\n jbProjects(),\n jbDirectory(),\n jbSplitsStore(),\n jbPrices(),\n jbPaymentTerminalStore(),\n multisig()\n );\n\n // Should support these interfaces\n assertTrue(terminal.supportsInterface(type(IERC165).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBRedemptionTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBSingleTokenPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!terminal.supportsInterface(notSupportedInterface));\n }\n\n function testJBETHPaymentTerminal() public {\n JBETHPaymentTerminal terminal = jbETHPaymentTerminal();\n\n // Should support these interfaces\n assertTrue(terminal.supportsInterface(type(IERC165).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBRedemptionTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBSingleTokenPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!terminal.supportsInterface(notSupportedInterface));\n }\n\n function testJBProjects() public {\n JBProjects projects = jbProjects();\n\n // Should support these interfaces\n assertTrue(projects.supportsInterface(type(IERC165).interfaceId));\n assertTrue(projects.supportsInterface(type(IERC721).interfaceId));\n assertTrue(projects.supportsInterface(type(IERC721Metadata).interfaceId));\n assertTrue(projects.supportsInterface(type(IJBProjects).interfaceId));\n assertTrue(projects.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!projects.supportsInterface(notSupportedInterface));\n }\n\n function testJBReconfigurationBufferBallot() public {\n JBReconfigurationBufferBallot ballot = new JBReconfigurationBufferBallot(\n 3000,\n jbFundingCycleStore()\n );\n\n // Should support these interfaces\n assertTrue(ballot.supportsInterface(type(IERC165).interfaceId));\n assertTrue(ballot.supportsInterface(type(IJBReconfigurationBufferBallot).interfaceId));\n assertTrue(ballot.supportsInterface(type(IJBFundingCycleBallot).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!ballot.supportsInterface(notSupportedInterface));\n }\n\n function testJBGasTokenERC20SplitsPayer() public {\n JBGasTokenERC20SplitsPayer splitsPayer = new JBGasTokenERC20SplitsPayer(\n splitsProjectID,\n splitsDomain,\n splitsGroup,\n jbSplitsStore(),\n projectId,\n splitsBeneficiary,\n splitsPreferClaimedTokens,\n splitsMemo,\n splitsMetadata,\n splitsPreferAddToBalance,\n splitsOwner\n );\n\n // Should support these interfaces\n assertTrue(splitsPayer.supportsInterface(type(IERC165).interfaceId));\n assertTrue(splitsPayer.supportsInterface(type(IJBSplitsPayer).interfaceId));\n assertTrue(splitsPayer.supportsInterface(type(IJBProjectPayer).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!splitsPayer.supportsInterface(notSupportedInterface));\n }\n}\n" }, - "contracts/JBETHERC20SplitsPayer/1.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBSplitsPayer/1.sol';\nimport './../interfaces/IJBSplitsStore/1.sol';\nimport './../libraries/JBConstants.sol';\nimport './../JBETHERC20ProjectPayer.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\n\n @dev\n Adheres to -\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBETHERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBETHERC20SplitsPayer is IJBSplitsPayer, JBETHERC20ProjectPayer, ReentrancyGuard {\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The ID of project for which the default splits are stored. \n */\n uint256 public override defaultSplitsProjectId;\n\n /**\n @notice\n The domain within which the default splits are stored. \n */\n uint256 public override defaultSplitsDomain;\n\n /**\n @notice\n The group within which the default splits are stored. \n */\n uint256 public override defaultSplitsGroup;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBETHERC20ProjectPayer, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n )\n JBETHERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _preferAddToBalance,\n _splitsStore.directory(),\n _owner\n )\n {\n defaultSplitsProjectId = _defaultSplitsProjectId;\n defaultSplitsDomain = _defaultSplitsDomain;\n defaultSplitsGroup = _defaultSplitsGroup;\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default split group using the stored default properties.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override nonReentrant {\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n JBTokens.ETH,\n address(this).balance,\n 18 // decimals.\n );\n\n // If there is no leftover amount, nothing left to pay.\n if (_leftoverAmount == 0) return;\n\n // If there's a default project ID, try to pay it.\n if (defaultProjectId != 0)\n if (defaultPreferAddToBalance)\n // Pay the project by adding to its balance if prefered.\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.ETH,\n _leftoverAmount,\n 18, // decimals.\n defaultMemo,\n defaultMetadata\n );\n // Otherwise, issue a payment to the project.\n else\n _pay(\n defaultProjectId,\n JBTokens.ETH,\n _leftoverAmount,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n 0, // min returned tokens.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n // If no project was specified, send the funds directly to the beneficiary or the msg.sender.\n else\n Address.sendValue(\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(msg.sender),\n _leftoverAmount\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the location of the splits that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n */\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) external virtual override onlyOwner {\n // Set the default splits project ID if it's changing.\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\n\n // Set the default splits domain if it's changing.\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\n\n // Set the default splits group if it's changing.\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\n\n emit SetDefaultSplits(_projectId, _domain, _group, msg.sender);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals\n );\n\n // Pay any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to pay it.\n if (_projectId != 0) {\n _pay(\n _projectId,\n _token,\n _leftoverAmount,\n _decimals,\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n // If no project was specified, send the funds directly to the beneficiary or the msg.sender.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _beneficiary != address(0) ? payable(_beneficiary) : payable(msg.sender),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).transfer(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _leftoverAmount\n );\n }\n }\n\n emit Pay(\n _projectId,\n _beneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event. \n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals\n );\n\n // Distribute any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to add to its balance.\n if (_projectId != 0)\n // Add to the project's balance.\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\n\n // Otherwise, send a payment to the beneficiary.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(msg.sender),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).transfer(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _leftoverAmount\n );\n }\n }\n\n emit AddToBalance(\n _projectId,\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splitsProjectId The ID of the project to which the splits belong.\n @param _splitsDomain The splits domain to which the group belongs.\n @param _splitsGroup The splits group to pay.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payToSplits(\n uint256 _splitsProjectId,\n uint256 _splitsDomain,\n uint256 _splitsGroup,\n address _token,\n uint256 _amount,\n uint256 _decimals\n ) internal virtual returns (uint256 leftoverAmount) {\n // Get a reference to the splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup);\n\n // Set the leftover amount to the initial balance.\n leftoverAmount = _amount;\n\n // Settle between all splits.\n for (uint256 i = 0; i < _splits.length; i++) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[i];\n\n // The amount to send towards the split.\n uint256 _splitAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n if (_splitAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n _token,\n _splitAmount,\n _decimals,\n defaultProjectId,\n 0,\n _split\n );\n\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\n if (_token != JBTokens.ETH)\n IERC20(_token).approve(address(_split.allocator), _splitAmount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _splitAmount : 0;\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n if (_split.preferAddToBalance)\n _addToBalanceOf(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n defaultMemo,\n defaultMetadata\n );\n } else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _split.beneficiary != address(0) ? _split.beneficiary : payable(msg.sender),\n _splitAmount\n );\n // Or, transfer the ERC20.\n else {\n IERC20(_token).transfer(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n _splitAmount\n );\n }\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _splitAmount;\n }\n\n emit DistributeToSplit(\n _splitsProjectId,\n _splitsDomain,\n _splitsGroup,\n _split,\n _splitAmount,\n msg.sender\n );\n }\n }\n}\n" + "contracts/JBGasTokenERC20SplitsPayer/1.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBSplitsPayer/1.sol';\nimport './../interfaces/IJBSplitsStore/1.sol';\nimport './../libraries/JBConstants.sol';\nimport './../JBGasTokenERC20ProjectPayer.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\n\n @dev\n Adheres to -\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBGasTokenERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBGasTokenERC20SplitsPayer is IJBSplitsPayer, JBGasTokenERC20ProjectPayer, ReentrancyGuard {\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The ID of project for which the default splits are stored. \n */\n uint256 public override defaultSplitsProjectId;\n\n /**\n @notice\n The domain within which the default splits are stored. \n */\n uint256 public override defaultSplitsDomain;\n\n /**\n @notice\n The group within which the default splits are stored. \n */\n uint256 public override defaultSplitsGroup;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBGasTokenERC20ProjectPayer, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n )\n JBGasTokenERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _preferAddToBalance,\n _splitsStore.directory(),\n _owner\n )\n {\n defaultSplitsProjectId = _defaultSplitsProjectId;\n defaultSplitsDomain = _defaultSplitsDomain;\n defaultSplitsGroup = _defaultSplitsGroup;\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default split group using the stored default properties.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override nonReentrant {\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18 // decimals.\n );\n\n // If there is no leftover amount, nothing left to pay.\n if (_leftoverAmount == 0) return;\n\n // If there's a default project ID, try to pay it.\n if (defaultProjectId != 0)\n if (defaultPreferAddToBalance)\n // Pay the project by adding to its balance if prefered.\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n _leftoverAmount,\n 18, // decimals.\n defaultMemo,\n defaultMetadata\n );\n // Otherwise, issue a payment to the project.\n else\n _pay(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n _leftoverAmount,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n 0, // min returned tokens.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n // If no project was specified, send the funds directly to the beneficiary or the msg.sender.\n else\n Address.sendValue(\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(msg.sender),\n _leftoverAmount\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the location of the splits that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n */\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) external virtual override onlyOwner {\n // Set the default splits project ID if it's changing.\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\n\n // Set the default splits domain if it's changing.\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\n\n // Set the default splits group if it's changing.\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\n\n emit SetDefaultSplits(_projectId, _domain, _group, msg.sender);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals\n );\n\n // Pay any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to pay it.\n if (_projectId != 0) {\n _pay(\n _projectId,\n _token,\n _leftoverAmount,\n _decimals,\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n // If no project was specified, send the funds directly to the beneficiary or the msg.sender.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _beneficiary != address(0) ? payable(_beneficiary) : payable(msg.sender),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).transfer(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _leftoverAmount\n );\n }\n }\n\n emit Pay(\n _projectId,\n _beneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event. \n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals\n );\n\n // Distribute any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to add to its balance.\n if (_projectId != 0)\n // Add to the project's balance.\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\n\n // Otherwise, send a payment to the beneficiary.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(msg.sender),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).transfer(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _leftoverAmount\n );\n }\n }\n\n emit AddToBalance(\n _projectId,\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splitsProjectId The ID of the project to which the splits belong.\n @param _splitsDomain The splits domain to which the group belongs.\n @param _splitsGroup The splits group to pay.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payToSplits(\n uint256 _splitsProjectId,\n uint256 _splitsDomain,\n uint256 _splitsGroup,\n address _token,\n uint256 _amount,\n uint256 _decimals\n ) internal virtual returns (uint256 leftoverAmount) {\n // Get a reference to the splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup);\n\n // Set the leftover amount to the initial balance.\n leftoverAmount = _amount;\n\n // Settle between all splits.\n for (uint256 i = 0; i < _splits.length; i++) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[i];\n\n // The amount to send towards the split.\n uint256 _splitAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n if (_splitAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n _token,\n _splitAmount,\n _decimals,\n defaultProjectId,\n 0,\n _split\n );\n\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN)\n IERC20(_token).approve(address(_split.allocator), _splitAmount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _splitAmount : 0;\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n if (_split.preferAddToBalance)\n _addToBalanceOf(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n defaultMemo,\n defaultMetadata\n );\n } else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _split.beneficiary != address(0) ? _split.beneficiary : payable(msg.sender),\n _splitAmount\n );\n // Or, transfer the ERC20.\n else {\n IERC20(_token).transfer(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n _splitAmount\n );\n }\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _splitAmount;\n }\n\n emit DistributeToSplit(\n _splitsProjectId,\n _splitsDomain,\n _splitsGroup,\n _split,\n _splitAmount,\n msg.sender\n );\n }\n }\n}\n" }, "contracts/interfaces/IJBSplitsPayer/1.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './../../structs/JBSplit.sol';\nimport './../IJBSplitsStore/1.sol';\n\ninterface IJBSplitsPayer is IERC165 {\n event SetDefaultSplits(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n address caller\n );\n event Pay(\n uint256 indexed projectId,\n address beneficiary,\n address token,\n uint256 amount,\n uint256 decimals,\n uint256 leftoverAmount,\n uint256 minReturnedTokens,\n bool preferClaimedTokens,\n string memo,\n bytes metadata,\n address caller\n );\n\n event AddToBalance(\n uint256 indexed projectId,\n address beneficiary,\n address token,\n uint256 amount,\n uint256 decimals,\n uint256 leftoverAmount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DistributeToSplit(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n JBSplit split,\n uint256 amount,\n address caller\n );\n\n function defaultSplitsProjectId() external view returns (uint256);\n\n function defaultSplitsDomain() external view returns (uint256);\n\n function defaultSplitsGroup() external view returns (uint256);\n\n function splitsStore() external view returns (IJBSplitsStore);\n\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) external;\n}\n" }, - "contracts/JBETHERC20ProjectPayer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport './interfaces/IJBProjectPayer.sol';\nimport './libraries/JBTokens.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ERC165: Introspection on interface adherance. \n*/\ncontract JBETHERC20ProjectPayer is IJBProjectPayer, Ownable, ERC165 {\n //*********************************************************************//\n // -------------------------- custom errors -------------------------- //\n //*********************************************************************//\n error INCORRECT_DECIMAL_AMOUNT();\n error NO_MSG_VALUE_ALLOWED();\n error TERMINAL_NOT_FOUND();\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice \n A contract storing directories of terminals and controllers for each project.\n */\n IJBDirectory public immutable override directory;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The ID of the project that should be used to forward this contract's received payments.\n */\n uint256 public override defaultProjectId;\n\n /** \n @notice \n The beneficiary that should be used in the payment made when this contract receives payments.\n */\n address payable public override defaultBeneficiary;\n\n /** \n @notice \n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\n */\n bool public override defaultPreferClaimedTokens;\n\n /** \n @notice \n The memo that should be used in the payment made when this contract receives payments.\n */\n string public override defaultMemo;\n\n /** \n @notice \n The metadata that should be used in the payment made when this contract receives payments.\n */\n bytes public override defaultMetadata;\n\n /**\n @notice \n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n bool public override defaultPreferAddToBalance;\n\n //*********************************************************************//\n // ------------------------- public views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) {\n defaultProjectId = _defaultProjectId;\n defaultBeneficiary = _defaultBeneficiary;\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\n defaultMemo = _defaultMemo;\n defaultMetadata = _defaultMetadata;\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n directory = _directory;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default project ID using the stored default properties.\n\n @dev\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override {\n if (defaultPreferAddToBalance)\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.ETH,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n defaultProjectId,\n JBTokens.ETH,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultBeneficiary == address(0) ? msg.sender : defaultBeneficiary,\n 0, // Can't determine expectation of returned tokens ahead of time.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\n\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _beneficiary The address that'll receive the project's tokens. \n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _memo The memo that'll be used. \n @param _metadata The metadata that'll be sent. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external virtual override onlyOwner {\n // Set the default project ID if it has changed.\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\n\n // Set the default beneficiary if it has changed.\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\n\n // Set the default claimed token preference if it has changed.\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\n defaultPreferClaimedTokens = _preferClaimedTokens;\n\n // Set the default memo if it has changed.\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\n defaultMemo = _memo;\n\n // Set the default metadata if it has changed.\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\n defaultMetadata = _metadata;\n\n // Set the add to balance preference if it has changed.\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n\n emit SetDefaultValues(\n _projectId,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata,\n _defaultPreferAddToBalance,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _pay(\n _projectId,\n _token,\n _amount,\n _decimals,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. \n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source and delegate, if provided.\n */\n function _pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.ETH) IERC20(_token).approve(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\n\n // Send funds to the terminal.\n // If the token is ETH, send it in msg.value.\n _terminal.pay{value: _payableValue}(\n _projectId,\n _amount, // ignored if the token is JBTokens.ETH.\n _token,\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.ETH) IERC20(_token).approve(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\n\n // Add to balance so tokens don't get issued.\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\n }\n}\n" + "contracts/JBGasTokenERC20ProjectPayer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport './interfaces/IJBProjectPayer.sol';\nimport './libraries/JBTokens.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ERC165: Introspection on interface adherance. \n*/\ncontract JBGasTokenERC20ProjectPayer is IJBProjectPayer, Ownable, ERC165 {\n //*********************************************************************//\n // -------------------------- custom errors -------------------------- //\n //*********************************************************************//\n error INCORRECT_DECIMAL_AMOUNT();\n error NO_MSG_VALUE_ALLOWED();\n error TERMINAL_NOT_FOUND();\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice \n A contract storing directories of terminals and controllers for each project.\n */\n IJBDirectory public immutable override directory;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The ID of the project that should be used to forward this contract's received payments.\n */\n uint256 public override defaultProjectId;\n\n /** \n @notice \n The beneficiary that should be used in the payment made when this contract receives payments.\n */\n address payable public override defaultBeneficiary;\n\n /** \n @notice \n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\n */\n bool public override defaultPreferClaimedTokens;\n\n /** \n @notice \n The memo that should be used in the payment made when this contract receives payments.\n */\n string public override defaultMemo;\n\n /** \n @notice \n The metadata that should be used in the payment made when this contract receives payments.\n */\n bytes public override defaultMetadata;\n\n /**\n @notice \n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n bool public override defaultPreferAddToBalance;\n\n //*********************************************************************//\n // ------------------------- public views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) {\n defaultProjectId = _defaultProjectId;\n defaultBeneficiary = _defaultBeneficiary;\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\n defaultMemo = _defaultMemo;\n defaultMetadata = _defaultMetadata;\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n directory = _directory;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default project ID using the stored default properties.\n\n @dev\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override {\n if (defaultPreferAddToBalance)\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultBeneficiary == address(0) ? msg.sender : defaultBeneficiary,\n 0, // Can't determine expectation of returned tokens ahead of time.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\n\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _beneficiary The address that'll receive the project's tokens. \n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _memo The memo that'll be used. \n @param _metadata The metadata that'll be sent. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external virtual override onlyOwner {\n // Set the default project ID if it has changed.\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\n\n // Set the default beneficiary if it has changed.\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\n\n // Set the default claimed token preference if it has changed.\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\n defaultPreferClaimedTokens = _preferClaimedTokens;\n\n // Set the default memo if it has changed.\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\n defaultMemo = _memo;\n\n // Set the default metadata if it has changed.\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\n defaultMetadata = _metadata;\n\n // Set the add to balance preference if it has changed.\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n\n emit SetDefaultValues(\n _projectId,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata,\n _defaultPreferAddToBalance,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _pay(\n _projectId,\n _token,\n _amount,\n _decimals,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. \n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source and delegate, if provided.\n */\n function _pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).approve(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send funds to the terminal.\n // If the token is ETH, send it in msg.value.\n _terminal.pay{value: _payableValue}(\n _projectId,\n _amount, // ignored if the token is JBTokens.GAS_TOKEN.\n _token,\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).approve(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Add to balance so tokens don't get issued.\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\n }\n}\n" }, "contracts/interfaces/IJBProjectPayer.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './IJBDirectory.sol';\n\ninterface IJBProjectPayer is IERC165 {\n event SetDefaultValues(\n uint256 indexed projectId,\n address indexed beneficiary,\n bool preferClaimedTokens,\n string memo,\n bytes metadata,\n bool preferAddToBalance,\n address caller\n );\n\n function directory() external view returns (IJBDirectory);\n\n function defaultProjectId() external view returns (uint256);\n\n function defaultBeneficiary() external view returns (address payable);\n\n function defaultPreferClaimedTokens() external view returns (bool);\n\n function defaultMemo() external view returns (string memory);\n\n function defaultMetadata() external view returns (bytes memory);\n\n function defaultPreferAddToBalance() external view returns (bool);\n\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external;\n\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) external payable;\n\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) external payable;\n\n receive() external payable;\n}\n" }, - "contracts/JBETHERC20SplitsPayerDeployer/1.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './../interfaces/IJBETHERC20SplitsPayerDeployer/1.sol';\nimport './../JBETHERC20SplitsPayer/1.sol';\n\n/** \n @notice \n Deploys splits payer contracts.\n\n @dev\n Adheres to -\n IJBETHERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBETHERC20SplitsPayerDeployer is IJBETHERC20SplitsPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBSplitsPayer splitsPayer) {\n // Deploy the splits payer.\n splitsPayer = new JBETHERC20SplitsPayer(\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeploySplitsPayer(\n splitsPayer,\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner,\n msg.sender\n );\n }\n}\n" + "contracts/JBGasTokenERC20SplitsPayerDeployer/1.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './../interfaces/IJBGasTokenERC20SplitsPayerDeployer/1.sol';\nimport './../JBGasTokenERC20SplitsPayer/1.sol';\n\n/** \n @notice \n Deploys splits payer contracts.\n\n @dev\n Adheres to -\n IJBGasTokenERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBGasTokenERC20SplitsPayerDeployer is IJBGasTokenERC20SplitsPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBSplitsPayer splitsPayer) {\n // Deploy the splits payer.\n splitsPayer = new JBGasTokenERC20SplitsPayer(\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeploySplitsPayer(\n splitsPayer,\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner,\n msg.sender\n );\n }\n}\n" }, - "contracts/interfaces/IJBETHERC20SplitsPayerDeployer/1.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './../IJBSplitsPayer/1.sol';\nimport './../IJBSplitsStore/1.sol';\n\ninterface IJBETHERC20SplitsPayerDeployer {\n event DeploySplitsPayer(\n IJBSplitsPayer indexed splitsPayer,\n uint256 defaultSplitsProjectId,\n uint256 defaultSplitsDomain,\n uint256 defaultSplitsGroup,\n IJBSplitsStore splitsStore,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n address owner,\n address caller\n );\n\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string calldata _defaultMemo,\n bytes calldata _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n}\n" + "contracts/interfaces/IJBGasTokenERC20SplitsPayerDeployer/1.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './../IJBSplitsPayer/1.sol';\nimport './../IJBSplitsStore/1.sol';\n\ninterface IJBGasTokenERC20SplitsPayerDeployer {\n event DeploySplitsPayer(\n IJBSplitsPayer indexed splitsPayer,\n uint256 defaultSplitsProjectId,\n uint256 defaultSplitsDomain,\n uint256 defaultSplitsGroup,\n IJBSplitsStore splitsStore,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n address owner,\n address caller\n );\n\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string calldata _defaultMemo,\n bytes calldata _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n}\n" }, "contracts/JBSplitsStore/2.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './../abstract/JBOperatable.sol';\nimport './../interfaces/IJBDirectory.sol';\nimport './../interfaces/IJBSplitsStore/2.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBOperations.sol';\n\n/**\n @notice\n Stores splits for each project.\n\n @dev\n Adheres to -\n IJBSplitsStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\ncontract JBSplitsStore is IJBSplitsStore, JBOperatable {\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_LOCKED_UNTIL();\n error INVALID_PROJECT_ID();\n error INVALID_SPLIT_PERCENT();\n error INVALID_TOTAL_PERCENT();\n error PREVIOUS_LOCKED_SPLITS_NOT_INCLUDED();\n\n //*********************************************************************//\n // --------------------- private stored properties ------------------- //\n //*********************************************************************//\n\n /** \n @notice\n The number of splits currently set for each project ID's configurations.\n\n _projectId The ID of the project to get the split count for.\n _domain An identifier within which the returned splits should be considered active.\n _group The identifying group of the splits.\n */\n mapping(uint256 => mapping(uint256 => mapping(uint256 => uint256))) private _splitCountOf;\n\n /** \n @notice\n Packed data of splits for each project ID's configurations.\n\n _projectId The ID of the project to get packed splits data for.\n _domain An identifier within which the returned splits should be considered active.\n _group The identifying group of the splits.\n _index The indexed order that the split was set at.\n */\n mapping(uint256 => mapping(uint256 => mapping(uint256 => mapping(uint256 => uint256))))\n private _packedSplitParts1Of;\n\n /** \n @notice\n More packed data of splits for each project ID's configurations.\n\n @dev\n This packed data is often 0.\n\n _projectId The ID of the project to get packed splits data for.\n _domain An identifier within which the returned splits should be considered active.\n _group The identifying group of the splits.\n _index The indexed order that the split was set at.\n */\n mapping(uint256 => mapping(uint256 => mapping(uint256 => mapping(uint256 => uint256))))\n private _packedSplitParts2Of;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /** \n @notice \n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /** \n @notice \n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice \n Get all splits for the specified project ID, within the specified domain, for the specified group.\n\n @param _projectId The ID of the project to get splits for.\n @param _domain An identifier within which the returned splits should be considered active.\n @param _group The identifying group of the splits.\n\n @return An array of all splits for the project.\n*/\n function splitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) external view override returns (JBSplit[] memory) {\n return _getStructsFor(_projectId, _domain, _group);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n */\n constructor(\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory\n ) JBOperatable(_operatorStore) {\n projects = _projects;\n directory = _directory;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets a project's splits.\n\n @dev\n Only the owner or operator of a project, or the current controller contract of the project, can set its splits.\n\n @dev\n The new splits must include any currently set splits that are locked.\n\n @param _projectId The ID of the project for which splits are being added.\n @param _domain An identifier within which the splits should be considered active.\n @param _groupedSplits An array of splits to set for any number of groups. \n */\n function set(\n uint256 _projectId,\n uint256 _domain,\n JBGroupedSplits[] calldata _groupedSplits\n )\n external\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.SET_SPLITS,\n address(directory.controllerOf(_projectId)) == msg.sender\n )\n {\n // Push array length in stack\n uint256 _groupedSplitsLength = _groupedSplits.length;\n\n // Set each grouped splits.\n for (uint256 _i = 0; _i < _groupedSplitsLength; ) {\n // Get a reference to the grouped split being iterated on.\n JBGroupedSplits memory _groupedSplit = _groupedSplits[_i];\n\n // Set the splits for the group.\n _set(_projectId, _domain, _groupedSplit.group, _groupedSplit.splits);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets a project's splits.\n\n @dev\n The new splits must include any currently set splits that are locked.\n\n @param _projectId The ID of the project for which splits are being added.\n @param _domain An identifier within which the splits should be considered active.\n @param _group An identifier between of splits being set. All splits within this _group must add up to within 100%.\n @param _splits The splits to set.\n */\n function _set(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n JBSplit[] memory _splits\n ) internal {\n // Get a reference to the project's current splits.\n JBSplit[] memory _currentSplits = _getStructsFor(_projectId, _domain, _group);\n\n // Check to see if all locked splits are included.\n for (uint256 _i = 0; _i < _currentSplits.length; _i++) {\n // If not locked, continue.\n if (block.timestamp >= _currentSplits[_i].lockedUntil) continue;\n\n // Keep a reference to whether or not the locked split being iterated on is included.\n bool _includesLocked = false;\n\n for (uint256 _j = 0; _j < _splits.length; _j++) {\n // Check for sameness.\n if (\n _splits[_j].percent == _currentSplits[_i].percent &&\n _splits[_j].beneficiary == _currentSplits[_i].beneficiary &&\n _splits[_j].allocator == _currentSplits[_i].allocator &&\n _splits[_j].projectId == _currentSplits[_i].projectId &&\n // Allow lock extention.\n _splits[_j].lockedUntil >= _currentSplits[_i].lockedUntil\n ) _includesLocked = true;\n }\n\n if (!_includesLocked) revert PREVIOUS_LOCKED_SPLITS_NOT_INCLUDED();\n }\n\n // Add up all the percents to make sure they cumulative are under 100%.\n uint256 _percentTotal = 0;\n\n for (uint256 _i = 0; _i < _splits.length; _i++) {\n // The percent should be greater than 0.\n if (_splits[_i].percent == 0) revert INVALID_SPLIT_PERCENT();\n\n // ProjectId should be within a uint56\n if (_splits[_i].projectId > type(uint56).max) revert INVALID_PROJECT_ID();\n\n // Add to the total percents.\n _percentTotal = _percentTotal + _splits[_i].percent;\n\n // Validate the total does not exceed the expected value.\n if (_percentTotal > JBConstants.SPLITS_TOTAL_PERCENT) revert INVALID_TOTAL_PERCENT();\n\n uint256 _packedSplitParts1;\n\n // prefer claimed in bit 0.\n if (_splits[_i].preferClaimed) _packedSplitParts1 = 1;\n // prefer add to balance in bit 1.\n if (_splits[_i].preferAddToBalance) _packedSplitParts1 |= 1 << 1;\n // percent in bits 2-33.\n _packedSplitParts1 |= _splits[_i].percent << 2;\n // projectId in bits 32-89.\n _packedSplitParts1 |= _splits[_i].projectId << 34;\n // beneficiary in bits 90-249.\n _packedSplitParts1 |= uint256(uint160(address(_splits[_i].beneficiary))) << 90;\n\n // Store the first spit part.\n _packedSplitParts1Of[_projectId][_domain][_group][_i] = _packedSplitParts1;\n\n // If there's data to store in the second packed split part, pack and store.\n if (_splits[_i].lockedUntil > 0 || _splits[_i].allocator != IJBSplitAllocator(address(0))) {\n // Locked until should be within a uint48\n if (_splits[_i].lockedUntil > type(uint48).max) revert INVALID_LOCKED_UNTIL();\n\n // lockedUntil in bits 0-47.\n uint256 _packedSplitParts2 = uint48(_splits[_i].lockedUntil);\n // allocator in bits 48-207.\n _packedSplitParts2 |= uint256(uint160(address(_splits[_i].allocator))) << 48;\n\n // Store the second split part.\n _packedSplitParts2Of[_projectId][_domain][_group][_i] = _packedSplitParts2;\n\n // Otherwise if there's a value stored in the indexed position, delete it.\n } else if (_packedSplitParts2Of[_projectId][_domain][_group][_i] > 0)\n delete _packedSplitParts2Of[_projectId][_domain][_group][_i];\n\n emit SetSplit(_projectId, _domain, _group, _splits[_i], msg.sender);\n }\n\n // Set the new length of the splits.\n _splitCountOf[_projectId][_domain][_group] = _splits.length;\n }\n\n /**\n @notice \n Unpack splits' packed stored values into easy-to-work-with spit structs.\n\n @param _projectId The ID of the project to which the split belongs.\n @param _domain The identifier within which the returned splits should be considered active.\n @param _group The identifying group of the splits.\n\n @return splits The split structs.\n */\n function _getStructsFor(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) private view returns (JBSplit[] memory) {\n // Get a reference to the number of splits that need to be added to the returned array.\n uint256 _splitCount = _splitCountOf[_projectId][_domain][_group];\n\n // Initialize an array to be returned that has the set length.\n JBSplit[] memory _splits = new JBSplit[](_splitCount);\n\n // Loop through each split and unpack the values into structs.\n for (uint256 _i = 0; _i < _splitCount; _i++) {\n // Get a reference to the fist packed data.\n uint256 _packedSplitPart1 = _packedSplitParts1Of[_projectId][_domain][_group][_i];\n\n // Populate the split struct.\n JBSplit memory _split;\n\n // prefer claimed in bit 0.\n _split.preferClaimed = _packedSplitPart1 & 1 == 1;\n // prefer add to balance in bit 1.\n _split.preferAddToBalance = (_packedSplitPart1 >> 1) & 1 == 1;\n // percent in bits 2-33.\n _split.percent = uint256(uint32(_packedSplitPart1 >> 2));\n // projectId in bits 32-89.\n _split.projectId = uint256(uint56(_packedSplitPart1 >> 34));\n // beneficiary in bits 90-249.\n _split.beneficiary = payable(address(uint160(_packedSplitPart1 >> 90)));\n\n // Get a reference to the second packed data.\n uint256 _packedSplitPart2 = _packedSplitParts2Of[_projectId][_domain][_group][_i];\n\n // If there's anything in it, unpack.\n if (_packedSplitPart2 > 0) {\n // lockedUntil in bits 0-47.\n _split.lockedUntil = uint256(uint48(_packedSplitPart2));\n // allocator in bits 48-207.\n _split.allocator = IJBSplitAllocator(address(uint160(_packedSplitPart2 >> 48)));\n }\n\n // Add the split to the value being returned.\n _splits[_i] = _split;\n }\n\n return _splits;\n }\n}\n" @@ -344,13 +344,13 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../abstract/JBOperatable.sol';\nimport './../interfaces/IJBController/2.sol';\nimport './../interfaces/IJBMigratable.sol';\nimport './../interfaces/IJBOperatorStore.sol';\nimport './../interfaces/IJBPaymentTerminal.sol';\nimport './../interfaces/IJBProjects.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBSplitsGroups.sol';\n\n/**\n @notice\n Stitches together funding cycles and community tokens, making sure all activity is accounted for and correct.\n\n @dev\n Adheres to -\n IJBController: General interface for the generic controller methods in this contract that interacts with funding cycles and tokens according to the protocol's rules.\n IJBMigratable: Allows migrating to this contract, with a hook called to prepare for the migration.\n\n @dev\n Inherits from -\n JBOperatable: Several functions in this contract can only be accessed by a project owner, or an address that has been preconfifigured to be an operator of the project.\n ERC165: Introspection on interface adherance. \n*/\ncontract JBController is IJBController, IJBMigratable, JBOperatable, ERC165 {\n // A library that parses the packed funding cycle metadata into a more friendly format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error BURN_PAUSED_AND_SENDER_NOT_VALID_TERMINAL_DELEGATE();\n error CANT_MIGRATE_TO_CURRENT_CONTROLLER();\n error CHANGE_TOKEN_NOT_ALLOWED();\n error FUNDING_CYCLE_ALREADY_LAUNCHED();\n error INVALID_BALLOT_REDEMPTION_RATE();\n error INVALID_DISTRIBUTION_LIMIT();\n error INVALID_DISTRIBUTION_LIMIT_CURRENCY();\n error INVALID_OVERFLOW_ALLOWANCE();\n error INVALID_OVERFLOW_ALLOWANCE_CURRENCY();\n error INVALID_REDEMPTION_RATE();\n error INVALID_RESERVED_RATE();\n error MIGRATION_NOT_ALLOWED();\n error MINT_NOT_ALLOWED_AND_NOT_TERMINAL_DELEGATE();\n error NO_BURNABLE_TOKENS();\n error NOT_CURRENT_CONTROLLER();\n error ZERO_TOKENS_TO_MINT();\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n The difference between the processed token tracker of a project and the project's token's total supply is the amount of tokens that still need to have reserves minted against them.\n\n _projectId The ID of the project to get the tracker of.\n */\n mapping(uint256 => int256) internal _processedTokenTrackerOf;\n\n /**\n @notice\n Data regarding the distribution limit of a project during a configuration.\n\n @dev\n bits 0-231: The amount of token that a project can distribute per funding cycle.\n\n @dev\n bits 232-255: The currency of amount that a project can distribute.\n\n _projectId The ID of the project to get the packed distribution limit data of.\n _configuration The configuration during which the packed distribution limit data applies.\n _terminal The terminal from which distributions are being limited.\n _token The token for which distributions are being limited.\n */\n mapping(uint256 => mapping(uint256 => mapping(IJBPaymentTerminal => mapping(address => uint256))))\n internal _packedDistributionLimitDataOf;\n\n /**\n @notice\n Data regarding the overflow allowance of a project during a configuration.\n\n @dev\n bits 0-231: The amount of overflow that a project is allowed to tap into on-demand throughout the configuration.\n\n @dev\n bits 232-255: The currency of the amount of overflow that a project is allowed to tap.\n\n _projectId The ID of the project to get the packed overflow allowance data of.\n _configuration The configuration during which the packed overflow allowance data applies.\n _terminal The terminal managing the overflow.\n _token The token for which overflow is being allowed.\n */\n mapping(uint256 => mapping(uint256 => mapping(IJBPaymentTerminal => mapping(address => uint256))))\n internal _packedOverflowAllowanceDataOf;\n\n //*********************************************************************//\n // --------------- public immutable stored properties ---------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that manages token minting and burning.\n */\n IJBTokenStore public immutable override tokenStore;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of token that a project can distribute per funding cycle, and the currency it's in terms of.\n\n @dev\n The number of decimals in the returned fixed point amount is the same as that of the specified terminal. \n\n @param _projectId The ID of the project to get the distribution limit of.\n @param _configuration The configuration during which the distribution limit applies.\n @param _terminal The terminal from which distributions are being limited.\n @param _token The token for which the distribution limit applies.\n\n @return The distribution limit, as a fixed point number with the same number of decimals as the provided terminal.\n @return The currency of the distribution limit.\n */\n function distributionLimitOf(\n uint256 _projectId,\n uint256 _configuration,\n IJBPaymentTerminal _terminal,\n address _token\n ) external view override returns (uint256, uint256) {\n // Get a reference to the packed data.\n uint256 _data = _packedDistributionLimitDataOf[_projectId][_configuration][_terminal][_token];\n\n // The limit is in bits 0-231. The currency is in bits 232-255.\n return (uint256(uint232(_data)), _data >> 232);\n }\n\n /**\n @notice\n The amount of overflow that a project is allowed to tap into on-demand throughout a configuration, and the currency it's in terms of.\n\n @dev\n The number of decimals in the returned fixed point amount is the same as that of the specified terminal. \n\n @param _projectId The ID of the project to get the overflow allowance of.\n @param _configuration The configuration of the during which the allowance applies.\n @param _terminal The terminal managing the overflow.\n @param _token The token for which the overflow allowance applies.\n\n @return The overflow allowance, as a fixed point number with the same number of decimals as the provided terminal.\n @return The currency of the overflow allowance.\n */\n function overflowAllowanceOf(\n uint256 _projectId,\n uint256 _configuration,\n IJBPaymentTerminal _terminal,\n address _token\n ) external view override returns (uint256, uint256) {\n // Get a reference to the packed data.\n uint256 _data = _packedOverflowAllowanceDataOf[_projectId][_configuration][_terminal][_token];\n\n // The allowance is in bits 0-231. The currency is in bits 232-255.\n return (uint256(uint232(_data)), _data >> 232);\n }\n\n /**\n @notice\n Gets the amount of reserved tokens that a project has available to distribute.\n\n @param _projectId The ID of the project to get a reserved token balance of.\n @param _reservedRate The reserved rate to use when making the calculation.\n\n @return The current amount of reserved tokens.\n */\n function reservedTokenBalanceOf(uint256 _projectId, uint256 _reservedRate)\n external\n view\n override\n returns (uint256)\n {\n return\n _reservedTokenAmountFrom(\n _processedTokenTrackerOf[_projectId],\n _reservedRate,\n tokenStore.totalSupplyOf(_projectId)\n );\n }\n\n /**\n @notice\n Gets the current total amount of outstanding tokens for a project, given a reserved rate.\n\n @param _projectId The ID of the project to get total outstanding tokens of.\n @param _reservedRate The reserved rate to use when making the calculation.\n\n @return The current total amount of outstanding tokens for the project.\n */\n function totalOutstandingTokensOf(uint256 _projectId, uint256 _reservedRate)\n external\n view\n override\n returns (uint256)\n {\n // Get the total number of tokens in circulation.\n uint256 _totalSupply = tokenStore.totalSupplyOf(_projectId);\n\n // Get the number of reserved tokens the project has.\n uint256 _reservedTokenAmount = _reservedTokenAmountFrom(\n _processedTokenTrackerOf[_projectId],\n _reservedRate,\n _totalSupply\n );\n\n // Add the reserved tokens to the total supply.\n return _totalSupply + _reservedTokenAmount;\n }\n\n /** \n @notice\n A project's funding cycle for the specified configuration along with its metadata.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n \n @return fundingCycle The funding cycle.\n @return metadata The funding cycle's metadata.\n */\n function getFundingCycleOf(uint256 _projectId, uint256 _configuration)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata)\n {\n fundingCycle = fundingCycleStore.get(_projectId, _configuration);\n metadata = fundingCycle.expandMetadata();\n }\n\n /** \n @notice\n A project's latest configured funding cycle along with its metadata and the ballot state of the configuration.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n \n @return fundingCycle The latest configured funding cycle.\n @return metadata The latest configured funding cycle's metadata.\n @return ballotState The state of the configuration.\n */\n function latestConfiguredFundingCycleOf(uint256 _projectId)\n external\n view\n override\n returns (\n JBFundingCycle memory fundingCycle,\n JBFundingCycleMetadata memory metadata,\n JBBallotState ballotState\n )\n {\n (fundingCycle, ballotState) = fundingCycleStore.latestConfiguredOf(_projectId);\n metadata = fundingCycle.expandMetadata();\n }\n\n /** \n @notice\n A project's current funding cycle along with its metadata.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n \n @return fundingCycle The current funding cycle.\n @return metadata The current funding cycle's metadata.\n */\n function currentFundingCycleOf(uint256 _projectId)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata)\n {\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n metadata = fundingCycle.expandMetadata();\n }\n\n /** \n @notice\n A project's queued funding cycle along with its metadata.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n \n @return fundingCycle The queued funding cycle.\n @return metadata The queued funding cycle's metadata.\n */\n function queuedFundingCycleOf(uint256 _projectId)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata)\n {\n fundingCycle = fundingCycleStore.queuedOf(_projectId);\n metadata = fundingCycle.expandMetadata();\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBController).interfaceId ||\n _interfaceId == type(IJBMigratable).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // ---------------------------- constructor -------------------------- //\n //*********************************************************************//\n\n /**\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _tokenStore A contract that manages token minting and burning.\n @param _splitsStore A contract that stores splits for each project.\n */\n constructor(\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBTokenStore _tokenStore,\n IJBSplitsStore _splitsStore\n ) JBOperatable(_operatorStore) {\n projects = _projects;\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n tokenStore = _tokenStore;\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // --------------------- external transactions ----------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Creates a project. This will mint an ERC-721 into the specified owner's account, configure a first funding cycle, and set up any splits.\n\n @dev\n Each operation within this transaction can be done in sequence separately.\n\n @dev\n Anyone can deploy a project on an owner's behalf.\n\n @param _owner The address to set as the owner of the project. The project ERC-721 will be owned by this address.\n @param _projectMetadata Metadata to associate with the project within a particular domain. This can be updated any time by the owner of the project.\n @param _data Data that defines the project's first funding cycle. These properties will remain fixed for the duration of the funding cycle.\n @param _metadata Metadata specifying the controller specific params that a funding cycle can have. These properties will remain fixed for the duration of the funding cycle.\n @param _mustStartAtOrAfter The time before which the configured funding cycle cannot start.\n @param _groupedSplits An array of splits to set for any number of groups. \n @param _fundAccessConstraints An array containing amounts that a project can use from its treasury for each payment terminal. Amounts are fixed point numbers using the same number of decimals as the accompanying terminal. The `_distributionLimit` and `_overflowAllowance` parameters must fit in a `uint232`.\n @param _terminals Payment terminals to add for the project.\n @param _memo A memo to pass along to the emitted event.\n\n @return projectId The ID of the project.\n */\n function launchProjectFor(\n address _owner,\n JBProjectMetadata calldata _projectMetadata,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] calldata _groupedSplits,\n JBFundAccessConstraints[] calldata _fundAccessConstraints,\n IJBPaymentTerminal[] memory _terminals,\n string memory _memo\n ) external virtual override returns (uint256 projectId) {\n // Mint the project into the wallet of the message sender.\n projectId = projects.createFor(_owner, _projectMetadata);\n\n // Set this contract as the project's controller in the directory.\n directory.setControllerOf(projectId, address(this));\n\n // Configure the first funding cycle.\n uint256 _configuration = _configure(\n projectId,\n _data,\n _metadata,\n _mustStartAtOrAfter,\n _groupedSplits,\n _fundAccessConstraints\n );\n\n // Add the provided terminals to the list of terminals.\n if (_terminals.length > 0) directory.setTerminalsOf(projectId, _terminals);\n\n emit LaunchProject(_configuration, projectId, _memo, msg.sender);\n }\n\n /**\n @notice\n Creates a funding cycle for an already existing project ERC-721.\n\n @dev\n Each operation within this transaction can be done in sequence separately.\n\n @dev\n Only a project owner or operator can launch its funding cycles.\n\n @param _projectId The ID of the project to launch funding cycles for.\n @param _data Data that defines the project's first funding cycle. These properties will remain fixed for the duration of the funding cycle.\n @param _metadata Metadata specifying the controller specific params that a funding cycle can have. These properties will remain fixed for the duration of the funding cycle.\n @param _mustStartAtOrAfter The time before which the configured funding cycle cannot start.\n @param _groupedSplits An array of splits to set for any number of groups. \n @param _fundAccessConstraints An array containing amounts that a project can use from its treasury for each payment terminal. Amounts are fixed point numbers using the same number of decimals as the accompanying terminal. The `_distributionLimit` and `_overflowAllowance` parameters must fit in a `uint232`.\n @param _terminals Payment terminals to add for the project.\n @param _memo A memo to pass along to the emitted event.\n\n @return configuration The configuration of the funding cycle that was successfully created.\n */\n function launchFundingCyclesFor(\n uint256 _projectId,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] calldata _groupedSplits,\n JBFundAccessConstraints[] memory _fundAccessConstraints,\n IJBPaymentTerminal[] memory _terminals,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.RECONFIGURE)\n returns (uint256 configuration)\n {\n // If there is a previous configuration, reconfigureFundingCyclesOf should be called instead\n if (fundingCycleStore.latestConfigurationOf(_projectId) > 0)\n revert FUNDING_CYCLE_ALREADY_LAUNCHED();\n\n // Set this contract as the project's controller in the directory.\n directory.setControllerOf(_projectId, address(this));\n\n // Configure the first funding cycle.\n configuration = _configure(\n _projectId,\n _data,\n _metadata,\n _mustStartAtOrAfter,\n _groupedSplits,\n _fundAccessConstraints\n );\n\n // Add the provided terminals to the list of terminals.\n if (_terminals.length > 0) directory.setTerminalsOf(_projectId, _terminals);\n\n emit LaunchFundingCycles(configuration, _projectId, _memo, msg.sender);\n }\n\n /**\n @notice\n Proposes a configuration of a subsequent funding cycle that will take effect once the current one expires if it is approved by the current funding cycle's ballot.\n\n @dev\n Only a project's owner or a designated operator can configure its funding cycles.\n\n @param _projectId The ID of the project whose funding cycles are being reconfigured.\n @param _data Data that defines the funding cycle. These properties will remain fixed for the duration of the funding cycle.\n @param _metadata Metadata specifying the controller specific params that a funding cycle can have. These properties will remain fixed for the duration of the funding cycle.\n @param _mustStartAtOrAfter The time before which the configured funding cycle cannot start.\n @param _groupedSplits An array of splits to set for any number of groups. \n @param _fundAccessConstraints An array containing amounts that a project can use from its treasury for each payment terminal. Amounts are fixed point numbers using the same number of decimals as the accompanying terminal. The `_distributionLimit` and `_overflowAllowance` parameters must fit in a `uint232`.\n @param _memo A memo to pass along to the emitted event.\n\n @return configuration The configuration of the funding cycle that was successfully reconfigured.\n */\n function reconfigureFundingCyclesOf(\n uint256 _projectId,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] calldata _groupedSplits,\n JBFundAccessConstraints[] calldata _fundAccessConstraints,\n string calldata _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.RECONFIGURE)\n returns (uint256 configuration)\n {\n // Configure the next funding cycle.\n configuration = _configure(\n _projectId,\n _data,\n _metadata,\n _mustStartAtOrAfter,\n _groupedSplits,\n _fundAccessConstraints\n );\n\n emit ReconfigureFundingCycles(configuration, _projectId, _memo, msg.sender);\n }\n\n /**\n @notice\n Issues an owner's ERC20 JBTokens that'll be used when claiming tokens.\n\n @dev\n Deploys a project's ERC20 JBToken contract.\n\n @dev\n Only a project's owner or operator can issue its token.\n\n @param _projectId The ID of the project being issued tokens.\n @param _name The ERC20's name.\n @param _symbol The ERC20's symbol.\n */\n function issueTokenFor(\n uint256 _projectId,\n string calldata _name,\n string calldata _symbol\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.ISSUE)\n returns (IJBToken token)\n {\n // Issue the token in the store.\n return tokenStore.issueFor(_projectId, _name, _symbol);\n }\n\n /**\n @notice\n Swap the current project's token that is minted and burned for another, and transfer ownership of the current token to another address if needed.\n\n @dev\n Only a project's owner or operator can change its token.\n\n @param _projectId The ID of the project to which the changed token belongs.\n @param _token The new token.\n @param _newOwner An address to transfer the current token's ownership to. This is optional, but it cannot be done later.\n */\n function changeTokenOf(\n uint256 _projectId,\n IJBToken _token,\n address _newOwner\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.CHANGE_TOKEN)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (!_fundingCycle.changeTokenAllowed()) revert CHANGE_TOKEN_NOT_ALLOWED();\n\n // Change the token in the store.\n tokenStore.changeFor(_projectId, _token, _newOwner);\n }\n\n /**\n @notice\n Mint new token supply into an account, and optionally reserve a supply to be distributed according to the project's current funding cycle configuration.\n\n @dev\n Only a project's owner, a designated operator, one of its terminals, or the current data source can mint its tokens.\n\n @param _projectId The ID of the project to which the tokens being minted belong.\n @param _tokenCount The amount of tokens to mint in total, counting however many should be reserved.\n @param _beneficiary The account that the tokens are being minted for.\n @param _memo A memo to pass along to the emitted event.\n @param _preferClaimedTokens A flag indicating whether a project's attached token contract should be minted if they have been issued.\n @param _useReservedRate Whether to use the current funding cycle's reserved rate in the mint calculation.\n\n @return beneficiaryTokenCount The amount of tokens minted for the beneficiary.\n */\n function mintTokensOf(\n uint256 _projectId,\n uint256 _tokenCount,\n address _beneficiary,\n string calldata _memo,\n bool _preferClaimedTokens,\n bool _useReservedRate\n ) external virtual override returns (uint256 beneficiaryTokenCount) {\n // There should be tokens to mint.\n if (_tokenCount == 0) revert ZERO_TOKENS_TO_MINT();\n\n // Define variables that will be needed outside scoped section below.\n // Keep a reference to the reserved rate to use\n uint256 _reservedRate;\n\n // Scoped section prevents stack too deep. `_fundingCycle` only used within scope.\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Minting limited to: project owner, authorized callers, project terminal and current funding cycle data source\n _requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.MINT,\n directory.isTerminalOf(_projectId, IJBPaymentTerminal(msg.sender)) ||\n msg.sender == address(_fundingCycle.dataSource())\n );\n\n // If the message sender is not a terminal or a datasource, the current funding cycle must allow minting.\n if (\n !_fundingCycle.mintingAllowed() &&\n !directory.isTerminalOf(_projectId, IJBPaymentTerminal(msg.sender)) &&\n msg.sender != address(_fundingCycle.dataSource())\n ) revert MINT_NOT_ALLOWED_AND_NOT_TERMINAL_DELEGATE();\n\n // Determine the reserved rate to use.\n _reservedRate = _useReservedRate ? _fundingCycle.reservedRate() : 0;\n }\n\n if (_reservedRate == JBConstants.MAX_RESERVED_RATE)\n // Subtract the total weighted amount from the tracker so the full reserved token amount can be printed later.\n _processedTokenTrackerOf[_projectId] =\n _processedTokenTrackerOf[_projectId] -\n int256(_tokenCount);\n else {\n // The unreserved token count that will be minted for the beneficiary.\n beneficiaryTokenCount = PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_RESERVED_RATE - _reservedRate,\n JBConstants.MAX_RESERVED_RATE\n );\n\n if (_reservedRate == 0)\n // If there's no reserved rate, increment the tracker with the newly minted tokens.\n _processedTokenTrackerOf[_projectId] =\n _processedTokenTrackerOf[_projectId] +\n int256(beneficiaryTokenCount);\n\n // Mint the tokens.\n tokenStore.mintFor(_beneficiary, _projectId, beneficiaryTokenCount, _preferClaimedTokens);\n }\n\n emit MintTokens(\n _beneficiary,\n _projectId,\n _tokenCount,\n beneficiaryTokenCount,\n _memo,\n _reservedRate,\n msg.sender\n );\n }\n\n /**\n @notice\n Burns a token holder's supply.\n\n @dev\n Only a token's holder, a designated operator, or a project's terminal can burn it.\n\n @param _holder The account that is having its tokens burned.\n @param _projectId The ID of the project to which the tokens being burned belong.\n @param _tokenCount The number of tokens to burn.\n @param _memo A memo to pass along to the emitted event.\n @param _preferClaimedTokens A flag indicating whether a project's attached token contract should be burned first if they have been issued.\n */\n function burnTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string calldata _memo,\n bool _preferClaimedTokens\n )\n external\n virtual\n override\n requirePermissionAllowingOverride(\n _holder,\n _projectId,\n JBOperations.BURN,\n directory.isTerminalOf(_projectId, IJBPaymentTerminal(msg.sender))\n )\n {\n // There should be tokens to burn\n if (_tokenCount == 0) revert NO_BURNABLE_TOKENS();\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // If the message sender is not a terminal, the current funding cycle must not be paused.\n if (\n _fundingCycle.burnPaused() &&\n !directory.isTerminalOf(_projectId, IJBPaymentTerminal(msg.sender))\n ) revert BURN_PAUSED_AND_SENDER_NOT_VALID_TERMINAL_DELEGATE();\n\n // Update the token tracker so that reserved tokens will still be correctly mintable.\n _processedTokenTrackerOf[_projectId] =\n _processedTokenTrackerOf[_projectId] -\n int256(_tokenCount);\n\n // Burn the tokens.\n tokenStore.burnFrom(_holder, _projectId, _tokenCount, _preferClaimedTokens);\n\n emit BurnTokens(_holder, _projectId, _tokenCount, _memo, msg.sender);\n }\n\n /**\n @notice\n Distributes all outstanding reserved tokens for a project.\n\n @param _projectId The ID of the project to which the reserved tokens belong.\n @param _memo A memo to pass along to the emitted event.\n\n @return The amount of minted reserved tokens.\n */\n function distributeReservedTokensOf(uint256 _projectId, string calldata _memo)\n external\n virtual\n override\n returns (uint256)\n {\n return _distributeReservedTokensOf(_projectId, _memo);\n }\n\n /**\n @notice\n Allows other controllers to signal to this one that a migration is expected for the specified project.\n\n @dev\n This controller should not yet be the project's controller.\n\n @param _projectId The ID of the project that will be migrated to this controller.\n @param _from The controller being migrated from.\n */\n function prepForMigrationOf(uint256 _projectId, address _from) external virtual override {\n // This controller must not be the project's current controller.\n if (directory.controllerOf(_projectId) == address(this))\n revert CANT_MIGRATE_TO_CURRENT_CONTROLLER();\n\n // Set the tracker as the total supply.\n _processedTokenTrackerOf[_projectId] = int256(tokenStore.totalSupplyOf(_projectId));\n\n emit PrepMigration(_projectId, _from, msg.sender);\n }\n\n /**\n @notice\n Allows a project to migrate from this controller to another.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project that will be migrated from this controller.\n @param _to The controller to which the project is migrating.\n */\n function migrate(uint256 _projectId, IJBMigratable _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_CONTROLLER)\n {\n // This controller must be the project's current controller.\n if (directory.controllerOf(_projectId) != address(this)) revert NOT_CURRENT_CONTROLLER();\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.controllerMigrationAllowed()) revert MIGRATION_NOT_ALLOWED();\n\n // All reserved tokens must be minted before migrating.\n if (uint256(_processedTokenTrackerOf[_projectId]) != tokenStore.totalSupplyOf(_projectId))\n _distributeReservedTokensOf(_projectId, '');\n\n // Make sure the new controller is prepped for the migration.\n _to.prepForMigrationOf(_projectId, address(this));\n\n // Set the new controller.\n directory.setControllerOf(_projectId, address(_to));\n\n emit Migrate(_projectId, _to, msg.sender);\n }\n\n //*********************************************************************//\n // ------------------------ internal functions ----------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Distributes all outstanding reserved tokens for a project.\n\n @param _projectId The ID of the project to which the reserved tokens belong.\n @param _memo A memo to pass along to the emitted event.\n\n @return tokenCount The amount of minted reserved tokens.\n */\n function _distributeReservedTokensOf(uint256 _projectId, string memory _memo)\n internal\n returns (uint256 tokenCount)\n {\n // Get the current funding cycle to read the reserved rate from.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to new total supply of tokens before minting reserved tokens.\n uint256 _totalTokens = tokenStore.totalSupplyOf(_projectId);\n\n // Get a reference to the number of tokens that need to be minted.\n tokenCount = _reservedTokenAmountFrom(\n _processedTokenTrackerOf[_projectId],\n _fundingCycle.reservedRate(),\n _totalTokens\n );\n\n // Set the tracker to be the new total supply.\n _processedTokenTrackerOf[_projectId] = int256(_totalTokens + tokenCount);\n\n // Get a reference to the project owner.\n address _owner = projects.ownerOf(_projectId);\n\n // Distribute tokens to splits and get a reference to the leftover amount to mint after all splits have gotten their share.\n uint256 _leftoverTokenCount = tokenCount == 0\n ? 0\n : _distributeToReservedTokenSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n JBSplitsGroups.RESERVED_TOKENS,\n tokenCount\n );\n\n // Mint any leftover tokens to the project owner.\n if (_leftoverTokenCount > 0) tokenStore.mintFor(_owner, _projectId, _leftoverTokenCount, false);\n\n emit DistributeReservedTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _owner,\n tokenCount,\n _leftoverTokenCount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Distribute tokens to the splits according to the specified funding cycle configuration.\n\n @param _projectId The ID of the project for which reserved token splits are being distributed.\n @param _domain The domain of the splits to distribute the reserved tokens between.\n @param _group The group of the splits to distribute the reserved tokens between.\n @param _amount The total amount of tokens to mint.\n\n @return leftoverAmount If the splits percents dont add up to 100%, the leftover amount is returned.\n */\n function _distributeToReservedTokenSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount\n ) internal returns (uint256 leftoverAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n\n // Get a reference to the project's reserved token splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n //Transfer between all splits.\n for (uint256 _i = 0; _i < _splits.length; _i++) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _tokenCount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n // Mints tokens for the split if needed.\n if (_tokenCount > 0) {\n tokenStore.mintFor(\n // If an allocator is set in the splits, set it as the beneficiary.\n // Otherwise if a projectId is set in the split, set the project's owner as the beneficiary.\n // If the split has a beneficiary send to the split's beneficiary. Otherwise send to the msg.sender.\n _split.allocator != IJBSplitAllocator(address(0))\n ? address(_split.allocator)\n : _split.projectId != 0\n ? projects.ownerOf(_split.projectId)\n : _split.beneficiary != address(0)\n ? _split.beneficiary\n : msg.sender,\n _projectId,\n _tokenCount,\n _split.preferClaimed\n );\n\n // If there's an allocator set, trigger its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0)))\n _split.allocator.allocate(\n JBSplitAllocationData(\n address(tokenStore.tokenOf(_projectId)),\n _tokenCount,\n 18,\n _projectId,\n _group,\n _split\n )\n );\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _tokenCount;\n }\n\n emit DistributeToReservedTokenSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _tokenCount,\n msg.sender\n );\n }\n }\n\n /**\n @notice\n Configures a funding cycle and stores information pertinent to the configuration.\n\n @param _projectId The ID of the project whose funding cycles are being reconfigured.\n @param _data Data that defines the funding cycle. These properties will remain fixed for the duration of the funding cycle.\n @param _metadata Metadata specifying the controller specific params that a funding cycle can have. These properties will remain fixed for the duration of the funding cycle.\n @param _mustStartAtOrAfter The time before which the configured funding cycle cannot start.\n @param _groupedSplits An array of splits to set for any number of groups. \n @param _fundAccessConstraints An array containing amounts that a project can use from its treasury for each payment terminal. Amounts are fixed point numbers using the same number of decimals as the accompanying terminal.\n\n @return configuration The configuration of the funding cycle that was successfully reconfigured.\n */\n function _configure(\n uint256 _projectId,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] memory _groupedSplits,\n JBFundAccessConstraints[] memory _fundAccessConstraints\n ) internal returns (uint256) {\n // Make sure the provided reserved rate is valid.\n if (_metadata.reservedRate > JBConstants.MAX_RESERVED_RATE) revert INVALID_RESERVED_RATE();\n\n // Make sure the provided redemption rate is valid.\n if (_metadata.redemptionRate > JBConstants.MAX_REDEMPTION_RATE)\n revert INVALID_REDEMPTION_RATE();\n\n // Make sure the provided ballot redemption rate is valid.\n if (_metadata.ballotRedemptionRate > JBConstants.MAX_REDEMPTION_RATE)\n revert INVALID_BALLOT_REDEMPTION_RATE();\n\n // Configure the funding cycle's properties.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.configureFor(\n _projectId,\n _data,\n JBFundingCycleMetadataResolver.packFundingCycleMetadata(_metadata),\n _mustStartAtOrAfter\n );\n\n // Set splits for the group.\n splitsStore.set(_projectId, _fundingCycle.configuration, _groupedSplits);\n\n // Set distribution limits if there are any.\n for (uint256 _i; _i < _fundAccessConstraints.length; _i++) {\n JBFundAccessConstraints memory _constraints = _fundAccessConstraints[_i];\n\n // If distribution limit value is larger than 232 bits, revert.\n if (_constraints.distributionLimit > type(uint232).max) revert INVALID_DISTRIBUTION_LIMIT();\n\n // If distribution limit currency value is larger than 24 bits, revert.\n if (_constraints.distributionLimitCurrency > type(uint24).max)\n revert INVALID_DISTRIBUTION_LIMIT_CURRENCY();\n\n // If overflow allowance value is larger than 232 bits, revert.\n if (_constraints.overflowAllowance > type(uint232).max) revert INVALID_OVERFLOW_ALLOWANCE();\n\n // If overflow allowance currency value is larger than 24 bits, revert.\n if (_constraints.overflowAllowanceCurrency > type(uint24).max)\n revert INVALID_OVERFLOW_ALLOWANCE_CURRENCY();\n\n // Set the distribution limit if there is one.\n if (_constraints.distributionLimit > 0)\n _packedDistributionLimitDataOf[_projectId][_fundingCycle.configuration][\n _constraints.terminal\n ][_constraints.token] =\n _constraints.distributionLimit |\n (_constraints.distributionLimitCurrency << 232);\n\n // Set the overflow allowance if there is one.\n if (_constraints.overflowAllowance > 0)\n _packedOverflowAllowanceDataOf[_projectId][_fundingCycle.configuration][\n _constraints.terminal\n ][_constraints.token] =\n _constraints.overflowAllowance |\n (_constraints.overflowAllowanceCurrency << 232);\n\n emit SetFundAccessConstraints(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _constraints,\n msg.sender\n );\n }\n\n return _fundingCycle.configuration;\n }\n\n /**\n @notice\n Gets the amount of reserved tokens currently tracked for a project given a reserved rate.\n\n @param _processedTokenTracker The tracker to make the calculation with.\n @param _reservedRate The reserved rate to use to make the calculation.\n @param _totalEligibleTokens The total amount to make the calculation with.\n\n @return amount reserved token amount.\n */\n function _reservedTokenAmountFrom(\n int256 _processedTokenTracker,\n uint256 _reservedRate,\n uint256 _totalEligibleTokens\n ) internal pure returns (uint256) {\n // Get a reference to the amount of tokens that are unprocessed.\n uint256 _unprocessedTokenBalanceOf = _processedTokenTracker >= 0\n ? _totalEligibleTokens - uint256(_processedTokenTracker)\n : _totalEligibleTokens + uint256(-_processedTokenTracker);\n\n // If there are no unprocessed tokens, return.\n if (_unprocessedTokenBalanceOf == 0) return 0;\n\n // If all tokens are reserved, return the full unprocessed amount.\n if (_reservedRate == JBConstants.MAX_RESERVED_RATE) return _unprocessedTokenBalanceOf;\n\n return\n PRBMath.mulDiv(\n _unprocessedTokenBalanceOf,\n JBConstants.MAX_RESERVED_RATE,\n JBConstants.MAX_RESERVED_RATE - _reservedRate\n ) - _unprocessedTokenBalanceOf;\n }\n}\n" }, "contracts/JBETHPaymentTerminal/2.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './../abstract/JBPayoutRedemptionPaymentTerminal/2.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n JBTokens.ETH,\n 18, // 18 decimals.\n JBCurrencies.ETH,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal pure override {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './../abstract/JBPayoutRedemptionPaymentTerminal/2.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n JBTokens.GAS_TOKEN,\n 18, // 18 decimals.\n JBCurrencies.GAS_CURRENCY,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal pure override {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n}\n" }, "contracts/JBERC20PaymentTerminal/2.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol';\nimport './../abstract/JBPayoutRedemptionPaymentTerminal/2.sol';\n\n/** \n @notice \n Manages the inflows and outflows of an ERC-20 token.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\ncontract JBERC20PaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n IERC20Metadata _token,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n address(_token),\n _token.decimals(),\n _currency,\n _baseWeightCurrency,\n _payoutSplitsGroup,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from == address(this)\n ? IERC20(token).transfer(_to, _amount)\n : IERC20(token).transferFrom(_from, _to, _amount);\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal override {\n IERC20(token).approve(_to, _amount);\n }\n}\n" }, "contracts/JBSingleTokenPaymentTerminalStore/2.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController/2.sol';\nimport './../interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBSingleTokenPaymentTerminalStore is IJBSingleTokenPaymentTerminalStore, ReentrancyGuard {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n Mint's 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegate A delegate contract to use for subsequent calls.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n IJBPayDelegate delegate,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay()) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegate) = IJBFundingCycleDataSource(fundingCycle.dataSource()).payParams(\n _data\n );\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegate, memo);\n\n // Add the amount to the token balance of the project.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount.value;\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegate, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegate A delegate contract to use for subsequent calls.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n IJBRedemptionDelegate delegate,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\n _projectId,\n fundingCycle.reservedRate()\n );\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow > 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem()) {\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n fundingCycle.redemptionRate(),\n fundingCycle.ballotRedemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegate) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .redeemParams(_data);\n } else {\n memo = _memo;\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (reclaimAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (reclaimAmount > 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n reclaimAmount;\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n return _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i = 0; _i < _terminals.length; _i++)\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.ETH\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.ETH, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController/2.sol';\nimport './../interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBSingleTokenPaymentTerminalStore is IJBSingleTokenPaymentTerminalStore, ReentrancyGuard {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n Mint's 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegate A delegate contract to use for subsequent calls.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n IJBPayDelegate delegate,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay()) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegate) = IJBFundingCycleDataSource(fundingCycle.dataSource()).payParams(\n _data\n );\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegate, memo);\n\n // Add the amount to the token balance of the project.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount.value;\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegate, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegate A delegate contract to use for subsequent calls.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n IJBRedemptionDelegate delegate,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\n _projectId,\n fundingCycle.reservedRate()\n );\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow > 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem()) {\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n fundingCycle.redemptionRate(),\n fundingCycle.ballotRedemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegate) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .redeemParams(_data);\n } else {\n memo = _memo;\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (reclaimAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (reclaimAmount > 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n reclaimAmount;\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n return _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i = 0; _i < _terminals.length; _i++)\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.GAS_CURRENCY\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.GAS_CURRENCY, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" }, "contracts/JBFundingCycleStore/2.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../abstract/JBControllerUtility.sol';\nimport './../libraries/JBConstants.sol';\n\n/** \n @notice \n Manages funding cycle configurations and scheduling.\n\n @dev\n Adheres to -\n IJBTokenStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBControllerUtility: Includes convenience functionality for checking if the message sender is the current controller of the project whose data is being manipulated.\n*/\ncontract JBFundingCycleStore is IJBFundingCycleStore, JBControllerUtility {\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_DISCOUNT_RATE();\n error INVALID_DURATION();\n error INVALID_WEIGHT();\n error NO_SAME_BLOCK_RECONFIGURATION();\n\n //*********************************************************************//\n // --------------------- private stored properties ------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Stores the user defined properties of each funding cycle, packed into one storage slot.\n\n _projectId The ID of the project to get properties of.\n _configuration The funding cycle configuration to get properties of.\n */\n mapping(uint256 => mapping(uint256 => uint256)) private _packedUserPropertiesOf;\n\n /** \n @notice\n Stores the properties added by the mechanism to manage and schedule each funding cycle, packed into one storage slot.\n \n _projectId The ID of the project to get instrinsic properties of.\n _configuration The funding cycle configuration to get properties of.\n */\n mapping(uint256 => mapping(uint256 => uint256)) private _packedIntrinsicPropertiesOf;\n\n /** \n @notice\n Stores the metadata for each funding cycle configuration, packed into one storage slot.\n\n _projectId The ID of the project to get metadata of.\n _configuration The funding cycle configuration to get metadata of.\n */\n mapping(uint256 => mapping(uint256 => uint256)) private _metadataOf;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The latest funding cycle configuration for each project.\n\n _projectId The ID of the project to get the latest funding cycle configuration of.\n */\n mapping(uint256 => uint256) public override latestConfigurationOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice \n Get the funding cycle with the given configuration for the specified project.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n @param _configuration The configuration of the funding cycle to get.\n\n @return fundingCycle The funding cycle.\n */\n function get(uint256 _projectId, uint256 _configuration)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle)\n {\n return _getStructFor(_projectId, _configuration);\n }\n\n /**\n @notice \n The latest funding cycle to be configured for the specified project, and its current ballot state.\n\n @param _projectId The ID of the project to get the latest configured funding cycle of.\n\n @return fundingCycle The project's queued funding cycle.\n @return ballotState The state of the ballot for the reconfiguration.\n */\n function latestConfiguredOf(uint256 _projectId)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle, JBBallotState ballotState)\n {\n // Get a reference to the latest funding cycle configuration.\n uint256 _fundingCycleConfiguration = latestConfigurationOf[_projectId];\n\n // Resolve the funding cycle for the latest configuration.\n fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n // Resolve the ballot state.\n ballotState = _ballotStateOf(\n _projectId,\n fundingCycle.configuration,\n fundingCycle.start,\n fundingCycle.basedOn\n );\n }\n\n /**\n @notice \n The funding cycle that's next up for the specified project.\n\n @dev\n If a queued funding cycle of the project is not found, returns an empty funding cycle with all properties set to 0.\n\n @param _projectId The ID of the project to get the queued funding cycle of.\n\n @return fundingCycle The project's queued funding cycle.\n */\n function queuedOf(uint256 _projectId)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle)\n {\n // If the project does not have a funding cycle, return an empty struct.\n if (latestConfigurationOf[_projectId] == 0) return _getStructFor(0, 0);\n\n // Get a reference to the configuration of the standby funding cycle.\n uint256 _standbyFundingCycleConfiguration = _standbyOf(_projectId);\n\n // If it exists, return its funding cycle if it is approved.\n if (_standbyFundingCycleConfiguration > 0) {\n fundingCycle = _getStructFor(_projectId, _standbyFundingCycleConfiguration);\n\n if (_isApproved(_projectId, fundingCycle)) return fundingCycle;\n\n // Resolve the funding cycle for the latest configured funding cycle.\n fundingCycle = _getStructFor(_projectId, fundingCycle.basedOn);\n } else {\n // Resolve the funding cycle for the latest configured funding cycle.\n fundingCycle = _getStructFor(_projectId, latestConfigurationOf[_projectId]);\n\n // If the latest funding cycle starts in the future, it must start in the distant future\n // since its not in standby. In this case base the queued cycles on the base cycle.\n if (fundingCycle.start > block.timestamp)\n fundingCycle = _getStructFor(_projectId, fundingCycle.basedOn);\n }\n\n // There's no queued if the current has a duration of 0.\n if (fundingCycle.duration == 0) return _getStructFor(0, 0);\n\n // Check to see if this funding cycle's ballot is approved.\n // If so, return a funding cycle based on it.\n if (_isApproved(_projectId, fundingCycle)) return _mockFundingCycleBasedOn(fundingCycle, false);\n\n // Get the funding cycle of its base funding cycle, which carries the last approved configuration.\n fundingCycle = _getStructFor(_projectId, fundingCycle.basedOn);\n\n // There's no queued if the base, which must still be the current, has a duration of 0.\n if (fundingCycle.duration == 0) return _getStructFor(0, 0);\n\n // Return a mock of the next up funding cycle.\n return _mockFundingCycleBasedOn(fundingCycle, false);\n }\n\n /**\n @notice \n The funding cycle that is currently active for the specified project.\n\n @dev\n If a current funding cycle of the project is not found, returns an empty funding cycle with all properties set to 0.\n\n @param _projectId The ID of the project to get the current funding cycle of.\n\n @return fundingCycle The project's current funding cycle.\n */\n function currentOf(uint256 _projectId)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle)\n {\n // If the project does not have a funding cycle, return an empty struct.\n if (latestConfigurationOf[_projectId] == 0) return _getStructFor(0, 0);\n\n // Get a reference to the configuration of the eligible funding cycle.\n uint256 _fundingCycleConfiguration = _eligibleOf(_projectId);\n\n // Keep a reference to the eligible funding cycle.\n JBFundingCycle memory _fundingCycle;\n\n // If an eligible funding cycle exists...\n if (_fundingCycleConfiguration > 0) {\n // Resolve the funding cycle for the eligible configuration.\n _fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n // Check to see if this funding cycle's ballot is approved.\n // If so, return it.\n if (_isApproved(_projectId, _fundingCycle)) return _fundingCycle;\n\n // If it hasn't been approved, set the funding cycle configuration to be the configuration of the funding cycle that it's based on,\n // which carries the last approved configuration.\n _fundingCycleConfiguration = _fundingCycle.basedOn;\n } else {\n // No upcoming funding cycle found that is eligible to become active,\n // so use the last configuration.\n _fundingCycleConfiguration = latestConfigurationOf[_projectId];\n\n // Get the funding cycle for the latest ID.\n _fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n // If it's not approved or if it hasn't yet started, get a reference to the funding cycle that the latest is based on, which has the latest approved configuration.\n if (!_isApproved(_projectId, _fundingCycle) || block.timestamp < _fundingCycle.start)\n _fundingCycleConfiguration = _fundingCycle.basedOn;\n }\n\n // If there is not funding cycle to base the current one on, there can't be a current one.\n if (_fundingCycleConfiguration == 0) return _getStructFor(0, 0);\n\n // The funding cycle to base a current one on.\n _fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n // If the base has no duration, it's still the current one.\n if (_fundingCycle.duration == 0) return _fundingCycle;\n\n // Return a mock of the current funding cycle.\n return _mockFundingCycleBasedOn(_fundingCycle, true);\n }\n\n /** \n @notice \n The current ballot state of the project.\n\n @param _projectId The ID of the project to check the ballot state of.\n\n @return The project's current ballot's state.\n */\n function currentBallotStateOf(uint256 _projectId) external view override returns (JBBallotState) {\n // Get a reference to the latest funding cycle configuration.\n uint256 _fundingCycleConfiguration = latestConfigurationOf[_projectId];\n\n // Resolve the funding cycle for the latest configuration.\n JBFundingCycle memory _fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n return\n _ballotStateOf(\n _projectId,\n _fundingCycle.configuration,\n _fundingCycle.start,\n _fundingCycle.basedOn\n );\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _directory A contract storing directories of terminals and controllers for each project.\n */\n // solhint-disable-next-line no-empty-blocks\n constructor(IJBDirectory _directory) JBControllerUtility(_directory) {}\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice \n Configures the next eligible funding cycle for the specified project.\n\n @dev\n Only a project's current controller can configure its funding cycles.\n\n @param _projectId The ID of the project being configured.\n @param _data The funding cycle configuration data.\n @param _metadata Arbitrary extra data to associate with this funding cycle configuration that's not used within.\n @param _mustStartAtOrAfter The time before which the initialized funding cycle cannot start.\n\n @return The funding cycle that the configuration will take effect during.\n */\n function configureFor(\n uint256 _projectId,\n JBFundingCycleData calldata _data,\n uint256 _metadata,\n uint256 _mustStartAtOrAfter\n ) external override onlyController(_projectId) returns (JBFundingCycle memory) {\n // Duration must fit in a uint64.\n if (_data.duration > type(uint64).max) revert INVALID_DURATION();\n\n // Discount rate must be less than or equal to 100%.\n if (_data.discountRate > JBConstants.MAX_DISCOUNT_RATE) revert INVALID_DISCOUNT_RATE();\n\n // Weight must fit into a uint88.\n if (_data.weight > type(uint88).max) revert INVALID_WEIGHT();\n\n // The configuration timestamp is now.\n uint256 _configuration = block.timestamp;\n\n // Set up a reconfiguration by configuring intrinsic properties.\n _configureIntrinsicPropertiesFor(\n _projectId,\n _configuration,\n _data.weight,\n // Must start on or after the current timestamp.\n _mustStartAtOrAfter > block.timestamp ? _mustStartAtOrAfter : block.timestamp\n );\n\n // Efficiently stores a funding cycles provided user defined properties.\n // If all user config properties are zero, no need to store anything as the default value will have the same outcome.\n if (\n _data.ballot != IJBFundingCycleBallot(address(0)) ||\n _data.duration > 0 ||\n _data.discountRate > 0\n ) {\n // ballot in bits 0-159 bytes.\n uint256 packed = uint160(address(_data.ballot));\n\n // duration in bits 160-223 bytes.\n packed |= _data.duration << 160;\n\n // discountRate in bits 224-255 bytes.\n packed |= _data.discountRate << 224;\n\n // Set in storage.\n _packedUserPropertiesOf[_projectId][_configuration] = packed;\n }\n\n // Set the metadata if needed.\n if (_metadata > 0) _metadataOf[_projectId][_configuration] = _metadata;\n\n emit Configure(_configuration, _projectId, _data, _metadata, _mustStartAtOrAfter, msg.sender);\n\n // Return the funding cycle for the new configuration.\n return _getStructFor(_projectId, _configuration);\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice \n Updates the configurable funding cycle for this project if it exists, otherwise creates one.\n\n @param _projectId The ID of the project to find a configurable funding cycle for.\n @param _configuration The time at which the funding cycle was configured.\n @param _weight The weight to store in the configured funding cycle.\n @param _mustStartAtOrAfter The time before which the initialized funding cycle can't start.\n */\n function _configureIntrinsicPropertiesFor(\n uint256 _projectId,\n uint256 _configuration,\n uint256 _weight,\n uint256 _mustStartAtOrAfter\n ) private {\n // If there's not yet a funding cycle for the project, initialize one.\n if (latestConfigurationOf[_projectId] == 0)\n // Use an empty funding cycle as the base.\n return\n _initFor(_projectId, _getStructFor(0, 0), _configuration, _mustStartAtOrAfter, _weight);\n\n // Get the active funding cycle's configuration.\n uint256 _currentConfiguration = _eligibleOf(_projectId);\n\n // If an eligible funding cycle does not exist, get a reference to the latest funding cycle configuration for the project.\n if (_currentConfiguration == 0)\n // Get the latest funding cycle's configuration.\n _currentConfiguration = latestConfigurationOf[_projectId];\n\n // Get a reference to the funding cycle.\n JBFundingCycle memory _baseFundingCycle = _getStructFor(_projectId, _currentConfiguration);\n\n if (!_isApproved(_projectId, _baseFundingCycle) || block.timestamp < _baseFundingCycle.start)\n // If it hasn't been approved or hasn't yet started, set the ID to be the funding cycle it's based on,\n // which carries the latest approved configuration.\n _baseFundingCycle = _getStructFor(_projectId, _baseFundingCycle.basedOn);\n\n // The configuration can't be the same as the base configuration.\n if (_baseFundingCycle.configuration == _configuration) revert NO_SAME_BLOCK_RECONFIGURATION();\n\n // The time after the ballot of the provided funding cycle has expired.\n // If the provided funding cycle has no ballot, return the current timestamp.\n uint256 _timestampAfterBallot = _baseFundingCycle.ballot == IJBFundingCycleBallot(address(0))\n ? 0\n : _configuration + _baseFundingCycle.ballot.duration();\n\n _initFor(\n _projectId,\n _baseFundingCycle,\n _configuration,\n // Can only start after the ballot.\n _timestampAfterBallot > _mustStartAtOrAfter ? _timestampAfterBallot : _mustStartAtOrAfter,\n _weight\n );\n }\n\n /**\n @notice \n Initializes a funding cycle with the specified properties.\n\n @param _projectId The ID of the project to which the funding cycle being initialized belongs.\n @param _baseFundingCycle The funding cycle to base the initialized one on.\n @param _configuration The configuration of the funding cycle being initialized.\n @param _mustStartAtOrAfter The time before which the initialized funding cycle cannot start.\n @param _weight The weight to give the newly initialized funding cycle.\n */\n function _initFor(\n uint256 _projectId,\n JBFundingCycle memory _baseFundingCycle,\n uint256 _configuration,\n uint256 _mustStartAtOrAfter,\n uint256 _weight\n ) private {\n // If there is no base, initialize a first cycle.\n if (_baseFundingCycle.number == 0) {\n // The first number is 1.\n uint256 _number = 1;\n\n // Set fresh intrinsic properties.\n _packAndStoreIntrinsicPropertiesOf(\n _configuration,\n _projectId,\n _number,\n _weight,\n _baseFundingCycle.configuration,\n _mustStartAtOrAfter\n );\n } else {\n // Derive the correct next start time from the base.\n uint256 _start = _deriveStartFrom(_baseFundingCycle, _mustStartAtOrAfter);\n\n // A weight of 1 is treated as a weight of 0.\n // This is to allow a weight of 0 (default) to represent inheriting the discounted weight of the previous funding cycle.\n _weight = _weight > 0\n ? (_weight == 1 ? 0 : _weight)\n : _deriveWeightFrom(_baseFundingCycle, _start);\n\n // Derive the correct number.\n uint256 _number = _deriveNumberFrom(_baseFundingCycle, _start);\n\n // Update the intrinsic properties.\n _packAndStoreIntrinsicPropertiesOf(\n _configuration,\n _projectId,\n _number,\n _weight,\n _baseFundingCycle.configuration,\n _start\n );\n }\n\n // Set the project's latest funding cycle configuration.\n latestConfigurationOf[_projectId] = _configuration;\n\n emit Init(_configuration, _projectId, _baseFundingCycle.configuration);\n }\n\n /**\n @notice \n Efficiently stores a funding cycle's provided intrinsic properties.\n\n @param _configuration The configuration of the funding cycle to pack and store.\n @param _projectId The ID of the project to which the funding cycle belongs.\n @param _number The number of the funding cycle.\n @param _weight The weight of the funding cycle.\n @param _basedOn The configuration of the base funding cycle.\n @param _start The start time of this funding cycle.\n */\n function _packAndStoreIntrinsicPropertiesOf(\n uint256 _configuration,\n uint256 _projectId,\n uint256 _number,\n uint256 _weight,\n uint256 _basedOn,\n uint256 _start\n ) private {\n // weight in bits 0-87.\n uint256 packed = _weight;\n\n // basedOn in bits 88-143.\n packed |= _basedOn << 88;\n\n // start in bits 144-199.\n packed |= _start << 144;\n\n // number in bits 200-255.\n packed |= _number << 200;\n\n // Store the packed value.\n _packedIntrinsicPropertiesOf[_projectId][_configuration] = packed;\n }\n\n /**\n @notice \n The project's stored funding cycle that hasn't yet started and should be used next, if one exists.\n\n @dev\n A value of 0 is returned if no funding cycle was found.\n\n @dev\n Assumes the project has a latest configuration.\n \n @param _projectId The ID of a project to look through for a standby cycle.\n\n @return configuration The configuration of the standby funding cycle if one exists, or 0 if one doesn't exist.\n */\n function _standbyOf(uint256 _projectId) private view returns (uint256 configuration) {\n // Get a reference to the project's latest funding cycle.\n configuration = latestConfigurationOf[_projectId];\n\n // Get the necessary properties for the latest funding cycle.\n JBFundingCycle memory _fundingCycle = _getStructFor(_projectId, configuration);\n\n // There is no upcoming funding cycle if the latest funding cycle has already started.\n if (block.timestamp >= _fundingCycle.start) return 0;\n\n // If this is the first funding cycle, it is queued.\n if (_fundingCycle.number == 1) return configuration;\n\n // Get the necessary properties for the base funding cycle.\n JBFundingCycle memory _baseFundingCycle = _getStructFor(_projectId, _fundingCycle.basedOn);\n\n // If the latest configuration doesn't start until after another base cycle, return 0.\n if (\n _baseFundingCycle.duration > 0 &&\n block.timestamp < _fundingCycle.start - _baseFundingCycle.duration\n ) return 0;\n }\n\n /**\n @notice \n The project's stored funding cycle that has started and hasn't yet expired.\n \n @dev\n A value of 0 is returned if no funding cycle was found.\n\n @dev\n Assumes the project has a latest configuration.\n\n @param _projectId The ID of the project to look through.\n\n @return configuration The configuration of an eligible funding cycle if one exists, or 0 if one doesn't exist.\n */\n function _eligibleOf(uint256 _projectId) private view returns (uint256 configuration) {\n // Get a reference to the project's latest funding cycle.\n configuration = latestConfigurationOf[_projectId];\n\n // Get the latest funding cycle.\n JBFundingCycle memory _fundingCycle = _getStructFor(_projectId, configuration);\n\n // If the latest is expired, return an empty funding cycle.\n // A duration of 0 cannot be expired.\n if (\n _fundingCycle.duration > 0 && block.timestamp >= _fundingCycle.start + _fundingCycle.duration\n ) return 0;\n\n // Return the funding cycle's configuration if it has started.\n if (block.timestamp >= _fundingCycle.start) return _fundingCycle.configuration;\n\n // Get a reference to the cycle's base configuration.\n JBFundingCycle memory _baseFundingCycle = _getStructFor(_projectId, _fundingCycle.basedOn);\n\n // If the base cycle isn't eligible, the project has no eligible cycle.\n // A duration of 0 is always eligible.\n if (\n _baseFundingCycle.duration > 0 &&\n block.timestamp >= _baseFundingCycle.start + _baseFundingCycle.duration\n ) return 0;\n\n // Return the configuration that the latest funding cycle is based on.\n configuration = _fundingCycle.basedOn;\n }\n\n /** \n @notice \n A view of the funding cycle that would be created based on the provided one if the project doesn't make a reconfiguration.\n\n @dev\n Returns an empty funding cycle if there can't be a mock funding cycle based on the provided one.\n\n @dev\n Assumes a funding cycle with a duration of 0 will never be asked to be the base of a mock.\n\n @param _baseFundingCycle The funding cycle that the resulting funding cycle should follow.\n @param _allowMidCycle A flag indicating if the mocked funding cycle is allowed to already be mid cycle.\n\n @return A mock of what the next funding cycle will be.\n */\n function _mockFundingCycleBasedOn(JBFundingCycle memory _baseFundingCycle, bool _allowMidCycle)\n private\n view\n returns (JBFundingCycle memory)\n {\n // Get the distance of the current time to the start of the next possible funding cycle.\n // If the returned mock cycle must not yet have started, the start time of the mock must be in the future.\n uint256 _mustStartAtOrAfter = !_allowMidCycle\n ? block.timestamp + 1\n : block.timestamp - _baseFundingCycle.duration + 1;\n\n // Derive what the start time should be.\n uint256 _start = _deriveStartFrom(_baseFundingCycle, _mustStartAtOrAfter);\n\n // Derive what the number should be.\n uint256 _number = _deriveNumberFrom(_baseFundingCycle, _start);\n\n return\n JBFundingCycle(\n _number,\n _baseFundingCycle.configuration,\n _baseFundingCycle.basedOn,\n _start,\n _baseFundingCycle.duration,\n _deriveWeightFrom(_baseFundingCycle, _start),\n _baseFundingCycle.discountRate,\n _baseFundingCycle.ballot,\n _baseFundingCycle.metadata\n );\n }\n\n /** \n @notice \n The date that is the nearest multiple of the specified funding cycle's duration from its end.\n\n @param _baseFundingCycle The funding cycle to base the calculation on.\n @param _mustStartAtOrAfter A date that the derived start must be on or come after.\n\n @return start The next start time.\n */\n function _deriveStartFrom(JBFundingCycle memory _baseFundingCycle, uint256 _mustStartAtOrAfter)\n private\n pure\n returns (uint256 start)\n {\n // A subsequent cycle to one with a duration of 0 should start as soon as possible.\n if (_baseFundingCycle.duration == 0) return _mustStartAtOrAfter;\n\n // The time when the funding cycle immediately after the specified funding cycle starts.\n uint256 _nextImmediateStart = _baseFundingCycle.start + _baseFundingCycle.duration;\n\n // If the next immediate start is now or in the future, return it.\n if (_nextImmediateStart >= _mustStartAtOrAfter) return _nextImmediateStart;\n\n // The amount of seconds since the `_mustStartAtOrAfter` time which results in a start time that might satisfy the specified constraints.\n uint256 _timeFromImmediateStartMultiple = (_mustStartAtOrAfter - _nextImmediateStart) %\n _baseFundingCycle.duration;\n\n // A reference to the first possible start timestamp.\n start = _mustStartAtOrAfter - _timeFromImmediateStartMultiple;\n\n // Add increments of duration as necessary to satisfy the threshold.\n while (_mustStartAtOrAfter > start) start = start + _baseFundingCycle.duration;\n }\n\n /** \n @notice \n The accumulated weight change since the specified funding cycle.\n\n @param _baseFundingCycle The funding cycle to base the calculation on.\n @param _start The start time of the funding cycle to derive a number for.\n\n @return weight The derived weight, as a fixed point number with 18 decimals.\n */\n function _deriveWeightFrom(JBFundingCycle memory _baseFundingCycle, uint256 _start)\n private\n pure\n returns (uint256 weight)\n {\n // A subsequent cycle to one with a duration of 0 should have the next possible weight.\n if (_baseFundingCycle.duration == 0)\n return\n PRBMath.mulDiv(\n _baseFundingCycle.weight,\n JBConstants.MAX_DISCOUNT_RATE - _baseFundingCycle.discountRate,\n JBConstants.MAX_DISCOUNT_RATE\n );\n\n // The weight should be based off the base funding cycle's weight.\n weight = _baseFundingCycle.weight;\n\n // If the discount is 0, the weight doesn't change.\n if (_baseFundingCycle.discountRate == 0) return weight;\n\n // The difference between the start of the base funding cycle and the proposed start.\n uint256 _startDistance = _start - _baseFundingCycle.start;\n\n // Apply the base funding cycle's discount rate for each cycle that has passed.\n uint256 _discountMultiple = _startDistance / _baseFundingCycle.duration;\n\n for (uint256 i = 0; i < _discountMultiple; i++) {\n // The number of times to apply the discount rate.\n // Base the new weight on the specified funding cycle's weight.\n weight = PRBMath.mulDiv(\n weight,\n JBConstants.MAX_DISCOUNT_RATE - _baseFundingCycle.discountRate,\n JBConstants.MAX_DISCOUNT_RATE\n );\n // The calculation doesn't need to continue if the weight is 0.\n if (weight == 0) break;\n }\n }\n\n /** \n @notice \n The number of the next funding cycle given the specified funding cycle.\n\n @param _baseFundingCycle The funding cycle to base the calculation on.\n @param _start The start time of the funding cycle to derive a number for.\n\n @return The funding cycle number.\n */\n function _deriveNumberFrom(JBFundingCycle memory _baseFundingCycle, uint256 _start)\n private\n pure\n returns (uint256)\n {\n // A subsequent cycle to one with a duration of 0 should be the next number.\n if (_baseFundingCycle.duration == 0) return _baseFundingCycle.number + 1;\n\n // The difference between the start of the base funding cycle and the proposed start.\n uint256 _startDistance = _start - _baseFundingCycle.start;\n\n // Find the number of base cycles that fit in the start distance.\n return _baseFundingCycle.number + (_startDistance / _baseFundingCycle.duration);\n }\n\n /** \n @notice \n Checks to see if the provided funding cycle is approved according to the correct ballot.\n\n @param _projectId The ID of the project to which the funding cycle belongs. \n @param _fundingCycle The funding cycle to get an approval flag for.\n\n @return The approval flag.\n */\n function _isApproved(uint256 _projectId, JBFundingCycle memory _fundingCycle)\n private\n view\n returns (bool)\n {\n return\n _ballotStateOf(\n _projectId,\n _fundingCycle.configuration,\n _fundingCycle.start,\n _fundingCycle.basedOn\n ) == JBBallotState.Approved;\n }\n\n /**\n @notice \n A project's latest funding cycle configuration approval status.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n @param _configuration The funding cycle configuration to get the ballot state of.\n @param _start The start time of the funding cycle configuration to get the ballot state of.\n @param _ballotFundingCycleConfiguration The configuration of the funding cycle which is configured with the ballot that should be used.\n\n @return The ballot state of the project.\n */\n function _ballotStateOf(\n uint256 _projectId,\n uint256 _configuration,\n uint256 _start,\n uint256 _ballotFundingCycleConfiguration\n ) private view returns (JBBallotState) {\n // If there is no ballot funding cycle, implicitly approve.\n if (_ballotFundingCycleConfiguration == 0) return JBBallotState.Approved;\n\n // Get the ballot funding cycle.\n JBFundingCycle memory _ballotFundingCycle = _getStructFor(\n _projectId,\n _ballotFundingCycleConfiguration\n );\n\n // If there is no ballot, the ID is auto approved.\n // Otherwise if the ballot's duration hasn't passed, its still active.\n // Otherwise, return the ballot's state.\n if (_ballotFundingCycle.ballot == IJBFundingCycleBallot(address(0)))\n return JBBallotState.Approved;\n else if (_ballotFundingCycle.ballot.duration() >= block.timestamp - _configuration)\n return JBBallotState.Active;\n else return _ballotFundingCycle.ballot.stateOf(_projectId, _configuration, _start);\n }\n\n /**\n @notice \n Unpack a funding cycle's packed stored values into an easy-to-work-with funding cycle struct.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n @param _configuration The funding cycle configuration to get the full struct for.\n\n @return fundingCycle A funding cycle struct.\n */\n function _getStructFor(uint256 _projectId, uint256 _configuration)\n private\n view\n returns (JBFundingCycle memory fundingCycle)\n {\n // Return an empty funding cycle if the configuration specified is 0.\n if (_configuration == 0) return fundingCycle;\n\n fundingCycle.configuration = _configuration;\n\n uint256 _packedIntrinsicProperties = _packedIntrinsicPropertiesOf[_projectId][_configuration];\n\n // weight in bits 0-87 bits.\n fundingCycle.weight = uint256(uint88(_packedIntrinsicProperties));\n // basedOn in bits 88-143 bits.\n fundingCycle.basedOn = uint256(uint56(_packedIntrinsicProperties >> 88));\n // start in bits 144-199 bits.\n fundingCycle.start = uint256(uint56(_packedIntrinsicProperties >> 144));\n // number in bits 200-255 bits.\n fundingCycle.number = uint256(uint56(_packedIntrinsicProperties >> 200));\n\n uint256 _packedUserProperties = _packedUserPropertiesOf[_projectId][_configuration];\n\n // ballot in bits 0-159 bits.\n fundingCycle.ballot = IJBFundingCycleBallot(address(uint160(_packedUserProperties)));\n // duration in bits 160-223 bits.\n fundingCycle.duration = uint256(uint64(_packedUserProperties >> 160));\n // discountRate in bits 224-255 bits.\n fundingCycle.discountRate = uint256(uint32(_packedUserProperties >> 224));\n\n fundingCycle.metadata = _metadataOf[_projectId][_configuration];\n }\n}\n" @@ -359,7 +359,7 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './../../structs/JBFundAccessConstraints.sol';\nimport './../../structs/JBFundingCycleData.sol';\nimport './../../structs/JBFundingCycleMetadata.sol';\nimport './../../structs/JBGroupedSplits.sol';\nimport './../../structs/JBProjectMetadata.sol';\nimport './../IJBDirectory.sol';\nimport './../IJBFundingCycleStore.sol';\nimport './../IJBMigratable.sol';\nimport './../IJBPaymentTerminal.sol';\nimport './../IJBSplitsStore/2.sol';\nimport './../IJBToken.sol';\nimport './../IJBTokenStore.sol';\n\ninterface IJBController is IERC165 {\n event LaunchProject(uint256 configuration, uint256 projectId, string memo, address caller);\n\n event LaunchFundingCycles(uint256 configuration, uint256 projectId, string memo, address caller);\n\n event ReconfigureFundingCycles(\n uint256 configuration,\n uint256 projectId,\n string memo,\n address caller\n );\n\n event SetFundAccessConstraints(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n JBFundAccessConstraints constraints,\n address caller\n );\n\n event DistributeReservedTokens(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address beneficiary,\n uint256 tokenCount,\n uint256 beneficiaryTokenCount,\n string memo,\n address caller\n );\n\n event DistributeToReservedTokenSplit(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n JBSplit split,\n uint256 tokenCount,\n address caller\n );\n\n event MintTokens(\n address indexed beneficiary,\n uint256 indexed projectId,\n uint256 tokenCount,\n uint256 beneficiaryTokenCount,\n string memo,\n uint256 reservedRate,\n address caller\n );\n\n event BurnTokens(\n address indexed holder,\n uint256 indexed projectId,\n uint256 tokenCount,\n string memo,\n address caller\n );\n\n event Migrate(uint256 indexed projectId, IJBMigratable to, address caller);\n\n event PrepMigration(uint256 indexed projectId, address from, address caller);\n\n function projects() external view returns (IJBProjects);\n\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\n\n function tokenStore() external view returns (IJBTokenStore);\n\n function splitsStore() external view returns (IJBSplitsStore);\n\n function directory() external view returns (IJBDirectory);\n\n function reservedTokenBalanceOf(uint256 _projectId, uint256 _reservedRate)\n external\n view\n returns (uint256);\n\n function distributionLimitOf(\n uint256 _projectId,\n uint256 _configuration,\n IJBPaymentTerminal _terminal,\n address _token\n ) external view returns (uint256 distributionLimit, uint256 distributionLimitCurrency);\n\n function overflowAllowanceOf(\n uint256 _projectId,\n uint256 _configuration,\n IJBPaymentTerminal _terminal,\n address _token\n ) external view returns (uint256 overflowAllowance, uint256 overflowAllowanceCurrency);\n\n function totalOutstandingTokensOf(uint256 _projectId, uint256 _reservedRate)\n external\n view\n returns (uint256);\n\n function getFundingCycleOf(uint256 _projectId, uint256 _configuration)\n external\n view\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\n\n function latestConfiguredFundingCycleOf(uint256 _projectId)\n external\n view\n returns (\n JBFundingCycle memory,\n JBFundingCycleMetadata memory metadata,\n JBBallotState\n );\n\n function currentFundingCycleOf(uint256 _projectId)\n external\n view\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\n\n function queuedFundingCycleOf(uint256 _projectId)\n external\n view\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\n\n function launchProjectFor(\n address _owner,\n JBProjectMetadata calldata _projectMetadata,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] memory _groupedSplits,\n JBFundAccessConstraints[] memory _fundAccessConstraints,\n IJBPaymentTerminal[] memory _terminals,\n string calldata _memo\n ) external returns (uint256 projectId);\n\n function launchFundingCyclesFor(\n uint256 _projectId,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] memory _groupedSplits,\n JBFundAccessConstraints[] memory _fundAccessConstraints,\n IJBPaymentTerminal[] memory _terminals,\n string calldata _memo\n ) external returns (uint256 configuration);\n\n function reconfigureFundingCyclesOf(\n uint256 _projectId,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] memory _groupedSplits,\n JBFundAccessConstraints[] memory _fundAccessConstraints,\n string calldata _memo\n ) external returns (uint256);\n\n function issueTokenFor(\n uint256 _projectId,\n string calldata _name,\n string calldata _symbol\n ) external returns (IJBToken token);\n\n function changeTokenOf(\n uint256 _projectId,\n IJBToken _token,\n address _newOwner\n ) external;\n\n function mintTokensOf(\n uint256 _projectId,\n uint256 _tokenCount,\n address _beneficiary,\n string calldata _memo,\n bool _preferClaimedTokens,\n bool _useReservedRate\n ) external returns (uint256 beneficiaryTokenCount);\n\n function burnTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string calldata _memo,\n bool _preferClaimedTokens\n ) external;\n\n function distributeReservedTokensOf(uint256 _projectId, string memory _memo)\n external\n returns (uint256);\n\n function migrate(uint256 _projectId, IJBMigratable _to) external;\n}\n" }, "contracts/abstract/JBPayoutRedemptionPaymentTerminal/2.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../../interfaces/IJBController/2.sol';\nimport './../../interfaces/IJBPayoutRedemptionPaymentTerminal/2.sol';\nimport './../../libraries/JBConstants.sol';\nimport './../../libraries/JBCurrencies.sol';\nimport './../../libraries/JBFixedPointNumber.sol';\nimport './../../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../../libraries/JBOperations.sol';\nimport './../../libraries/JBSplitsGroups.sol';\nimport './../../libraries/JBTokens.sol';\nimport './../../structs/JBTokenAmount.sol';\nimport './../JBOperatable.sol';\nimport './../JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal is\n IJBPayoutRedemptionPaymentTerminal,\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n ReentrancyGuard\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The protocol project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _PROTOCOL_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.ETH)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.ETH, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.ETH) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i = 0; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @dev\n If the fee gauge reverts when called upon while a project is attempting to distribute its funds, a project's funds will be locked. This is a known risk.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual;\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual;\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegate` only used within scope.\n {\n IJBRedemptionDelegate _delegate;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegate, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If a delegate was returned by the data source, issue a callback to it.\n if (_delegate != IJBRedemptionDelegate(address(0))) {\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _beneficiary,\n _memo,\n _metadata\n );\n _delegate.didRedeem(_data);\n emit DelegateDidRedeem(_delegate, _data, msg.sender);\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convinience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n\n // Take the fee.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || _feeEligibleDistributionAmount == 0\n ? 0\n : _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n );\n\n // Get a reference to how much to distribute to the project owner, which is the leftover amount minus any fees.\n\n unchecked {\n netLeftoverDistributionAmount = _leftoverDistributionAmount == 0\n ? 0\n : _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n }\n\n // Transfer any remaining balance to the project owner.\n if (netLeftoverDistributionAmount > 0)\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convinience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i = 0; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount;\n\n if (_payoutAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (isFeelessAddress[address(_split.allocator)])\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _netPayoutAmount : 0;\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n _netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // Save gas if this contract is being used as the terminal.\n if (_terminal == this) {\n // This distribution does not incur a fee.\n _netPayoutAmount = _payoutAmount;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\n else\n _pay(\n _netPayoutAmount,\n address(this),\n _split.projectId,\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n } else {\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (isFeelessAddress[address(_terminal)])\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _netPayoutAmount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _terminal.addToBalanceOf{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n '',\n _projectMetadata\n );\n else\n _terminal.pay{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n }\n } else {\n unchecked {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(\n address(this),\n _split.beneficiary != address(0) ? _split.beneficiary : payable(msg.sender),\n _netPayoutAmount\n );\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _PROTOCOL_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n */\n function _processFee(uint256 _amount, address _beneficiary) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_PROTOCOL_PROJECT_ID, token);\n\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\n if (_terminal == this)\n _pay(_amount, address(this), _PROTOCOL_PROJECT_ID, _beneficiary, 0, false, '', bytes('')); // Use the local pay call.\n else {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _amount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _amount : 0;\n\n // Send the payment.\n _terminal.pay{value: _payableValue}(\n _PROTOCOL_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the external pay call of the correct terminal.\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegate` and `_tokenCount` only used within scope.\n {\n IJBPayDelegate _delegate;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegate, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If a delegate was returned by the data source, issue a callback to it.\n if (_delegate != IJBPayDelegate(address(0))) {\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n _delegate.didPay(_data);\n emit DelegateDidPay(_delegate, _data, msg.sender);\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i = 0; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n unchecked {\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256 feeDiscount) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (directory.primaryTerminalOf(_PROTOCOL_PROJECT_ID, token) == IJBPaymentTerminal(address(0)))\n return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge == IJBFeeGauge(address(0)))\n feeDiscount = 0;\n // If the guage reverts, set the discount to 0.\n else\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n feeDiscount = discount;\n } catch {\n feeDiscount = 0;\n }\n\n // If the fee discount is greater than the max, nullify the discount.\n if (feeDiscount > JBConstants.MAX_FEE_DISCOUNT) feeDiscount = 0;\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../../interfaces/IJBController/2.sol';\nimport './../../interfaces/IJBPayoutRedemptionPaymentTerminal/2.sol';\nimport './../../libraries/JBConstants.sol';\nimport './../../libraries/JBCurrencies.sol';\nimport './../../libraries/JBFixedPointNumber.sol';\nimport './../../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../../libraries/JBOperations.sol';\nimport './../../libraries/JBSplitsGroups.sol';\nimport './../../libraries/JBTokens.sol';\nimport './../../structs/JBTokenAmount.sol';\nimport './../JBOperatable.sol';\nimport './../JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal is\n IJBPayoutRedemptionPaymentTerminal,\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n ReentrancyGuard\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The protocol project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _PROTOCOL_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.GAS_CURRENCY)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.GAS_CURRENCY, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.GAS_TOKEN) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i = 0; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @dev\n If the fee gauge reverts when called upon while a project is attempting to distribute its funds, a project's funds will be locked. This is a known risk.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual;\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual;\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegate` only used within scope.\n {\n IJBRedemptionDelegate _delegate;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegate, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If a delegate was returned by the data source, issue a callback to it.\n if (_delegate != IJBRedemptionDelegate(address(0))) {\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _beneficiary,\n _memo,\n _metadata\n );\n _delegate.didRedeem(_data);\n emit DelegateDidRedeem(_delegate, _data, msg.sender);\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convinience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n\n // Take the fee.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || _feeEligibleDistributionAmount == 0\n ? 0\n : _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n );\n\n // Get a reference to how much to distribute to the project owner, which is the leftover amount minus any fees.\n\n unchecked {\n netLeftoverDistributionAmount = _leftoverDistributionAmount == 0\n ? 0\n : _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n }\n\n // Transfer any remaining balance to the project owner.\n if (netLeftoverDistributionAmount > 0)\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convinience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i = 0; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount;\n\n if (_payoutAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (isFeelessAddress[address(_split.allocator)])\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0;\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n _netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // Save gas if this contract is being used as the terminal.\n if (_terminal == this) {\n // This distribution does not incur a fee.\n _netPayoutAmount = _payoutAmount;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\n else\n _pay(\n _netPayoutAmount,\n address(this),\n _split.projectId,\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n } else {\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (isFeelessAddress[address(_terminal)])\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _terminal.addToBalanceOf{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n '',\n _projectMetadata\n );\n else\n _terminal.pay{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n }\n } else {\n unchecked {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(\n address(this),\n _split.beneficiary != address(0) ? _split.beneficiary : payable(msg.sender),\n _netPayoutAmount\n );\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _PROTOCOL_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n */\n function _processFee(uint256 _amount, address _beneficiary) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_PROTOCOL_PROJECT_ID, token);\n\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\n if (_terminal == this)\n _pay(_amount, address(this), _PROTOCOL_PROJECT_ID, _beneficiary, 0, false, '', bytes('')); // Use the local pay call.\n else {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _amount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send the payment.\n _terminal.pay{value: _payableValue}(\n _PROTOCOL_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the external pay call of the correct terminal.\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegate` and `_tokenCount` only used within scope.\n {\n IJBPayDelegate _delegate;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegate, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If a delegate was returned by the data source, issue a callback to it.\n if (_delegate != IJBPayDelegate(address(0))) {\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n _delegate.didPay(_data);\n emit DelegateDidPay(_delegate, _data, msg.sender);\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i = 0; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n unchecked {\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256 feeDiscount) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (directory.primaryTerminalOf(_PROTOCOL_PROJECT_ID, token) == IJBPaymentTerminal(address(0)))\n return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge == IJBFeeGauge(address(0)))\n feeDiscount = 0;\n // If the guage reverts, set the discount to 0.\n else\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n feeDiscount = discount;\n } catch {\n feeDiscount = 0;\n }\n\n // If the fee discount is greater than the max, nullify the discount.\n if (feeDiscount > JBConstants.MAX_FEE_DISCOUNT) feeDiscount = 0;\n }\n}\n" }, "contracts/interfaces/IJBPayoutRedemptionPaymentTerminal/2.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\nimport './../../structs/JBFee.sol';\nimport './../IJBAllowanceTerminal.sol';\nimport './../IJBDirectory.sol';\nimport './../IJBFeeGauge.sol';\nimport './../IJBPayDelegate.sol';\nimport './../IJBPaymentTerminal.sol';\nimport './../IJBPayoutTerminal.sol';\nimport './../IJBPrices.sol';\nimport './../IJBProjects.sol';\nimport './../IJBRedemptionDelegate.sol';\nimport './../IJBRedemptionTerminal.sol';\nimport './../IJBSingleTokenPaymentTerminal.sol';\nimport './../IJBSingleTokenPaymentTerminalStore.sol';\nimport './../IJBSplitsStore/2.sol';\n\ninterface IJBPayoutRedemptionPaymentTerminal is\n IJBPaymentTerminal,\n IJBPayoutTerminal,\n IJBAllowanceTerminal,\n IJBRedemptionTerminal\n{\n event AddToBalance(\n uint256 indexed projectId,\n uint256 amount,\n uint256 refundedFees,\n string memo,\n bytes metadata,\n address caller\n );\n\n event Migrate(\n uint256 indexed projectId,\n IJBPaymentTerminal indexed to,\n uint256 amount,\n address caller\n );\n\n event DistributePayouts(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address beneficiary,\n uint256 amount,\n uint256 distributedAmount,\n uint256 fee,\n uint256 beneficiaryDistributionAmount,\n string memo,\n address caller\n );\n\n event UseAllowance(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address beneficiary,\n uint256 amount,\n uint256 distributedAmount,\n uint256 netDistributedamount,\n string memo,\n address caller\n );\n\n event HoldFee(\n uint256 indexed projectId,\n uint256 indexed amount,\n uint256 indexed fee,\n uint256 feeDiscount,\n address beneficiary,\n address caller\n );\n\n event ProcessFee(\n uint256 indexed projectId,\n uint256 indexed amount,\n bool indexed wasHeld,\n address beneficiary,\n address caller\n );\n\n event RefundHeldFees(\n uint256 indexed projectId,\n uint256 indexed amount,\n uint256 indexed refundedFees,\n uint256 leftoverAmount,\n address caller\n );\n\n event Pay(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address payer,\n address beneficiary,\n uint256 amount,\n uint256 beneficiaryTokenCount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DelegateDidPay(IJBPayDelegate indexed delegate, JBDidPayData data, address caller);\n\n event RedeemTokens(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address holder,\n address beneficiary,\n uint256 tokenCount,\n uint256 reclaimedAmount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DelegateDidRedeem(\n IJBRedemptionDelegate indexed delegate,\n JBDidRedeemData data,\n address caller\n );\n\n event DistributeToPayoutSplit(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n JBSplit split,\n uint256 amount,\n address caller\n );\n\n event SetFee(uint256 fee, address caller);\n\n event SetFeeGauge(IJBFeeGauge indexed feeGauge, address caller);\n\n event SetFeelessAddress(address indexed addrs, bool indexed flag, address caller);\n\n function projects() external view returns (IJBProjects);\n\n function splitsStore() external view returns (IJBSplitsStore);\n\n function directory() external view returns (IJBDirectory);\n\n function prices() external view returns (IJBPrices);\n\n function store() external view returns (IJBSingleTokenPaymentTerminalStore);\n\n function baseWeightCurrency() external view returns (uint256);\n\n function payoutSplitsGroup() external view returns (uint256);\n\n function heldFeesOf(uint256 _projectId) external view returns (JBFee[] memory);\n\n function fee() external view returns (uint256);\n\n function feeGauge() external view returns (IJBFeeGauge);\n\n function isFeelessAddress(address _contract) external view returns (bool);\n\n function migrate(uint256 _projectId, IJBPaymentTerminal _to) external returns (uint256 balance);\n\n function processFees(uint256 _projectId) external;\n\n function setFee(uint256 _fee) external;\n\n function setFeeGauge(IJBFeeGauge _feeGauge) external;\n\n function setFeelessAddress(address _contract, bool _flag) external;\n}\n" @@ -394,29 +394,29 @@ "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface AggregatorV3Interface {\n\n function decimals()\n external\n view\n returns (\n uint8\n );\n\n function description()\n external\n view\n returns (\n string memory\n );\n\n function version()\n external\n view\n returns (\n uint256\n );\n\n // getRoundData and latestRoundData should both raise \"No data present\"\n // if they do not have data to report, instead of returning unset values\n // which could be misinterpreted as actual reported values.\n function getRoundData(\n uint80 _roundId\n )\n external\n view\n returns (\n uint80 roundId,\n int256 answer,\n uint256 startedAt,\n uint256 updatedAt,\n uint80 answeredInRound\n );\n\n function latestRoundData()\n external\n view\n returns (\n uint80 roundId,\n int256 answer,\n uint256 startedAt,\n uint256 updatedAt,\n uint80 answeredInRound\n );\n\n}\n" }, - "contracts/JBETHERC20SplitsPayer/2.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBSplitsPayer/2.sol';\nimport './../interfaces/IJBSplitsStore/2.sol';\nimport './../libraries/JBConstants.sol';\nimport './../JBETHERC20ProjectPayer.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\n\n @dev\n Adheres to -\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBETHERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBETHERC20SplitsPayer is IJBSplitsPayer, JBETHERC20ProjectPayer, ReentrancyGuard {\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The ID of project for which the default splits are stored. \n */\n uint256 public override defaultSplitsProjectId;\n\n /**\n @notice\n The domain within which the default splits are stored. \n */\n uint256 public override defaultSplitsDomain;\n\n /**\n @notice\n The group within which the default splits are stored. \n */\n uint256 public override defaultSplitsGroup;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBETHERC20ProjectPayer, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n )\n JBETHERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _preferAddToBalance,\n _splitsStore.directory(),\n _owner\n )\n {\n defaultSplitsProjectId = _defaultSplitsProjectId;\n defaultSplitsDomain = _defaultSplitsDomain;\n defaultSplitsGroup = _defaultSplitsGroup;\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default split group using the stored default properties.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override nonReentrant {\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n JBTokens.ETH,\n address(this).balance,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender\n );\n\n // If there is no leftover amount, nothing left to pay.\n if (_leftoverAmount == 0) return;\n\n // If there's a default project ID, try to pay it.\n if (defaultProjectId != 0)\n if (defaultPreferAddToBalance)\n // Pay the project by adding to its balance if prefered.\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.ETH,\n _leftoverAmount,\n 18, // decimals.\n defaultMemo,\n defaultMetadata\n );\n // Otherwise, issue a payment to the project.\n else\n _pay(\n defaultProjectId,\n JBTokens.ETH,\n _leftoverAmount,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n 0, // min returned tokens.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n // If no project was specified, send the funds directly to the beneficiary or the msg.sender.\n else\n Address.sendValue(\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(msg.sender),\n _leftoverAmount\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the location of the splits that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n */\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) external virtual override onlyOwner {\n // Set the default splits project ID if it's changing.\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\n\n // Set the default splits domain if it's changing.\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\n\n // Set the default splits group if it's changing.\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\n\n emit SetDefaultSplits(_projectId, _domain, _group, msg.sender);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender\n );\n\n // Pay any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to pay it.\n if (_projectId != 0) {\n _pay(\n _projectId,\n _token,\n _leftoverAmount,\n _decimals,\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n // If no project was specified, send the funds directly to the beneficiary or the msg.sender.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _beneficiary != address(0) ? payable(_beneficiary) : payable(msg.sender),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).transfer(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _leftoverAmount\n );\n }\n }\n\n emit Pay(\n _projectId,\n _beneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event. \n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender\n );\n\n // Distribute any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to add to its balance.\n if (_projectId != 0)\n // Add to the project's balance.\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\n\n // Otherwise, send a payment to the beneficiary.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(msg.sender),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).transfer(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _leftoverAmount\n );\n }\n }\n\n emit AddToBalance(\n _projectId,\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splitsProjectId The ID of the project to which the splits belong.\n @param _splitsDomain The splits domain to which the group belongs.\n @param _splitsGroup The splits group to pay.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payToSplits(\n uint256 _splitsProjectId,\n uint256 _splitsDomain,\n uint256 _splitsGroup,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Get a reference to the splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup);\n\n // Set the leftover amount to the initial balance.\n leftoverAmount = _amount;\n\n // Settle between all splits.\n for (uint256 i = 0; i < _splits.length; i++) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[i];\n\n // The amount to send towards the split.\n uint256 _splitAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n if (_splitAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n _token,\n _splitAmount,\n _decimals,\n defaultProjectId,\n 0,\n _split\n );\n\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\n if (_token != JBTokens.ETH)\n IERC20(_token).approve(address(_split.allocator), _splitAmount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _splitAmount : 0;\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n if (_split.preferAddToBalance)\n _addToBalanceOf(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n 0,\n _split.preferClaimed,\n defaultMemo,\n defaultMetadata\n );\n } else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _split.beneficiary != address(0) ? _split.beneficiary : payable(_defaultBeneficiary),\n _splitAmount\n );\n // Or, transfer the ERC20.\n else {\n IERC20(_token).transfer(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n _splitAmount\n );\n }\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _splitAmount;\n }\n\n emit DistributeToSplit(\n _splitsProjectId,\n _splitsDomain,\n _splitsGroup,\n _split,\n _splitAmount,\n _defaultBeneficiary,\n msg.sender\n );\n }\n }\n}\n" + "contracts/JBGasTokenERC20SplitsPayer/2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBSplitsPayer/2.sol';\nimport './../interfaces/IJBSplitsStore/2.sol';\nimport './../libraries/JBConstants.sol';\nimport './../JBGasTokenERC20ProjectPayer.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\n\n @dev\n Adheres to -\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBGasTokenERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBGasTokenERC20SplitsPayer is IJBSplitsPayer, JBGasTokenERC20ProjectPayer, ReentrancyGuard {\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The ID of project for which the default splits are stored. \n */\n uint256 public override defaultSplitsProjectId;\n\n /**\n @notice\n The domain within which the default splits are stored. \n */\n uint256 public override defaultSplitsDomain;\n\n /**\n @notice\n The group within which the default splits are stored. \n */\n uint256 public override defaultSplitsGroup;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBGasTokenERC20ProjectPayer, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n )\n JBGasTokenERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _preferAddToBalance,\n _splitsStore.directory(),\n _owner\n )\n {\n defaultSplitsProjectId = _defaultSplitsProjectId;\n defaultSplitsDomain = _defaultSplitsDomain;\n defaultSplitsGroup = _defaultSplitsGroup;\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default split group using the stored default properties.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override nonReentrant {\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender\n );\n\n // If there is no leftover amount, nothing left to pay.\n if (_leftoverAmount == 0) return;\n\n // If there's a default project ID, try to pay it.\n if (defaultProjectId != 0)\n if (defaultPreferAddToBalance)\n // Pay the project by adding to its balance if prefered.\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n _leftoverAmount,\n 18, // decimals.\n defaultMemo,\n defaultMetadata\n );\n // Otherwise, issue a payment to the project.\n else\n _pay(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n _leftoverAmount,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n 0, // min returned tokens.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n // If no project was specified, send the funds directly to the beneficiary or the msg.sender.\n else\n Address.sendValue(\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(msg.sender),\n _leftoverAmount\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the location of the splits that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n */\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) external virtual override onlyOwner {\n // Set the default splits project ID if it's changing.\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\n\n // Set the default splits domain if it's changing.\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\n\n // Set the default splits group if it's changing.\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\n\n emit SetDefaultSplits(_projectId, _domain, _group, msg.sender);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender\n );\n\n // Pay any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to pay it.\n if (_projectId != 0) {\n _pay(\n _projectId,\n _token,\n _leftoverAmount,\n _decimals,\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n // If no project was specified, send the funds directly to the beneficiary or the msg.sender.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _beneficiary != address(0) ? payable(_beneficiary) : payable(msg.sender),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).transfer(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _leftoverAmount\n );\n }\n }\n\n emit Pay(\n _projectId,\n _beneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event. \n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender\n );\n\n // Distribute any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to add to its balance.\n if (_projectId != 0)\n // Add to the project's balance.\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\n\n // Otherwise, send a payment to the beneficiary.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(msg.sender),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).transfer(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _leftoverAmount\n );\n }\n }\n\n emit AddToBalance(\n _projectId,\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splitsProjectId The ID of the project to which the splits belong.\n @param _splitsDomain The splits domain to which the group belongs.\n @param _splitsGroup The splits group to pay.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payToSplits(\n uint256 _splitsProjectId,\n uint256 _splitsDomain,\n uint256 _splitsGroup,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Get a reference to the splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup);\n\n // Set the leftover amount to the initial balance.\n leftoverAmount = _amount;\n\n // Settle between all splits.\n for (uint256 i = 0; i < _splits.length; i++) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[i];\n\n // The amount to send towards the split.\n uint256 _splitAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n if (_splitAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n _token,\n _splitAmount,\n _decimals,\n defaultProjectId,\n 0,\n _split\n );\n\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN)\n IERC20(_token).approve(address(_split.allocator), _splitAmount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _splitAmount : 0;\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n if (_split.preferAddToBalance)\n _addToBalanceOf(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n 0,\n _split.preferClaimed,\n defaultMemo,\n defaultMetadata\n );\n } else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _split.beneficiary != address(0) ? _split.beneficiary : payable(_defaultBeneficiary),\n _splitAmount\n );\n // Or, transfer the ERC20.\n else {\n IERC20(_token).transfer(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n _splitAmount\n );\n }\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _splitAmount;\n }\n\n emit DistributeToSplit(\n _splitsProjectId,\n _splitsDomain,\n _splitsGroup,\n _split,\n _splitAmount,\n _defaultBeneficiary,\n msg.sender\n );\n }\n }\n}\n" }, "contracts/interfaces/IJBSplitsPayer/2.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './../../structs/JBSplit.sol';\nimport './../IJBSplitsStore/2.sol';\n\ninterface IJBSplitsPayer is IERC165 {\n event SetDefaultSplits(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n address caller\n );\n event Pay(\n uint256 indexed projectId,\n address beneficiary,\n address token,\n uint256 amount,\n uint256 decimals,\n uint256 leftoverAmount,\n uint256 minReturnedTokens,\n bool preferClaimedTokens,\n string memo,\n bytes metadata,\n address caller\n );\n\n event AddToBalance(\n uint256 indexed projectId,\n address beneficiary,\n address token,\n uint256 amount,\n uint256 decimals,\n uint256 leftoverAmount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DistributeToSplit(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n JBSplit split,\n uint256 amount,\n address defaultBeneficiary,\n address caller\n );\n\n function defaultSplitsProjectId() external view returns (uint256);\n\n function defaultSplitsDomain() external view returns (uint256);\n\n function defaultSplitsGroup() external view returns (uint256);\n\n function splitsStore() external view returns (IJBSplitsStore);\n\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) external;\n}\n" }, "contracts/system_tests/TestEIP165_2.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './helpers/TestBaseWorkflow_2.sol';\nimport '../JBReconfigurationBufferBallot.sol';\nimport '../JBETHERC20SplitsPayer/2.sol';\n\ncontract TestEIP165 is TestBaseWorkflow_2 {\n bytes4 constant notSupportedInterface = 0xffffffff;\n\n uint256 constant projectId = 2;\n uint256 constant splitsProjectID = 3;\n address payable constant splitsBeneficiary = payable(address(420));\n uint256 constant splitsDomain = 1;\n uint256 constant splitsGroup = 1;\n bool constant splitsPreferClaimedTokens = false;\n string constant splitsMemo = '';\n bytes constant splitsMetadata = '';\n bool constant splitsPreferAddToBalance = true;\n address constant splitsOwner = address(420);\n\n function testJBController() public {\n JBController controller = jbController();\n\n // Should support these interfaces\n assertTrue(controller.supportsInterface(type(IERC165).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBController).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBMigratable).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!controller.supportsInterface(notSupportedInterface));\n }\n\n function testJBERC20PaymentTerminal() public {\n JBERC20PaymentTerminal terminal = new JBERC20PaymentTerminal(\n jbToken(),\n jbLibraries().USD(), // currency\n jbLibraries().ETH(), // base weight currency\n 1, // JBSplitsGroupe\n jbOperatorStore(),\n jbProjects(),\n jbDirectory(),\n jbSplitsStore(),\n jbPrices(),\n jbPaymentTerminalStore(),\n multisig()\n );\n\n // Should support these interfaces\n assertTrue(terminal.supportsInterface(type(IERC165).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBRedemptionTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBSingleTokenPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!terminal.supportsInterface(notSupportedInterface));\n }\n\n function testJBETHPaymentTerminal() public {\n JBETHPaymentTerminal terminal = jbETHPaymentTerminal();\n\n // Should support these interfaces\n assertTrue(terminal.supportsInterface(type(IERC165).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBRedemptionTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBSingleTokenPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!terminal.supportsInterface(notSupportedInterface));\n }\n\n function testJBProjects() public {\n JBProjects projects = jbProjects();\n\n // Should support these interfaces\n assertTrue(projects.supportsInterface(type(IERC165).interfaceId));\n assertTrue(projects.supportsInterface(type(IERC721).interfaceId));\n assertTrue(projects.supportsInterface(type(IERC721Metadata).interfaceId));\n assertTrue(projects.supportsInterface(type(IJBProjects).interfaceId));\n assertTrue(projects.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!projects.supportsInterface(notSupportedInterface));\n }\n\n function testJBReconfigurationBufferBallot() public {\n JBReconfigurationBufferBallot ballot = new JBReconfigurationBufferBallot(\n 3000,\n jbFundingCycleStore()\n );\n\n // Should support these interfaces\n assertTrue(ballot.supportsInterface(type(IERC165).interfaceId));\n assertTrue(ballot.supportsInterface(type(IJBReconfigurationBufferBallot).interfaceId));\n assertTrue(ballot.supportsInterface(type(IJBFundingCycleBallot).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!ballot.supportsInterface(notSupportedInterface));\n }\n\n function testJBETHERC20SplitsPayer() public {\n JBETHERC20SplitsPayer splitsPayer = new JBETHERC20SplitsPayer(\n splitsProjectID,\n splitsDomain,\n splitsGroup,\n jbSplitsStore(),\n projectId,\n splitsBeneficiary,\n splitsPreferClaimedTokens,\n splitsMemo,\n splitsMetadata,\n splitsPreferAddToBalance,\n splitsOwner\n );\n\n // Should support these interfaces\n assertTrue(splitsPayer.supportsInterface(type(IERC165).interfaceId));\n assertTrue(splitsPayer.supportsInterface(type(IJBSplitsPayer).interfaceId));\n assertTrue(splitsPayer.supportsInterface(type(IJBProjectPayer).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!splitsPayer.supportsInterface(notSupportedInterface));\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './helpers/TestBaseWorkflow_2.sol';\nimport '../JBReconfigurationBufferBallot.sol';\nimport '../JBGasTokenERC20SplitsPayer/2.sol';\n\ncontract TestEIP165 is TestBaseWorkflow_2 {\n bytes4 constant notSupportedInterface = 0xffffffff;\n\n uint256 constant projectId = 2;\n uint256 constant splitsProjectID = 3;\n address payable constant splitsBeneficiary = payable(address(420));\n uint256 constant splitsDomain = 1;\n uint256 constant splitsGroup = 1;\n bool constant splitsPreferClaimedTokens = false;\n string constant splitsMemo = '';\n bytes constant splitsMetadata = '';\n bool constant splitsPreferAddToBalance = true;\n address constant splitsOwner = address(420);\n\n function testJBController() public {\n JBController controller = jbController();\n\n // Should support these interfaces\n assertTrue(controller.supportsInterface(type(IERC165).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBController).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBMigratable).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!controller.supportsInterface(notSupportedInterface));\n }\n\n function testJBERC20PaymentTerminal() public {\n JBERC20PaymentTerminal terminal = new JBERC20PaymentTerminal(\n jbToken(),\n jbLibraries().USD(), // currency\n jbLibraries().ETH(), // base weight currency\n 1, // JBSplitsGroupe\n jbOperatorStore(),\n jbProjects(),\n jbDirectory(),\n jbSplitsStore(),\n jbPrices(),\n jbPaymentTerminalStore(),\n multisig()\n );\n\n // Should support these interfaces\n assertTrue(terminal.supportsInterface(type(IERC165).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBRedemptionTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBSingleTokenPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!terminal.supportsInterface(notSupportedInterface));\n }\n\n function testJBETHPaymentTerminal() public {\n JBETHPaymentTerminal terminal = jbETHPaymentTerminal();\n\n // Should support these interfaces\n assertTrue(terminal.supportsInterface(type(IERC165).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBRedemptionTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBSingleTokenPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!terminal.supportsInterface(notSupportedInterface));\n }\n\n function testJBProjects() public {\n JBProjects projects = jbProjects();\n\n // Should support these interfaces\n assertTrue(projects.supportsInterface(type(IERC165).interfaceId));\n assertTrue(projects.supportsInterface(type(IERC721).interfaceId));\n assertTrue(projects.supportsInterface(type(IERC721Metadata).interfaceId));\n assertTrue(projects.supportsInterface(type(IJBProjects).interfaceId));\n assertTrue(projects.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!projects.supportsInterface(notSupportedInterface));\n }\n\n function testJBReconfigurationBufferBallot() public {\n JBReconfigurationBufferBallot ballot = new JBReconfigurationBufferBallot(\n 3000,\n jbFundingCycleStore()\n );\n\n // Should support these interfaces\n assertTrue(ballot.supportsInterface(type(IERC165).interfaceId));\n assertTrue(ballot.supportsInterface(type(IJBReconfigurationBufferBallot).interfaceId));\n assertTrue(ballot.supportsInterface(type(IJBFundingCycleBallot).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!ballot.supportsInterface(notSupportedInterface));\n }\n\n function testJBGasTokenERC20SplitsPayer() public {\n JBGasTokenERC20SplitsPayer splitsPayer = new JBGasTokenERC20SplitsPayer(\n splitsProjectID,\n splitsDomain,\n splitsGroup,\n jbSplitsStore(),\n projectId,\n splitsBeneficiary,\n splitsPreferClaimedTokens,\n splitsMemo,\n splitsMetadata,\n splitsPreferAddToBalance,\n splitsOwner\n );\n\n // Should support these interfaces\n assertTrue(splitsPayer.supportsInterface(type(IERC165).interfaceId));\n assertTrue(splitsPayer.supportsInterface(type(IJBSplitsPayer).interfaceId));\n assertTrue(splitsPayer.supportsInterface(type(IJBProjectPayer).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!splitsPayer.supportsInterface(notSupportedInterface));\n }\n}\n" }, - "contracts/JBETHERC20SplitsPayerDeployer/2.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './../interfaces/IJBETHERC20SplitsPayerDeployer/2.sol';\nimport './../JBETHERC20SplitsPayer/2.sol';\n\n/** \n @notice \n Deploys splits payer contracts.\n\n @dev\n Adheres to -\n IJBETHERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBETHERC20SplitsPayerDeployer is IJBETHERC20SplitsPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBSplitsPayer splitsPayer) {\n // Deploy the splits payer.\n splitsPayer = new JBETHERC20SplitsPayer(\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeploySplitsPayer(\n splitsPayer,\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner,\n msg.sender\n );\n }\n}\n" + "contracts/JBGasTokenERC20SplitsPayerDeployer/2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './../interfaces/IJBGasTokenERC20SplitsPayerDeployer/2.sol';\nimport './../JBGasTokenERC20SplitsPayer/2.sol';\n\n/** \n @notice \n Deploys splits payer contracts.\n\n @dev\n Adheres to -\n IJBGasTokenERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBGasTokenERC20SplitsPayerDeployer is IJBGasTokenERC20SplitsPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBSplitsPayer splitsPayer) {\n // Deploy the splits payer.\n splitsPayer = new JBGasTokenERC20SplitsPayer(\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeploySplitsPayer(\n splitsPayer,\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner,\n msg.sender\n );\n }\n}\n" }, - "contracts/interfaces/IJBETHERC20SplitsPayerDeployer/2.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './../IJBSplitsPayer/2.sol';\nimport './../IJBSplitsStore/2.sol';\n\ninterface IJBETHERC20SplitsPayerDeployer {\n event DeploySplitsPayer(\n IJBSplitsPayer indexed splitsPayer,\n uint256 defaultSplitsProjectId,\n uint256 defaultSplitsDomain,\n uint256 defaultSplitsGroup,\n IJBSplitsStore splitsStore,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n address owner,\n address caller\n );\n\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string calldata _defaultMemo,\n bytes calldata _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n}\n" + "contracts/interfaces/IJBGasTokenERC20SplitsPayerDeployer/2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './../IJBSplitsPayer/2.sol';\nimport './../IJBSplitsStore/2.sol';\n\ninterface IJBGasTokenERC20SplitsPayerDeployer {\n event DeploySplitsPayer(\n IJBSplitsPayer indexed splitsPayer,\n uint256 defaultSplitsProjectId,\n uint256 defaultSplitsDomain,\n uint256 defaultSplitsGroup,\n IJBSplitsStore splitsStore,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n address owner,\n address caller\n );\n\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string calldata _defaultMemo,\n bytes calldata _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n}\n" }, "contracts/interfaces/IJBTerminalUtility.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './IJBDirectory.sol';\n\ninterface IJBPaymentTerminalUtility {\n function directory() external view returns (IJBDirectory);\n}\n" }, - "contracts/interfaces/IJBETHERC20ProjectPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './IJBDirectory.sol';\nimport './IJBProjectPayer.sol';\n\ninterface IJBETHERC20ProjectPayerDeployer {\n event DeployProjectPayer(\n IJBProjectPayer indexed projectPayer,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n IJBDirectory directory,\n address owner,\n address caller\n );\n\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external returns (IJBProjectPayer projectPayer);\n}\n" + "contracts/interfaces/IJBGasTokenERC20ProjectPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './IJBDirectory.sol';\nimport './IJBProjectPayer.sol';\n\ninterface IJBGasTokenERC20ProjectPayerDeployer {\n event DeployProjectPayer(\n IJBProjectPayer indexed projectPayer,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n IJBDirectory directory,\n address owner,\n address caller\n );\n\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external returns (IJBProjectPayer projectPayer);\n}\n" }, - "contracts/JBETHERC20ProjectPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './interfaces/IJBETHERC20ProjectPayerDeployer.sol';\nimport './JBETHERC20ProjectPayer.sol';\n\n/** \n @notice \n Deploys project payer contracts.\n\n @dev\n Adheres to -\n IJBETHERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBETHERC20ProjectPayerDeployer is IJBETHERC20ProjectPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new project payer contract.\n\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the project payer contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the project payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the project payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the project payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the project payer.\n\n @return projectPayer The project payer contract.\n */\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external override returns (IJBProjectPayer projectPayer) {\n // Deploy the project payer.\n projectPayer = new JBETHERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner\n );\n\n emit DeployProjectPayer(\n projectPayer,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner,\n msg.sender\n );\n }\n}\n" + "contracts/JBGasTokenERC20ProjectPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './interfaces/IJBGasTokenERC20ProjectPayerDeployer.sol';\nimport './JBGasTokenERC20ProjectPayer.sol';\n\n/** \n @notice \n Deploys project payer contracts.\n\n @dev\n Adheres to -\n IJBGasTokenERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBGasTokenERC20ProjectPayerDeployer is IJBGasTokenERC20ProjectPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new project payer contract.\n\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the project payer contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the project payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the project payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the project payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the project payer.\n\n @return projectPayer The project payer contract.\n */\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external override returns (IJBProjectPayer projectPayer) {\n // Deploy the project payer.\n projectPayer = new JBGasTokenERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner\n );\n\n emit DeployProjectPayer(\n projectPayer,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner,\n msg.sender\n );\n }\n}\n" }, "contracts/system_tests/TestLaunchProject.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './helpers/TestBaseWorkflow.sol';\n\ncontract TestLaunchProject is TestBaseWorkflow {\n JBController controller;\n JBProjectMetadata _projectMetadata;\n JBFundingCycleData _data;\n JBFundingCycleMetadata _metadata;\n JBGroupedSplits[] _groupedSplits; // Default empty\n JBFundAccessConstraints[] _fundAccessConstraints; // Default empty\n IJBPaymentTerminal[] _terminals; // Default empty\n\n function setUp() public override {\n super.setUp();\n\n controller = jbController();\n\n _projectMetadata = JBProjectMetadata({content: 'myIPFSHash', domain: 1});\n\n _data = JBFundingCycleData({\n duration: 14,\n weight: 1000 * 10**18,\n discountRate: 450000000,\n ballot: IJBFundingCycleBallot(address(0))\n });\n\n _metadata = JBFundingCycleMetadata({\n global: JBGlobalFundingCycleMetadata({allowSetTerminals: false, allowSetController: false}),\n reservedRate: 5000, //50%\n redemptionRate: 5000, //50%\n ballotRedemptionRate: 0,\n pausePay: false,\n pauseDistributions: false,\n pauseRedeem: false,\n pauseBurn: false,\n allowMinting: false,\n allowChangeToken: false,\n allowTerminalMigration: false,\n allowControllerMigration: false,\n holdFees: false,\n useTotalOverflowForRedemptions: false,\n useDataSourceForPay: false,\n useDataSourceForRedeem: false,\n dataSource: address(0)\n });\n }\n\n function testLaunchProject() public {\n uint256 projectId = controller.launchProjectFor(\n msg.sender,\n _projectMetadata,\n _data,\n _metadata,\n block.timestamp,\n _groupedSplits,\n _fundAccessConstraints,\n _terminals,\n ''\n );\n\n JBFundingCycle memory fundingCycle = jbFundingCycleStore().currentOf(projectId); //, latestConfig);\n\n assertEq(fundingCycle.number, 1);\n assertEq(fundingCycle.weight, 1000 * 10**18);\n }\n\n function testLaunchProjectFuzzWeight(uint256 WEIGHT) public {\n _data = JBFundingCycleData({\n duration: 14,\n weight: WEIGHT,\n discountRate: 450000000,\n ballot: IJBFundingCycleBallot(address(0))\n });\n\n uint256 projectId;\n\n // expectRevert on the next call if weight overflowing\n if (WEIGHT > type(uint88).max) {\n evm.expectRevert(abi.encodeWithSignature('INVALID_WEIGHT()'));\n\n projectId = controller.launchProjectFor(\n msg.sender,\n _projectMetadata,\n _data,\n _metadata,\n block.timestamp,\n _groupedSplits,\n _fundAccessConstraints,\n _terminals,\n ''\n );\n } else {\n projectId = controller.launchProjectFor(\n msg.sender,\n _projectMetadata,\n _data,\n _metadata,\n block.timestamp,\n _groupedSplits,\n _fundAccessConstraints,\n _terminals,\n ''\n );\n\n JBFundingCycle memory fundingCycle = jbFundingCycleStore().currentOf(projectId); //, latestConfig);\n\n assertEq(fundingCycle.number, 1);\n assertEq(fundingCycle.weight, WEIGHT);\n }\n }\n}\n" diff --git a/deployments/mainnet/solcInputs/4138c0c854528929e18f6ccc34d600b0.json b/deployments/mainnet/solcInputs/4138c0c854528929e18f6ccc34d600b0.json index f1b1b7fac..92d17410b 100644 --- a/deployments/mainnet/solcInputs/4138c0c854528929e18f6ccc34d600b0.json +++ b/deployments/mainnet/solcInputs/4138c0c854528929e18f6ccc34d600b0.json @@ -119,13 +119,13 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport './abstract/JBOperatable.sol';\nimport './interfaces/IJBDirectory.sol';\nimport './libraries/JBGlobalFundingCycleMetadataResolver.sol';\nimport './libraries/JBOperations.sol';\n\n/**\n @notice\n Keeps a reference of which terminal contracts each project is currently accepting funds through, and which controller contract is managing each project's tokens and funding cycles.\n\n @dev\n Adheres to -\n IJBDirectory: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\ncontract JBDirectory is IJBDirectory, JBOperatable, Ownable {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBGlobalFundingCycleMetadataResolver for uint8;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error DUPLICATE_TERMINALS();\n error INVALID_PROJECT_ID_IN_DIRECTORY();\n error SET_CONTROLLER_NOT_ALLOWED();\n error SET_TERMINALS_NOT_ALLOWED();\n error TOKEN_NOT_ACCEPTED();\n\n //*********************************************************************//\n // --------------------- private stored properties ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n For each project ID, the terminals that are currently managing its funds.\n\n _projectId The ID of the project to get terminals of.\n */\n mapping(uint256 => IJBPaymentTerminal[]) private _terminalsOf;\n\n /**\n @notice\n The project's primary terminal for a token.\n\n _projectId The ID of the project to get the primary terminal of.\n _token The token to get the project's primary terminal of.\n */\n mapping(uint256 => mapping(address => IJBPaymentTerminal)) private _primaryTerminalOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n For each project ID, the controller that manages how terminals interact with tokens and funding cycles.\n\n _projectId The ID of the project to get the controller of.\n */\n mapping(uint256 => address) public override controllerOf;\n\n /**\n @notice\n Addresses that can set a project's first controller on their behalf. These addresses/contracts have been vetted and verified by this contract's owner.\n\n _address The address that is either allowed or not.\n */\n mapping(address => bool) public override isAllowedToSetFirstController;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n For each project ID, the terminals that are currently managing its funds.\n\n @param _projectId The ID of the project to get terminals of.\n\n @return An array of terminal addresses.\n */\n function terminalsOf(uint256 _projectId)\n external\n view\n override\n returns (IJBPaymentTerminal[] memory)\n {\n return _terminalsOf[_projectId];\n }\n\n /**\n @notice\n The primary terminal that is managing funds for a project for a specified token.\n\n @dev\n The zero address is returned if a terminal isn't found for the specified token.\n\n @param _projectId The ID of the project to get a terminal for.\n @param _token The token the terminal accepts.\n\n @return The primary terminal for the project for the specified token.\n */\n function primaryTerminalOf(uint256 _projectId, address _token)\n external\n view\n override\n returns (IJBPaymentTerminal)\n {\n // If a primary terminal for the token was specifically set and its one of the project's terminals, return it.\n if (\n _primaryTerminalOf[_projectId][_token] != IJBPaymentTerminal(address(0)) &&\n isTerminalOf(_projectId, _primaryTerminalOf[_projectId][_token])\n ) return _primaryTerminalOf[_projectId][_token];\n\n // Return the first terminal which accepts the specified token.\n for (uint256 _i; _i < _terminalsOf[_projectId].length; _i++) {\n IJBPaymentTerminal _terminal = _terminalsOf[_projectId][_i];\n if (_terminal.acceptsToken(_token, _projectId)) return _terminal;\n }\n\n // Not found.\n return IJBPaymentTerminal(address(0));\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Whether or not a specified terminal is a terminal of the specified project.\n\n @param _projectId The ID of the project to check within.\n @param _terminal The address of the terminal to check for.\n\n @return A flag indicating whether or not the specified terminal is a terminal of the specified project.\n */\n function isTerminalOf(uint256 _projectId, IJBPaymentTerminal _terminal)\n public\n view\n override\n returns (bool)\n {\n for (uint256 _i; _i < _terminalsOf[_projectId].length; _i++)\n if (_terminalsOf[_projectId][_i] == _terminal) return true;\n return false;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _owner The address that will own the contract.\n */\n constructor(\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBFundingCycleStore _fundingCycleStore,\n address _owner\n ) JBOperatable(_operatorStore) {\n projects = _projects;\n fundingCycleStore = _fundingCycleStore;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Update the controller that manages how terminals interact with the ecosystem.\n\n @dev\n A controller can be set if:\n - the message sender is the project owner or an operator having the correct authorization.\n - the message sender is the project's current controller.\n - or, an allowedlisted address is setting a controller for a project that doesn't already have a controller.\n\n @param _projectId The ID of the project to set a new controller for.\n @param _controller The new controller to set.\n */\n function setControllerOf(uint256 _projectId, address _controller)\n external\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.SET_CONTROLLER,\n (msg.sender == address(controllerOf[_projectId]) ||\n (isAllowedToSetFirstController[msg.sender] && controllerOf[_projectId] == address(0)))\n )\n {\n // The project must exist.\n if (projects.count() < _projectId) revert INVALID_PROJECT_ID_IN_DIRECTORY();\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Setting controller is allowed if called from the current controller, or if the project doesn't have a current controller, or if the project's funding cycle allows setting the controller. Revert otherwise.\n if (\n msg.sender != address(controllerOf[_projectId]) &&\n controllerOf[_projectId] != address(0) &&\n !uint8(_fundingCycle.metadata >> 8).setControllerAllowed()\n ) revert SET_CONTROLLER_NOT_ALLOWED();\n\n // Set the new controller.\n controllerOf[_projectId] = _controller;\n\n emit SetController(_projectId, _controller, msg.sender);\n }\n\n /** \n @notice \n Set a project's terminals.\n\n @dev\n Only a project owner, an operator, or its controller can set its terminals.\n\n @param _projectId The ID of the project having terminals set.\n @param _terminals The terminal to set.\n */\n function setTerminalsOf(uint256 _projectId, IJBPaymentTerminal[] calldata _terminals)\n external\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.SET_TERMINALS,\n msg.sender == address(controllerOf[_projectId])\n )\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Setting terminals must be allowed if not called from the current controller.\n if (\n msg.sender != address(controllerOf[_projectId]) &&\n !uint8(_fundingCycle.metadata >> 8).setTerminalsAllowed()\n ) revert SET_TERMINALS_NOT_ALLOWED();\n\n // Delete the stored terminals for the project.\n _terminalsOf[_projectId] = _terminals;\n\n // Make sure duplicates were not added.\n if (_terminals.length > 1)\n for (uint256 _i; _i < _terminals.length; _i++)\n for (uint256 _j = _i + 1; _j < _terminals.length; _j++)\n if (_terminals[_i] == _terminals[_j]) revert DUPLICATE_TERMINALS();\n\n emit SetTerminals(_projectId, _terminals, msg.sender);\n }\n\n /**\n @notice\n Project's can set which terminal should be their primary for a particular token.\n This is useful in case a project has several terminals connected for a particular token.\n\n @dev\n The terminal will be set as the primary terminal where ecosystem contracts should route tokens.\n\n @dev\n If setting a newly added terminal and the funding cycle doesn't allow new terminals, the caller must be the current controller.\n\n @param _projectId The ID of the project for which a primary token is being set.\n @param _token The token to set the primary terminal of.\n @param _terminal The terminal to make primary.\n */\n function setPrimaryTerminalOf(\n uint256 _projectId,\n address _token,\n IJBPaymentTerminal _terminal\n )\n external\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.SET_PRIMARY_TERMINAL)\n {\n // Can't set the primary terminal for a token if it doesn't accept the token.\n if (!_terminal.acceptsToken(_token, _projectId)) revert TOKEN_NOT_ACCEPTED();\n\n // Add the terminal to the project if it hasn't been already.\n _addTerminalIfNeeded(_projectId, _terminal);\n\n // Store the terminal as the primary for the particular token.\n _primaryTerminalOf[_projectId][_token] = _terminal;\n\n emit SetPrimaryTerminal(_projectId, _token, _terminal, msg.sender);\n }\n\n /** \n @notice\t\n Set a contract to the list of trusted addresses that can set a first controller for any project.\t\n\n @dev\n The owner can add addresses which are allowed to change projects' first controllers. \n These addresses are known and vetted controllers as well as contracts designed to launch new projects. \n A project can set its own controller without it being on the allow list.\n\n @dev\n If you would like an address/contract allowlisted, please reach out to the contract owner.\n\n @param _address The address to allow or revoke allowance from.\n @param _flag Whether allowance is being added or revoked.\n */\n function setIsAllowedToSetFirstController(address _address, bool _flag)\n external\n override\n onlyOwner\n {\n // Set the flag in the allowlist.\n isAllowedToSetFirstController[_address] = _flag;\n\n emit SetIsAllowedToSetFirstController(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Add a terminal to a project's list of terminals if it hasn't been already.\n\n @param _projectId The ID of the project having a terminal added.\n @param _terminal The terminal to add.\n */\n function _addTerminalIfNeeded(uint256 _projectId, IJBPaymentTerminal _terminal) private {\n // Check that the terminal has not already been added.\n if (isTerminalOf(_projectId, _terminal)) return;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Setting terminals must be allowed if not called from the current controller.\n if (\n msg.sender != address(controllerOf[_projectId]) &&\n !uint8(_fundingCycle.metadata >> 8).setTerminalsAllowed()\n ) revert SET_TERMINALS_NOT_ALLOWED();\n\n // Add the new terminal.\n _terminalsOf[_projectId].push(_terminal);\n\n emit AddTerminal(_projectId, _terminal, msg.sender);\n }\n}\n" }, "contracts/JBETHPaymentTerminal/1.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './../abstract/JBPayoutRedemptionPaymentTerminal/1.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n JBTokens.ETH,\n 18, // 18 decimals.\n JBCurrencies.ETH,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal pure override {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './../abstract/JBPayoutRedemptionPaymentTerminal/1.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n JBTokens.GAS_TOKEN,\n 18, // 18 decimals.\n JBCurrencies.GAS_CURRENCY,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal pure override {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n}\n" }, "contracts/JBERC20PaymentTerminal/1.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol';\nimport './../abstract/JBPayoutRedemptionPaymentTerminal/1.sol';\n\n/** \n @notice \n Manages the inflows and outflows of an ERC-20 token.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\ncontract JBERC20PaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n IERC20Metadata _token,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n address(_token),\n _token.decimals(),\n _currency,\n _baseWeightCurrency,\n _payoutSplitsGroup,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from == address(this)\n ? IERC20(token).transfer(_to, _amount)\n : IERC20(token).transferFrom(_from, _to, _amount);\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal override {\n IERC20(token).approve(_to, _amount);\n }\n}\n" }, "contracts/JBSingleTokenPaymentTerminalStore/1.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController/1.sol';\nimport './../interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBSingleTokenPaymentTerminalStore is IJBSingleTokenPaymentTerminalStore, ReentrancyGuard {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n Mint's 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegate A delegate contract to use for subsequent calls.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n IJBPayDelegate delegate,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay()) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegate) = IJBFundingCycleDataSource(fundingCycle.dataSource()).payParams(\n _data\n );\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegate, memo);\n\n // Add the amount to the token balance of the project.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount.value;\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegate, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegate A delegate contract to use for subsequent calls.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n IJBRedemptionDelegate delegate,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\n _projectId,\n fundingCycle.reservedRate()\n );\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow > 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem()) {\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n fundingCycle.redemptionRate(),\n fundingCycle.ballotRedemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegate) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .redeemParams(_data);\n } else {\n memo = _memo;\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (reclaimAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (reclaimAmount > 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n reclaimAmount;\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n return _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i = 0; _i < _terminals.length; _i++)\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.ETH\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.ETH, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController/1.sol';\nimport './../interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBSingleTokenPaymentTerminalStore is IJBSingleTokenPaymentTerminalStore, ReentrancyGuard {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n Mint's 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegate A delegate contract to use for subsequent calls.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n IJBPayDelegate delegate,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay()) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegate) = IJBFundingCycleDataSource(fundingCycle.dataSource()).payParams(\n _data\n );\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegate, memo);\n\n // Add the amount to the token balance of the project.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount.value;\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegate, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegate A delegate contract to use for subsequent calls.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n IJBRedemptionDelegate delegate,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\n _projectId,\n fundingCycle.reservedRate()\n );\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow > 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem()) {\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n fundingCycle.redemptionRate(),\n fundingCycle.ballotRedemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegate) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .redeemParams(_data);\n } else {\n memo = _memo;\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (reclaimAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (reclaimAmount > 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n reclaimAmount;\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n return _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i = 0; _i < _terminals.length; _i++)\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.GAS_CURRENCY\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.GAS_CURRENCY, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" }, "contracts/JBFundingCycleStore/1.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../abstract/JBControllerUtility.sol';\nimport './../libraries/JBConstants.sol';\n\n/** \n @notice \n Manages funding cycle configurations and scheduling.\n\n @dev\n Adheres to -\n IJBTokenStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBControllerUtility: Includes convenience functionality for checking if the message sender is the current controller of the project whose data is being manipulated.\n*/\ncontract JBFundingCycleStore is IJBFundingCycleStore, JBControllerUtility {\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_DISCOUNT_RATE();\n error INVALID_DURATION();\n error INVALID_WEIGHT();\n error NO_SAME_BLOCK_RECONFIGURATION();\n\n //*********************************************************************//\n // --------------------- private stored properties ------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Stores the user defined properties of each funding cycle, packed into one storage slot.\n\n _projectId The ID of the project to get properties of.\n _configuration The funding cycle configuration to get properties of.\n */\n mapping(uint256 => mapping(uint256 => uint256)) private _packedUserPropertiesOf;\n\n /** \n @notice\n Stores the properties added by the mechanism to manage and schedule each funding cycle, packed into one storage slot.\n \n _projectId The ID of the project to get instrinsic properties of.\n _configuration The funding cycle configuration to get properties of.\n */\n mapping(uint256 => mapping(uint256 => uint256)) private _packedIntrinsicPropertiesOf;\n\n /** \n @notice\n Stores the metadata for each funding cycle configuration, packed into one storage slot.\n\n _projectId The ID of the project to get metadata of.\n _configuration The funding cycle configuration to get metadata of.\n */\n mapping(uint256 => mapping(uint256 => uint256)) private _metadataOf;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The latest funding cycle configuration for each project.\n\n _projectId The ID of the project to get the latest funding cycle configuration of.\n */\n mapping(uint256 => uint256) public override latestConfigurationOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice \n Get the funding cycle with the given configuration for the specified project.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n @param _configuration The configuration of the funding cycle to get.\n\n @return fundingCycle The funding cycle.\n */\n function get(uint256 _projectId, uint256 _configuration)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle)\n {\n return _getStructFor(_projectId, _configuration);\n }\n\n /**\n @notice \n The latest funding cycle to be configured for the specified project, and its current ballot state.\n\n @param _projectId The ID of the project to get the latest configured funding cycle of.\n\n @return fundingCycle The project's queued funding cycle.\n @return ballotState The state of the ballot for the reconfiguration.\n */\n function latestConfiguredOf(uint256 _projectId)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle, JBBallotState ballotState)\n {\n // Get a reference to the latest funding cycle configuration.\n uint256 _fundingCycleConfiguration = latestConfigurationOf[_projectId];\n\n // Resolve the funding cycle for the latest configuration.\n fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n // Resolve the ballot state.\n ballotState = _ballotStateOf(\n _projectId,\n fundingCycle.configuration,\n fundingCycle.start,\n fundingCycle.basedOn\n );\n }\n\n /**\n @notice \n The funding cycle that's next up for the specified project.\n\n @dev\n If a queued funding cycle of the project is not found, returns an empty funding cycle with all properties set to 0.\n\n @param _projectId The ID of the project to get the queued funding cycle of.\n\n @return fundingCycle The project's queued funding cycle.\n */\n function queuedOf(uint256 _projectId)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle)\n {\n // If the project does not have a funding cycle, return an empty struct.\n if (latestConfigurationOf[_projectId] == 0) return _getStructFor(0, 0);\n\n // Get a reference to the configuration of the standby funding cycle.\n uint256 _standbyFundingCycleConfiguration = _standbyOf(_projectId);\n\n // If it exists, return its funding cycle if it is approved.\n if (_standbyFundingCycleConfiguration > 0) {\n fundingCycle = _getStructFor(_projectId, _standbyFundingCycleConfiguration);\n\n if (_isApproved(_projectId, fundingCycle)) return fundingCycle;\n\n // Resolve the funding cycle for the latest configured funding cycle.\n fundingCycle = _getStructFor(_projectId, fundingCycle.basedOn);\n } else {\n // Resolve the funding cycle for the latest configured funding cycle.\n fundingCycle = _getStructFor(_projectId, latestConfigurationOf[_projectId]);\n\n // If the latest funding cycle starts in the future, it must start in the distant future\n // since its not in standby. In this case base the queued cycles on the base cycle.\n if (fundingCycle.start > block.timestamp)\n fundingCycle = _getStructFor(_projectId, fundingCycle.basedOn);\n }\n\n // There's no queued if the current has a duration of 0.\n if (fundingCycle.duration == 0) return _getStructFor(0, 0);\n\n // Check to see if this funding cycle's ballot is approved.\n // If so, return a funding cycle based on it.\n if (_isApproved(_projectId, fundingCycle)) return _mockFundingCycleBasedOn(fundingCycle, false);\n\n // Get the funding cycle of its base funding cycle, which carries the last approved configuration.\n fundingCycle = _getStructFor(_projectId, fundingCycle.basedOn);\n\n // There's no queued if the base, which must still be the current, has a duration of 0.\n if (fundingCycle.duration == 0) return _getStructFor(0, 0);\n\n // Return a mock of the next up funding cycle.\n return _mockFundingCycleBasedOn(fundingCycle, false);\n }\n\n /**\n @notice \n The funding cycle that is currently active for the specified project.\n\n @dev\n If a current funding cycle of the project is not found, returns an empty funding cycle with all properties set to 0.\n\n @param _projectId The ID of the project to get the current funding cycle of.\n\n @return fundingCycle The project's current funding cycle.\n */\n function currentOf(uint256 _projectId)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle)\n {\n // If the project does not have a funding cycle, return an empty struct.\n if (latestConfigurationOf[_projectId] == 0) return _getStructFor(0, 0);\n\n // Get a reference to the configuration of the eligible funding cycle.\n uint256 _fundingCycleConfiguration = _eligibleOf(_projectId);\n\n // Keep a reference to the eligible funding cycle.\n JBFundingCycle memory _fundingCycle;\n\n // If an eligible funding cycle exists...\n if (_fundingCycleConfiguration > 0) {\n // Resolve the funding cycle for the eligible configuration.\n _fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n // Check to see if this funding cycle's ballot is approved.\n // If so, return it.\n if (_isApproved(_projectId, _fundingCycle)) return _fundingCycle;\n\n // If it hasn't been approved, set the funding cycle configuration to be the configuration of the funding cycle that it's based on,\n // which carries the last approved configuration.\n _fundingCycleConfiguration = _fundingCycle.basedOn;\n } else {\n // No upcoming funding cycle found that is eligible to become active,\n // so use the last configuration.\n _fundingCycleConfiguration = latestConfigurationOf[_projectId];\n\n // Get the funding cycle for the latest ID.\n _fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n // If it's not approved or if it hasn't yet started, get a reference to the funding cycle that the latest is based on, which has the latest approved configuration.\n if (!_isApproved(_projectId, _fundingCycle) || block.timestamp < _fundingCycle.start)\n _fundingCycleConfiguration = _fundingCycle.basedOn;\n }\n\n // If there is not funding cycle to base the current one on, there can't be a current one.\n if (_fundingCycleConfiguration == 0) return _getStructFor(0, 0);\n\n // The funding cycle to base a current one on.\n _fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n // If the base has no duration, it's still the current one.\n if (_fundingCycle.duration == 0) return _fundingCycle;\n\n // Return a mock of the current funding cycle.\n return _mockFundingCycleBasedOn(_fundingCycle, true);\n }\n\n /** \n @notice \n The current ballot state of the project.\n\n @param _projectId The ID of the project to check the ballot state of.\n\n @return The project's current ballot's state.\n */\n function currentBallotStateOf(uint256 _projectId) external view override returns (JBBallotState) {\n // Get a reference to the latest funding cycle configuration.\n uint256 _fundingCycleConfiguration = latestConfigurationOf[_projectId];\n\n // Resolve the funding cycle for the latest configuration.\n JBFundingCycle memory _fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n return\n _ballotStateOf(\n _projectId,\n _fundingCycle.configuration,\n _fundingCycle.start,\n _fundingCycle.basedOn\n );\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _directory A contract storing directories of terminals and controllers for each project.\n */\n // solhint-disable-next-line no-empty-blocks\n constructor(IJBDirectory _directory) JBControllerUtility(_directory) {}\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice \n Configures the next eligible funding cycle for the specified project.\n\n @dev\n Only a project's current controller can configure its funding cycles.\n\n @param _projectId The ID of the project being configured.\n @param _data The funding cycle configuration data.\n @param _metadata Arbitrary extra data to associate with this funding cycle configuration that's not used within.\n @param _mustStartAtOrAfter The time before which the initialized funding cycle cannot start.\n\n @return The funding cycle that the configuration will take effect during.\n */\n function configureFor(\n uint256 _projectId,\n JBFundingCycleData calldata _data,\n uint256 _metadata,\n uint256 _mustStartAtOrAfter\n ) external override onlyController(_projectId) returns (JBFundingCycle memory) {\n // Duration must fit in a uint64.\n if (_data.duration > type(uint64).max) revert INVALID_DURATION();\n\n // Discount rate must be less than or equal to 100%.\n if (_data.discountRate > JBConstants.MAX_DISCOUNT_RATE) revert INVALID_DISCOUNT_RATE();\n\n // Weight must fit into a uint88.\n if (_data.weight > type(uint88).max) revert INVALID_WEIGHT();\n\n // The configuration timestamp is now.\n uint256 _configuration = block.timestamp;\n\n // Set up a reconfiguration by configuring intrinsic properties.\n _configureIntrinsicPropertiesFor(\n _projectId,\n _configuration,\n _data.weight,\n // Must start on or after the current timestamp.\n _mustStartAtOrAfter > block.timestamp ? _mustStartAtOrAfter : block.timestamp\n );\n\n // Efficiently stores a funding cycles provided user defined properties.\n // If all user config properties are zero, no need to store anything as the default value will have the same outcome.\n if (\n _data.ballot != IJBFundingCycleBallot(address(0)) ||\n _data.duration > 0 ||\n _data.discountRate > 0\n ) {\n // ballot in bits 0-159 bytes.\n uint256 packed = uint160(address(_data.ballot));\n\n // duration in bits 160-223 bytes.\n packed |= _data.duration << 160;\n\n // discountRate in bits 224-255 bytes.\n packed |= _data.discountRate << 224;\n\n // Set in storage.\n _packedUserPropertiesOf[_projectId][_configuration] = packed;\n }\n\n // Set the metadata if needed.\n if (_metadata > 0) _metadataOf[_projectId][_configuration] = _metadata;\n\n emit Configure(_configuration, _projectId, _data, _metadata, _mustStartAtOrAfter, msg.sender);\n\n // Return the funding cycle for the new configuration.\n return _getStructFor(_projectId, _configuration);\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice \n Updates the configurable funding cycle for this project if it exists, otherwise creates one.\n\n @param _projectId The ID of the project to find a configurable funding cycle for.\n @param _configuration The time at which the funding cycle was configured.\n @param _weight The weight to store in the configured funding cycle.\n @param _mustStartAtOrAfter The time before which the initialized funding cycle can't start.\n */\n function _configureIntrinsicPropertiesFor(\n uint256 _projectId,\n uint256 _configuration,\n uint256 _weight,\n uint256 _mustStartAtOrAfter\n ) private {\n // If there's not yet a funding cycle for the project, initialize one.\n if (latestConfigurationOf[_projectId] == 0)\n // Use an empty funding cycle as the base.\n return\n _initFor(_projectId, _getStructFor(0, 0), _configuration, _mustStartAtOrAfter, _weight);\n\n // Get the active funding cycle's configuration.\n uint256 _currentConfiguration = _eligibleOf(_projectId);\n\n // If an eligible funding cycle does not exist, get a reference to the latest funding cycle configuration for the project.\n if (_currentConfiguration == 0)\n // Get the latest funding cycle's configuration.\n _currentConfiguration = latestConfigurationOf[_projectId];\n\n // Get a reference to the funding cycle.\n JBFundingCycle memory _baseFundingCycle = _getStructFor(_projectId, _currentConfiguration);\n\n if (!_isApproved(_projectId, _baseFundingCycle))\n // If it hasn't been approved, set the ID to be the funding cycle it's based on,\n // which carries the latest approved configuration.\n _baseFundingCycle = _getStructFor(_projectId, _baseFundingCycle.basedOn);\n\n // The configuration can't be the same as the base configuration.\n if (_baseFundingCycle.configuration == _configuration) revert NO_SAME_BLOCK_RECONFIGURATION();\n\n // The time after the ballot of the provided funding cycle has expired.\n // If the provided funding cycle has no ballot, return the current timestamp.\n uint256 _timestampAfterBallot = _baseFundingCycle.ballot == IJBFundingCycleBallot(address(0))\n ? 0\n : _configuration + _baseFundingCycle.ballot.duration();\n\n _initFor(\n _projectId,\n _baseFundingCycle,\n _configuration,\n // Can only start after the ballot.\n _timestampAfterBallot > _mustStartAtOrAfter ? _timestampAfterBallot : _mustStartAtOrAfter,\n _weight\n );\n }\n\n /**\n @notice \n Initializes a funding cycle with the specified properties.\n\n @param _projectId The ID of the project to which the funding cycle being initialized belongs.\n @param _baseFundingCycle The funding cycle to base the initialized one on.\n @param _configuration The configuration of the funding cycle being initialized.\n @param _mustStartAtOrAfter The time before which the initialized funding cycle cannot start.\n @param _weight The weight to give the newly initialized funding cycle.\n */\n function _initFor(\n uint256 _projectId,\n JBFundingCycle memory _baseFundingCycle,\n uint256 _configuration,\n uint256 _mustStartAtOrAfter,\n uint256 _weight\n ) private {\n // If there is no base, initialize a first cycle.\n if (_baseFundingCycle.number == 0) {\n // The first number is 1.\n uint256 _number = 1;\n\n // Set fresh intrinsic properties.\n _packAndStoreIntrinsicPropertiesOf(\n _configuration,\n _projectId,\n _number,\n _weight,\n _baseFundingCycle.configuration,\n _mustStartAtOrAfter\n );\n } else {\n // Derive the correct next start time from the base.\n uint256 _start = _deriveStartFrom(_baseFundingCycle, _mustStartAtOrAfter);\n\n // A weight of 1 is treated as a weight of 0.\n // This is to allow a weight of 0 (default) to represent inheriting the discounted weight of the previous funding cycle.\n _weight = _weight > 0\n ? (_weight == 1 ? 0 : _weight)\n : _deriveWeightFrom(_baseFundingCycle, _start);\n\n // Derive the correct number.\n uint256 _number = _deriveNumberFrom(_baseFundingCycle, _start);\n\n // Update the intrinsic properties.\n _packAndStoreIntrinsicPropertiesOf(\n _configuration,\n _projectId,\n _number,\n _weight,\n _baseFundingCycle.configuration,\n _start\n );\n }\n\n // Set the project's latest funding cycle configuration.\n latestConfigurationOf[_projectId] = _configuration;\n\n emit Init(_configuration, _projectId, _baseFundingCycle.configuration);\n }\n\n /**\n @notice \n Efficiently stores a funding cycle's provided intrinsic properties.\n\n @param _configuration The configuration of the funding cycle to pack and store.\n @param _projectId The ID of the project to which the funding cycle belongs.\n @param _number The number of the funding cycle.\n @param _weight The weight of the funding cycle.\n @param _basedOn The configuration of the base funding cycle.\n @param _start The start time of this funding cycle.\n */\n function _packAndStoreIntrinsicPropertiesOf(\n uint256 _configuration,\n uint256 _projectId,\n uint256 _number,\n uint256 _weight,\n uint256 _basedOn,\n uint256 _start\n ) private {\n // weight in bits 0-87.\n uint256 packed = _weight;\n\n // basedOn in bits 88-143.\n packed |= _basedOn << 88;\n\n // start in bits 144-199.\n packed |= _start << 144;\n\n // number in bits 200-255.\n packed |= _number << 200;\n\n // Store the packed value.\n _packedIntrinsicPropertiesOf[_projectId][_configuration] = packed;\n }\n\n /**\n @notice \n The project's stored funding cycle that hasn't yet started and should be used next, if one exists.\n\n @dev\n A value of 0 is returned if no funding cycle was found.\n\n @dev\n Assumes the project has a latest configuration.\n \n @param _projectId The ID of a project to look through for a standby cycle.\n\n @return configuration The configuration of the standby funding cycle if one exists, or 0 if one doesn't exist.\n */\n function _standbyOf(uint256 _projectId) private view returns (uint256 configuration) {\n // Get a reference to the project's latest funding cycle.\n configuration = latestConfigurationOf[_projectId];\n\n // Get the necessary properties for the latest funding cycle.\n JBFundingCycle memory _fundingCycle = _getStructFor(_projectId, configuration);\n\n // There is no upcoming funding cycle if the latest funding cycle has already started.\n if (block.timestamp >= _fundingCycle.start) return 0;\n\n // If this is the first funding cycle, it is queued.\n if (_fundingCycle.number == 1) return configuration;\n\n // Get the necessary properties for the base funding cycle.\n JBFundingCycle memory _baseFundingCycle = _getStructFor(_projectId, _fundingCycle.basedOn);\n\n // If the latest configuration doesn't start until after another base cycle, return 0.\n if (\n _baseFundingCycle.duration > 0 &&\n block.timestamp < _fundingCycle.start - _baseFundingCycle.duration\n ) return 0;\n }\n\n /**\n @notice \n The project's stored funding cycle that has started and hasn't yet expired.\n \n @dev\n A value of 0 is returned if no funding cycle was found.\n\n @dev\n Assumes the project has a latest configuration.\n\n @param _projectId The ID of the project to look through.\n\n @return configuration The configuration of an eligible funding cycle if one exists, or 0 if one doesn't exist.\n */\n function _eligibleOf(uint256 _projectId) private view returns (uint256 configuration) {\n // Get a reference to the project's latest funding cycle.\n configuration = latestConfigurationOf[_projectId];\n\n // Get the latest funding cycle.\n JBFundingCycle memory _fundingCycle = _getStructFor(_projectId, configuration);\n\n // If the latest is expired, return an empty funding cycle.\n // A duration of 0 cannot be expired.\n if (\n _fundingCycle.duration > 0 && block.timestamp >= _fundingCycle.start + _fundingCycle.duration\n ) return 0;\n\n // Return the funding cycle's configuration if it has started.\n if (block.timestamp >= _fundingCycle.start) return _fundingCycle.configuration;\n\n // Get a reference to the cycle's base configuration.\n JBFundingCycle memory _baseFundingCycle = _getStructFor(_projectId, _fundingCycle.basedOn);\n\n // If the base cycle isn't eligible, the project has no eligible cycle.\n // A duration of 0 is always eligible.\n if (\n _baseFundingCycle.duration > 0 &&\n block.timestamp >= _baseFundingCycle.start + _baseFundingCycle.duration\n ) return 0;\n\n // Return the configuration that the latest funding cycle is based on.\n configuration = _fundingCycle.basedOn;\n }\n\n /** \n @notice \n A view of the funding cycle that would be created based on the provided one if the project doesn't make a reconfiguration.\n\n @dev\n Returns an empty funding cycle if there can't be a mock funding cycle based on the provided one.\n\n @dev\n Assumes a funding cycle with a duration of 0 will never be asked to be the base of a mock.\n\n @param _baseFundingCycle The funding cycle that the resulting funding cycle should follow.\n @param _allowMidCycle A flag indicating if the mocked funding cycle is allowed to already be mid cycle.\n\n @return A mock of what the next funding cycle will be.\n */\n function _mockFundingCycleBasedOn(JBFundingCycle memory _baseFundingCycle, bool _allowMidCycle)\n private\n view\n returns (JBFundingCycle memory)\n {\n // Get the distance of the current time to the start of the next possible funding cycle.\n // If the returned mock cycle must not yet have started, the start time of the mock must be in the future.\n uint256 _mustStartAtOrAfter = !_allowMidCycle\n ? block.timestamp + 1\n : block.timestamp - _baseFundingCycle.duration + 1;\n\n // Derive what the start time should be.\n uint256 _start = _deriveStartFrom(_baseFundingCycle, _mustStartAtOrAfter);\n\n // Derive what the number should be.\n uint256 _number = _deriveNumberFrom(_baseFundingCycle, _start);\n\n return\n JBFundingCycle(\n _number,\n _baseFundingCycle.configuration,\n _baseFundingCycle.basedOn,\n _start,\n _baseFundingCycle.duration,\n _deriveWeightFrom(_baseFundingCycle, _start),\n _baseFundingCycle.discountRate,\n _baseFundingCycle.ballot,\n _baseFundingCycle.metadata\n );\n }\n\n /** \n @notice \n The date that is the nearest multiple of the specified funding cycle's duration from its end.\n\n @param _baseFundingCycle The funding cycle to base the calculation on.\n @param _mustStartAtOrAfter A date that the derived start must be on or come after.\n\n @return start The next start time.\n */\n function _deriveStartFrom(JBFundingCycle memory _baseFundingCycle, uint256 _mustStartAtOrAfter)\n private\n pure\n returns (uint256 start)\n {\n // A subsequent cycle to one with a duration of 0 should start as soon as possible.\n if (_baseFundingCycle.duration == 0) return _mustStartAtOrAfter;\n\n // The time when the funding cycle immediately after the specified funding cycle starts.\n uint256 _nextImmediateStart = _baseFundingCycle.start + _baseFundingCycle.duration;\n\n // If the next immediate start is now or in the future, return it.\n if (_nextImmediateStart >= _mustStartAtOrAfter) return _nextImmediateStart;\n\n // The amount of seconds since the `_mustStartAtOrAfter` time which results in a start time that might satisfy the specified constraints.\n uint256 _timeFromImmediateStartMultiple = (_mustStartAtOrAfter - _nextImmediateStart) %\n _baseFundingCycle.duration;\n\n // A reference to the first possible start timestamp.\n start = _mustStartAtOrAfter - _timeFromImmediateStartMultiple;\n\n // Add increments of duration as necessary to satisfy the threshold.\n while (_mustStartAtOrAfter > start) start = start + _baseFundingCycle.duration;\n }\n\n /** \n @notice \n The accumulated weight change since the specified funding cycle.\n\n @param _baseFundingCycle The funding cycle to base the calculation on.\n @param _start The start time of the funding cycle to derive a number for.\n\n @return weight The derived weight, as a fixed point number with 18 decimals.\n */\n function _deriveWeightFrom(JBFundingCycle memory _baseFundingCycle, uint256 _start)\n private\n pure\n returns (uint256 weight)\n {\n // A subsequent cycle to one with a duration of 0 should have the next possible weight.\n if (_baseFundingCycle.duration == 0)\n return\n PRBMath.mulDiv(\n _baseFundingCycle.weight,\n JBConstants.MAX_DISCOUNT_RATE - _baseFundingCycle.discountRate,\n JBConstants.MAX_DISCOUNT_RATE\n );\n\n // The weight should be based off the base funding cycle's weight.\n weight = _baseFundingCycle.weight;\n\n // If the discount is 0, the weight doesn't change.\n if (_baseFundingCycle.discountRate == 0) return weight;\n\n // The difference between the start of the base funding cycle and the proposed start.\n uint256 _startDistance = _start - _baseFundingCycle.start;\n\n // Apply the base funding cycle's discount rate for each cycle that has passed.\n uint256 _discountMultiple = _startDistance / _baseFundingCycle.duration;\n\n for (uint256 i = 0; i < _discountMultiple; i++) {\n // The number of times to apply the discount rate.\n // Base the new weight on the specified funding cycle's weight.\n weight = PRBMath.mulDiv(\n weight,\n JBConstants.MAX_DISCOUNT_RATE - _baseFundingCycle.discountRate,\n JBConstants.MAX_DISCOUNT_RATE\n );\n // The calculation doesn't need to continue if the weight is 0.\n if (weight == 0) break;\n }\n }\n\n /** \n @notice \n The number of the next funding cycle given the specified funding cycle.\n\n @param _baseFundingCycle The funding cycle to base the calculation on.\n @param _start The start time of the funding cycle to derive a number for.\n\n @return The funding cycle number.\n */\n function _deriveNumberFrom(JBFundingCycle memory _baseFundingCycle, uint256 _start)\n private\n pure\n returns (uint256)\n {\n // A subsequent cycle to one with a duration of 0 should be the next number.\n if (_baseFundingCycle.duration == 0) return _baseFundingCycle.number + 1;\n\n // The difference between the start of the base funding cycle and the proposed start.\n uint256 _startDistance = _start - _baseFundingCycle.start;\n\n // Find the number of base cycles that fit in the start distance.\n return _baseFundingCycle.number + (_startDistance / _baseFundingCycle.duration);\n }\n\n /** \n @notice \n Checks to see if the provided funding cycle is approved according to the correct ballot.\n\n @param _projectId The ID of the project to which the funding cycle belongs. \n @param _fundingCycle The funding cycle to get an approval flag for.\n\n @return The approval flag.\n */\n function _isApproved(uint256 _projectId, JBFundingCycle memory _fundingCycle)\n private\n view\n returns (bool)\n {\n return\n _ballotStateOf(\n _projectId,\n _fundingCycle.configuration,\n _fundingCycle.start,\n _fundingCycle.basedOn\n ) == JBBallotState.Approved;\n }\n\n /**\n @notice \n A project's latest funding cycle configuration approval status.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n @param _configuration The funding cycle configuration to get the ballot state of.\n @param _start The start time of the funding cycle configuration to get the ballot state of.\n @param _ballotFundingCycleConfiguration The configuration of the funding cycle which is configured with the ballot that should be used.\n\n @return The ballot state of the project.\n */\n function _ballotStateOf(\n uint256 _projectId,\n uint256 _configuration,\n uint256 _start,\n uint256 _ballotFundingCycleConfiguration\n ) private view returns (JBBallotState) {\n // If there is no ballot funding cycle, implicitly approve.\n if (_ballotFundingCycleConfiguration == 0) return JBBallotState.Approved;\n\n // Get the ballot funding cycle.\n JBFundingCycle memory _ballotFundingCycle = _getStructFor(\n _projectId,\n _ballotFundingCycleConfiguration\n );\n\n // If there is no ballot, the ID is auto approved.\n // Otherwise if the ballot's duration hasn't passed, its still active.\n // Otherwise, return the ballot's state.\n if (_ballotFundingCycle.ballot == IJBFundingCycleBallot(address(0)))\n return JBBallotState.Approved;\n else if (_ballotFundingCycle.ballot.duration() >= block.timestamp - _configuration)\n return JBBallotState.Active;\n else return _ballotFundingCycle.ballot.stateOf(_projectId, _configuration, _start);\n }\n\n /**\n @notice \n Unpack a funding cycle's packed stored values into an easy-to-work-with funding cycle struct.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n @param _configuration The funding cycle configuration to get the full struct for.\n\n @return fundingCycle A funding cycle struct.\n */\n function _getStructFor(uint256 _projectId, uint256 _configuration)\n private\n view\n returns (JBFundingCycle memory fundingCycle)\n {\n // Return an empty funding cycle if the configuration specified is 0.\n if (_configuration == 0) return fundingCycle;\n\n fundingCycle.configuration = _configuration;\n\n uint256 _packedIntrinsicProperties = _packedIntrinsicPropertiesOf[_projectId][_configuration];\n\n // weight in bits 0-87 bits.\n fundingCycle.weight = uint256(uint88(_packedIntrinsicProperties));\n // basedOn in bits 88-143 bits.\n fundingCycle.basedOn = uint256(uint56(_packedIntrinsicProperties >> 88));\n // start in bits 144-199 bits.\n fundingCycle.start = uint256(uint56(_packedIntrinsicProperties >> 144));\n // number in bits 200-255 bits.\n fundingCycle.number = uint256(uint56(_packedIntrinsicProperties >> 200));\n\n uint256 _packedUserProperties = _packedUserPropertiesOf[_projectId][_configuration];\n\n // ballot in bits 0-159 bits.\n fundingCycle.ballot = IJBFundingCycleBallot(address(uint160(_packedUserProperties)));\n // duration in bits 160-223 bits.\n fundingCycle.duration = uint256(uint64(_packedUserProperties >> 160));\n // discountRate in bits 224-255 bits.\n fundingCycle.discountRate = uint256(uint32(_packedUserProperties >> 224));\n\n fundingCycle.metadata = _metadataOf[_projectId][_configuration];\n }\n}\n" @@ -170,7 +170,7 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './../interfaces/IJBSplitAllocator.sol';\n\n/** \n @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.\n @member preferAddToBalance A flag indicating if a distribution to a project should prefer triggering it's addToBalance function instead of its pay function.\n @member percent The percent of the whole group that this split occupies. This number is out of `JBConstants.SPLITS_TOTAL_PERCENT`.\n @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.\n @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.\n @member lockedUntil Specifies if the split should be unchangeable until the specified time, with the exception of extending the locked period.\n @member allocator If an allocator is specified, funds will be sent to the allocator contract along with all properties of this split.\n*/\nstruct JBSplit {\n bool preferClaimed;\n bool preferAddToBalance;\n uint256 percent;\n uint256 projectId;\n address payable beneficiary;\n uint256 lockedUntil;\n IJBSplitAllocator allocator;\n}\n" }, "contracts/system_tests/helpers/AccessJBLib.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '../../libraries/JBCurrencies.sol';\nimport '../../libraries/JBConstants.sol';\nimport '../../libraries/JBTokens.sol';\n\ncontract AccessJBLib {\n function ETH() external pure returns (uint256) {\n return JBCurrencies.ETH;\n }\n\n function USD() external pure returns (uint256) {\n return JBCurrencies.USD;\n }\n\n function ETHToken() external pure returns (address) {\n return JBTokens.ETH;\n }\n\n function MAX_FEE() external pure returns (uint256) {\n return JBConstants.MAX_FEE;\n }\n\n function MAX_RESERVED_RATE() external pure returns (uint256) {\n return JBConstants.MAX_RESERVED_RATE;\n }\n\n function MAX_REDEMPTION_RATE() external pure returns (uint256) {\n return JBConstants.MAX_REDEMPTION_RATE;\n }\n\n function MAX_DISCOUNT_RATE() external pure returns (uint256) {\n return JBConstants.MAX_DISCOUNT_RATE;\n }\n\n function SPLITS_TOTAL_PERCENT() external pure returns (uint256) {\n return JBConstants.SPLITS_TOTAL_PERCENT;\n }\n\n function MAX_FEE_DISCOUNT() external pure returns (uint256) {\n return JBConstants.MAX_FEE_DISCOUNT;\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '../../libraries/JBCurrencies.sol';\nimport '../../libraries/JBConstants.sol';\nimport '../../libraries/JBTokens.sol';\n\ncontract AccessJBLib {\n function ETH() external pure returns (uint256) {\n return JBCurrencies.GAS_CURRENCY;\n }\n\n function USD() external pure returns (uint256) {\n return JBCurrencies.USD;\n }\n\n function ETHToken() external pure returns (address) {\n return JBTokens.GAS_TOKEN;\n }\n\n function MAX_FEE() external pure returns (uint256) {\n return JBConstants.MAX_FEE;\n }\n\n function MAX_RESERVED_RATE() external pure returns (uint256) {\n return JBConstants.MAX_RESERVED_RATE;\n }\n\n function MAX_REDEMPTION_RATE() external pure returns (uint256) {\n return JBConstants.MAX_REDEMPTION_RATE;\n }\n\n function MAX_DISCOUNT_RATE() external pure returns (uint256) {\n return JBConstants.MAX_DISCOUNT_RATE;\n }\n\n function SPLITS_TOTAL_PERCENT() external pure returns (uint256) {\n return JBConstants.SPLITS_TOTAL_PERCENT;\n }\n\n function MAX_FEE_DISCOUNT() external pure returns (uint256) {\n return JBConstants.MAX_FEE_DISCOUNT;\n }\n}\n" }, "@paulrberg/contracts/math/PRBMath.sol": { "content": "// SPDX-License-Identifier: Unlicense\npragma solidity >=0.8.4;\n\nimport \"prb-math/contracts/PRBMath.sol\";\n" @@ -227,7 +227,7 @@ "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" }, "contracts/abstract/JBPayoutRedemptionPaymentTerminal/1.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../../interfaces/IJBController/1.sol';\nimport './../../interfaces/IJBPayoutRedemptionPaymentTerminal/1.sol';\nimport './../../libraries/JBConstants.sol';\nimport './../../libraries/JBCurrencies.sol';\nimport './../../libraries/JBFixedPointNumber.sol';\nimport './../../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../../libraries/JBOperations.sol';\nimport './../../libraries/JBSplitsGroups.sol';\nimport './../../libraries/JBTokens.sol';\nimport './../../structs/JBTokenAmount.sol';\nimport './../JBOperatable.sol';\nimport './../JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal is\n IJBPayoutRedemptionPaymentTerminal,\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n ReentrancyGuard\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- private stored constants -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 private constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The protocol project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 private constant _PROTOCOL_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- private stored properties ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) private _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId) external view override returns (uint256) {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.ETH)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.ETH, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n ) JBSingleTokenPaymentTerminal(_token, _decimals, _currency) JBOperatable(_operatorStore) {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.ETH) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Process each fee.\n for (uint256 _i = 0; _i < _heldFees.length; _i++) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @dev\n If the fee gauge reverts when called upon while a project is attempting to distribute its funds, a project's funds will be locked. This is a known risk.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual;\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual;\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) private returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegate` only used within scope.\n {\n IJBRedemptionDelegate _delegate;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegate, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If a delegate was returned by the data source, issue a callback to it.\n if (_delegate != IJBRedemptionDelegate(address(0))) {\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _beneficiary,\n _memo,\n _metadata\n );\n _delegate.didRedeem(_data);\n emit DelegateDidRedeem(_delegate, _data, msg.sender);\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) private returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convinience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n\n // Take the fee.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || _feeEligibleDistributionAmount == 0\n ? 0\n : _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n );\n\n // Get a reference to how much to distribute to the project owner, which is the leftover amount minus any fees.\n netLeftoverDistributionAmount = _leftoverDistributionAmount == 0\n ? 0\n : _leftoverDistributionAmount - _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n\n // Transfer any remaining balance to the project owner.\n if (netLeftoverDistributionAmount > 0)\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n ) private returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convinience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) private returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i = 0; _i < _splits.length; _i++) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount;\n\n if (_payoutAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (isFeelessAddress[address(_split.allocator)])\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _netPayoutAmount : 0;\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n _netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // Save gas if this contract is being used as the terminal.\n if (_terminal == this) {\n // This distribution does not incur a fee.\n _netPayoutAmount = _payoutAmount;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\n else\n _pay(\n _netPayoutAmount,\n address(this),\n _split.projectId,\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n } else {\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (isFeelessAddress[address(_terminal)])\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _netPayoutAmount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _terminal.addToBalanceOf{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n '',\n _projectMetadata\n );\n else\n _terminal.pay{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n }\n } else {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(\n address(this),\n _split.beneficiary != address(0) ? _split.beneficiary : payable(msg.sender),\n _netPayoutAmount\n );\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _netPayoutAmount,\n msg.sender\n );\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _PROTOCOL_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) private returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n */\n function _processFee(uint256 _amount, address _beneficiary) private {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_PROTOCOL_PROJECT_ID, token);\n\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\n if (_terminal == this)\n _pay(_amount, address(this), _PROTOCOL_PROJECT_ID, _beneficiary, 0, false, '', bytes('')); // Use the local pay call.\n else {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _amount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _amount : 0;\n\n // Send the payment.\n _terminal.pay{value: _payableValue}(\n _PROTOCOL_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the external pay call of the correct terminal.\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) private returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegate` and `_tokenCount` only used within scope.\n {\n IJBPayDelegate _delegate;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegate, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If a delegate was returned by the data source, issue a callback to it.\n if (_delegate != IJBPayDelegate(address(0))) {\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n _delegate.didPay(_data);\n emit DelegateDidPay(_delegate, _data, msg.sender);\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) private {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n private\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Process each fee.\n for (uint256 _i = 0; _i < _heldFees.length; _i++) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n } else {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n leftoverAmount = 0;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) private pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) private view returns (uint256 feeDiscount) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (directory.primaryTerminalOf(_PROTOCOL_PROJECT_ID, token) == IJBPaymentTerminal(address(0)))\n return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge == IJBFeeGauge(address(0)))\n feeDiscount = 0;\n // If the guage reverts, set the discount to 0.\n else\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n feeDiscount = discount;\n } catch {\n feeDiscount = 0;\n }\n\n // If the fee discount is greater than the max, nullify the discount.\n if (feeDiscount > JBConstants.MAX_FEE_DISCOUNT) feeDiscount = 0;\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../../interfaces/IJBController/1.sol';\nimport './../../interfaces/IJBPayoutRedemptionPaymentTerminal/1.sol';\nimport './../../libraries/JBConstants.sol';\nimport './../../libraries/JBCurrencies.sol';\nimport './../../libraries/JBFixedPointNumber.sol';\nimport './../../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../../libraries/JBOperations.sol';\nimport './../../libraries/JBSplitsGroups.sol';\nimport './../../libraries/JBTokens.sol';\nimport './../../structs/JBTokenAmount.sol';\nimport './../JBOperatable.sol';\nimport './../JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal is\n IJBPayoutRedemptionPaymentTerminal,\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n ReentrancyGuard\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- private stored constants -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 private constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The protocol project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 private constant _PROTOCOL_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- private stored properties ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) private _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId) external view override returns (uint256) {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.GAS_CURRENCY)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.GAS_CURRENCY, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n ) JBSingleTokenPaymentTerminal(_token, _decimals, _currency) JBOperatable(_operatorStore) {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.GAS_TOKEN) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Process each fee.\n for (uint256 _i = 0; _i < _heldFees.length; _i++) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @dev\n If the fee gauge reverts when called upon while a project is attempting to distribute its funds, a project's funds will be locked. This is a known risk.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual;\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual;\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) private returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegate` only used within scope.\n {\n IJBRedemptionDelegate _delegate;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegate, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If a delegate was returned by the data source, issue a callback to it.\n if (_delegate != IJBRedemptionDelegate(address(0))) {\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _beneficiary,\n _memo,\n _metadata\n );\n _delegate.didRedeem(_data);\n emit DelegateDidRedeem(_delegate, _data, msg.sender);\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) private returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convinience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n\n // Take the fee.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || _feeEligibleDistributionAmount == 0\n ? 0\n : _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n );\n\n // Get a reference to how much to distribute to the project owner, which is the leftover amount minus any fees.\n netLeftoverDistributionAmount = _leftoverDistributionAmount == 0\n ? 0\n : _leftoverDistributionAmount - _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n\n // Transfer any remaining balance to the project owner.\n if (netLeftoverDistributionAmount > 0)\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n ) private returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convinience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) private returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i = 0; _i < _splits.length; _i++) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount;\n\n if (_payoutAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (isFeelessAddress[address(_split.allocator)])\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0;\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n _netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // Save gas if this contract is being used as the terminal.\n if (_terminal == this) {\n // This distribution does not incur a fee.\n _netPayoutAmount = _payoutAmount;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\n else\n _pay(\n _netPayoutAmount,\n address(this),\n _split.projectId,\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n } else {\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (isFeelessAddress[address(_terminal)])\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _terminal.addToBalanceOf{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n '',\n _projectMetadata\n );\n else\n _terminal.pay{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n }\n } else {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(\n address(this),\n _split.beneficiary != address(0) ? _split.beneficiary : payable(msg.sender),\n _netPayoutAmount\n );\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _netPayoutAmount,\n msg.sender\n );\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _PROTOCOL_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) private returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n */\n function _processFee(uint256 _amount, address _beneficiary) private {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_PROTOCOL_PROJECT_ID, token);\n\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\n if (_terminal == this)\n _pay(_amount, address(this), _PROTOCOL_PROJECT_ID, _beneficiary, 0, false, '', bytes('')); // Use the local pay call.\n else {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _amount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send the payment.\n _terminal.pay{value: _payableValue}(\n _PROTOCOL_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the external pay call of the correct terminal.\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) private returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegate` and `_tokenCount` only used within scope.\n {\n IJBPayDelegate _delegate;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegate, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If a delegate was returned by the data source, issue a callback to it.\n if (_delegate != IJBPayDelegate(address(0))) {\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n _delegate.didPay(_data);\n emit DelegateDidPay(_delegate, _data, msg.sender);\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) private {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n private\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Process each fee.\n for (uint256 _i = 0; _i < _heldFees.length; _i++) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n } else {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n leftoverAmount = 0;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) private pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) private view returns (uint256 feeDiscount) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (directory.primaryTerminalOf(_PROTOCOL_PROJECT_ID, token) == IJBPaymentTerminal(address(0)))\n return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge == IJBFeeGauge(address(0)))\n feeDiscount = 0;\n // If the guage reverts, set the discount to 0.\n else\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n feeDiscount = discount;\n } catch {\n feeDiscount = 0;\n }\n\n // If the fee discount is greater than the max, nullify the discount.\n if (feeDiscount > JBConstants.MAX_FEE_DISCOUNT) feeDiscount = 0;\n }\n}\n" }, "@openzeppelin/contracts/security/ReentrancyGuard.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n constructor() {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n // On the first call to nonReentrant, _notEntered will be true\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n\n _;\n\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n}\n" @@ -311,25 +311,25 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './IJBFundingCycleBallot.sol';\n\ninterface IJBReconfigurationBufferBallot is IJBFundingCycleBallot {\n event Finalize(\n uint256 indexed projectId,\n uint256 indexed configuration,\n JBBallotState indexed ballotState,\n address caller\n );\n\n function finalState(uint256 _projectId, uint256 _configuration)\n external\n view\n returns (JBBallotState);\n\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\n\n function finalize(uint256 _projectId, uint256 _configured) external returns (JBBallotState);\n}\n" }, "contracts/system_tests/TestEIP165.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './helpers/TestBaseWorkflow.sol';\nimport '../JBReconfigurationBufferBallot.sol';\nimport '../JBETHERC20SplitsPayer/1.sol';\n\ncontract TestEIP165 is TestBaseWorkflow {\n bytes4 constant notSupportedInterface = 0xffffffff;\n\n uint256 constant projectId = 2;\n uint256 constant splitsProjectID = 3;\n address payable constant splitsBeneficiary = payable(address(420));\n uint256 constant splitsDomain = 1;\n uint256 constant splitsGroup = 1;\n bool constant splitsPreferClaimedTokens = false;\n string constant splitsMemo = '';\n bytes constant splitsMetadata = '';\n bool constant splitsPreferAddToBalance = true;\n address constant splitsOwner = address(420);\n\n function testJBController() public {\n JBController controller = jbController();\n\n // Should support these interfaces\n assertTrue(controller.supportsInterface(type(IERC165).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBController).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBMigratable).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!controller.supportsInterface(notSupportedInterface));\n }\n\n function testJBERC20PaymentTerminal() public {\n JBERC20PaymentTerminal terminal = new JBERC20PaymentTerminal(\n jbToken(),\n jbLibraries().USD(), // currency\n jbLibraries().ETH(), // base weight currency\n 1, // JBSplitsGroupe\n jbOperatorStore(),\n jbProjects(),\n jbDirectory(),\n jbSplitsStore(),\n jbPrices(),\n jbPaymentTerminalStore(),\n multisig()\n );\n\n // Should support these interfaces\n assertTrue(terminal.supportsInterface(type(IERC165).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBRedemptionTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBSingleTokenPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!terminal.supportsInterface(notSupportedInterface));\n }\n\n function testJBETHPaymentTerminal() public {\n JBETHPaymentTerminal terminal = jbETHPaymentTerminal();\n\n // Should support these interfaces\n assertTrue(terminal.supportsInterface(type(IERC165).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBRedemptionTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBSingleTokenPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!terminal.supportsInterface(notSupportedInterface));\n }\n\n function testJBProjects() public {\n JBProjects projects = jbProjects();\n\n // Should support these interfaces\n assertTrue(projects.supportsInterface(type(IERC165).interfaceId));\n assertTrue(projects.supportsInterface(type(IERC721).interfaceId));\n assertTrue(projects.supportsInterface(type(IERC721Metadata).interfaceId));\n assertTrue(projects.supportsInterface(type(IJBProjects).interfaceId));\n assertTrue(projects.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!projects.supportsInterface(notSupportedInterface));\n }\n\n function testJBReconfigurationBufferBallot() public {\n JBReconfigurationBufferBallot ballot = new JBReconfigurationBufferBallot(\n 3000,\n jbFundingCycleStore()\n );\n\n // Should support these interfaces\n assertTrue(ballot.supportsInterface(type(IERC165).interfaceId));\n assertTrue(ballot.supportsInterface(type(IJBReconfigurationBufferBallot).interfaceId));\n assertTrue(ballot.supportsInterface(type(IJBFundingCycleBallot).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!ballot.supportsInterface(notSupportedInterface));\n }\n\n function testJBETHERC20SplitsPayer() public {\n JBETHERC20SplitsPayer splitsPayer = new JBETHERC20SplitsPayer(\n splitsProjectID,\n splitsDomain,\n splitsGroup,\n jbSplitsStore(),\n projectId,\n splitsBeneficiary,\n splitsPreferClaimedTokens,\n splitsMemo,\n splitsMetadata,\n splitsPreferAddToBalance,\n splitsOwner\n );\n\n // Should support these interfaces\n assertTrue(splitsPayer.supportsInterface(type(IERC165).interfaceId));\n assertTrue(splitsPayer.supportsInterface(type(IJBSplitsPayer).interfaceId));\n assertTrue(splitsPayer.supportsInterface(type(IJBProjectPayer).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!splitsPayer.supportsInterface(notSupportedInterface));\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './helpers/TestBaseWorkflow.sol';\nimport '../JBReconfigurationBufferBallot.sol';\nimport '../JBGasTokenERC20SplitsPayer/1.sol';\n\ncontract TestEIP165 is TestBaseWorkflow {\n bytes4 constant notSupportedInterface = 0xffffffff;\n\n uint256 constant projectId = 2;\n uint256 constant splitsProjectID = 3;\n address payable constant splitsBeneficiary = payable(address(420));\n uint256 constant splitsDomain = 1;\n uint256 constant splitsGroup = 1;\n bool constant splitsPreferClaimedTokens = false;\n string constant splitsMemo = '';\n bytes constant splitsMetadata = '';\n bool constant splitsPreferAddToBalance = true;\n address constant splitsOwner = address(420);\n\n function testJBController() public {\n JBController controller = jbController();\n\n // Should support these interfaces\n assertTrue(controller.supportsInterface(type(IERC165).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBController).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBMigratable).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!controller.supportsInterface(notSupportedInterface));\n }\n\n function testJBERC20PaymentTerminal() public {\n JBERC20PaymentTerminal terminal = new JBERC20PaymentTerminal(\n jbToken(),\n jbLibraries().USD(), // currency\n jbLibraries().ETH(), // base weight currency\n 1, // JBSplitsGroupe\n jbOperatorStore(),\n jbProjects(),\n jbDirectory(),\n jbSplitsStore(),\n jbPrices(),\n jbPaymentTerminalStore(),\n multisig()\n );\n\n // Should support these interfaces\n assertTrue(terminal.supportsInterface(type(IERC165).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBRedemptionTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBSingleTokenPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!terminal.supportsInterface(notSupportedInterface));\n }\n\n function testJBETHPaymentTerminal() public {\n JBETHPaymentTerminal terminal = jbETHPaymentTerminal();\n\n // Should support these interfaces\n assertTrue(terminal.supportsInterface(type(IERC165).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBRedemptionTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBSingleTokenPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!terminal.supportsInterface(notSupportedInterface));\n }\n\n function testJBProjects() public {\n JBProjects projects = jbProjects();\n\n // Should support these interfaces\n assertTrue(projects.supportsInterface(type(IERC165).interfaceId));\n assertTrue(projects.supportsInterface(type(IERC721).interfaceId));\n assertTrue(projects.supportsInterface(type(IERC721Metadata).interfaceId));\n assertTrue(projects.supportsInterface(type(IJBProjects).interfaceId));\n assertTrue(projects.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!projects.supportsInterface(notSupportedInterface));\n }\n\n function testJBReconfigurationBufferBallot() public {\n JBReconfigurationBufferBallot ballot = new JBReconfigurationBufferBallot(\n 3000,\n jbFundingCycleStore()\n );\n\n // Should support these interfaces\n assertTrue(ballot.supportsInterface(type(IERC165).interfaceId));\n assertTrue(ballot.supportsInterface(type(IJBReconfigurationBufferBallot).interfaceId));\n assertTrue(ballot.supportsInterface(type(IJBFundingCycleBallot).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!ballot.supportsInterface(notSupportedInterface));\n }\n\n function testJBGasTokenERC20SplitsPayer() public {\n JBGasTokenERC20SplitsPayer splitsPayer = new JBGasTokenERC20SplitsPayer(\n splitsProjectID,\n splitsDomain,\n splitsGroup,\n jbSplitsStore(),\n projectId,\n splitsBeneficiary,\n splitsPreferClaimedTokens,\n splitsMemo,\n splitsMetadata,\n splitsPreferAddToBalance,\n splitsOwner\n );\n\n // Should support these interfaces\n assertTrue(splitsPayer.supportsInterface(type(IERC165).interfaceId));\n assertTrue(splitsPayer.supportsInterface(type(IJBSplitsPayer).interfaceId));\n assertTrue(splitsPayer.supportsInterface(type(IJBProjectPayer).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!splitsPayer.supportsInterface(notSupportedInterface));\n }\n}\n" }, - "contracts/JBETHERC20SplitsPayer/1.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBSplitsPayer/1.sol';\nimport './../interfaces/IJBSplitsStore/1.sol';\nimport './../libraries/JBConstants.sol';\nimport './../JBETHERC20ProjectPayer.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\n\n @dev\n Adheres to -\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBETHERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBETHERC20SplitsPayer is IJBSplitsPayer, JBETHERC20ProjectPayer, ReentrancyGuard {\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The ID of project for which the default splits are stored. \n */\n uint256 public override defaultSplitsProjectId;\n\n /**\n @notice\n The domain within which the default splits are stored. \n */\n uint256 public override defaultSplitsDomain;\n\n /**\n @notice\n The group within which the default splits are stored. \n */\n uint256 public override defaultSplitsGroup;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBETHERC20ProjectPayer, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n )\n JBETHERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _preferAddToBalance,\n _splitsStore.directory(),\n _owner\n )\n {\n defaultSplitsProjectId = _defaultSplitsProjectId;\n defaultSplitsDomain = _defaultSplitsDomain;\n defaultSplitsGroup = _defaultSplitsGroup;\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default split group using the stored default properties.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override nonReentrant {\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n JBTokens.ETH,\n address(this).balance,\n 18 // decimals.\n );\n\n // If there is no leftover amount, nothing left to pay.\n if (_leftoverAmount == 0) return;\n\n // If there's a default project ID, try to pay it.\n if (defaultProjectId != 0)\n if (defaultPreferAddToBalance)\n // Pay the project by adding to its balance if prefered.\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.ETH,\n _leftoverAmount,\n 18, // decimals.\n defaultMemo,\n defaultMetadata\n );\n // Otherwise, issue a payment to the project.\n else\n _pay(\n defaultProjectId,\n JBTokens.ETH,\n _leftoverAmount,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n 0, // min returned tokens.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n // If no project was specified, send the funds directly to the beneficiary or the msg.sender.\n else\n Address.sendValue(\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(msg.sender),\n _leftoverAmount\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the location of the splits that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n */\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) external virtual override onlyOwner {\n // Set the default splits project ID if it's changing.\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\n\n // Set the default splits domain if it's changing.\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\n\n // Set the default splits group if it's changing.\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\n\n emit SetDefaultSplits(_projectId, _domain, _group, msg.sender);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals\n );\n\n // Pay any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to pay it.\n if (_projectId != 0) {\n _pay(\n _projectId,\n _token,\n _leftoverAmount,\n _decimals,\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n // If no project was specified, send the funds directly to the beneficiary or the msg.sender.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _beneficiary != address(0) ? payable(_beneficiary) : payable(msg.sender),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).transfer(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _leftoverAmount\n );\n }\n }\n\n emit Pay(\n _projectId,\n _beneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event. \n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals\n );\n\n // Distribute any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to add to its balance.\n if (_projectId != 0)\n // Add to the project's balance.\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\n\n // Otherwise, send a payment to the beneficiary.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(msg.sender),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).transfer(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _leftoverAmount\n );\n }\n }\n\n emit AddToBalance(\n _projectId,\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splitsProjectId The ID of the project to which the splits belong.\n @param _splitsDomain The splits domain to which the group belongs.\n @param _splitsGroup The splits group to pay.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payToSplits(\n uint256 _splitsProjectId,\n uint256 _splitsDomain,\n uint256 _splitsGroup,\n address _token,\n uint256 _amount,\n uint256 _decimals\n ) internal virtual returns (uint256 leftoverAmount) {\n // Get a reference to the splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup);\n\n // Set the leftover amount to the initial balance.\n leftoverAmount = _amount;\n\n // Settle between all splits.\n for (uint256 i = 0; i < _splits.length; i++) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[i];\n\n // The amount to send towards the split.\n uint256 _splitAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n if (_splitAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n _token,\n _splitAmount,\n _decimals,\n defaultProjectId,\n 0,\n _split\n );\n\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\n if (_token != JBTokens.ETH)\n IERC20(_token).approve(address(_split.allocator), _splitAmount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _splitAmount : 0;\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n if (_split.preferAddToBalance)\n _addToBalanceOf(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n defaultMemo,\n defaultMetadata\n );\n } else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _split.beneficiary != address(0) ? _split.beneficiary : payable(msg.sender),\n _splitAmount\n );\n // Or, transfer the ERC20.\n else {\n IERC20(_token).transfer(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n _splitAmount\n );\n }\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _splitAmount;\n }\n\n emit DistributeToSplit(\n _splitsProjectId,\n _splitsDomain,\n _splitsGroup,\n _split,\n _splitAmount,\n msg.sender\n );\n }\n }\n}\n" + "contracts/JBGasTokenERC20SplitsPayer/1.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBSplitsPayer/1.sol';\nimport './../interfaces/IJBSplitsStore/1.sol';\nimport './../libraries/JBConstants.sol';\nimport './../JBGasTokenERC20ProjectPayer.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\n\n @dev\n Adheres to -\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBGasTokenERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBGasTokenERC20SplitsPayer is IJBSplitsPayer, JBGasTokenERC20ProjectPayer, ReentrancyGuard {\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The ID of project for which the default splits are stored. \n */\n uint256 public override defaultSplitsProjectId;\n\n /**\n @notice\n The domain within which the default splits are stored. \n */\n uint256 public override defaultSplitsDomain;\n\n /**\n @notice\n The group within which the default splits are stored. \n */\n uint256 public override defaultSplitsGroup;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBGasTokenERC20ProjectPayer, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n )\n JBGasTokenERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _preferAddToBalance,\n _splitsStore.directory(),\n _owner\n )\n {\n defaultSplitsProjectId = _defaultSplitsProjectId;\n defaultSplitsDomain = _defaultSplitsDomain;\n defaultSplitsGroup = _defaultSplitsGroup;\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default split group using the stored default properties.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override nonReentrant {\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18 // decimals.\n );\n\n // If there is no leftover amount, nothing left to pay.\n if (_leftoverAmount == 0) return;\n\n // If there's a default project ID, try to pay it.\n if (defaultProjectId != 0)\n if (defaultPreferAddToBalance)\n // Pay the project by adding to its balance if prefered.\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n _leftoverAmount,\n 18, // decimals.\n defaultMemo,\n defaultMetadata\n );\n // Otherwise, issue a payment to the project.\n else\n _pay(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n _leftoverAmount,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n 0, // min returned tokens.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n // If no project was specified, send the funds directly to the beneficiary or the msg.sender.\n else\n Address.sendValue(\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(msg.sender),\n _leftoverAmount\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the location of the splits that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n */\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) external virtual override onlyOwner {\n // Set the default splits project ID if it's changing.\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\n\n // Set the default splits domain if it's changing.\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\n\n // Set the default splits group if it's changing.\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\n\n emit SetDefaultSplits(_projectId, _domain, _group, msg.sender);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals\n );\n\n // Pay any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to pay it.\n if (_projectId != 0) {\n _pay(\n _projectId,\n _token,\n _leftoverAmount,\n _decimals,\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n // If no project was specified, send the funds directly to the beneficiary or the msg.sender.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _beneficiary != address(0) ? payable(_beneficiary) : payable(msg.sender),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).transfer(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _leftoverAmount\n );\n }\n }\n\n emit Pay(\n _projectId,\n _beneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event. \n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals\n );\n\n // Distribute any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to add to its balance.\n if (_projectId != 0)\n // Add to the project's balance.\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\n\n // Otherwise, send a payment to the beneficiary.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(msg.sender),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).transfer(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _leftoverAmount\n );\n }\n }\n\n emit AddToBalance(\n _projectId,\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splitsProjectId The ID of the project to which the splits belong.\n @param _splitsDomain The splits domain to which the group belongs.\n @param _splitsGroup The splits group to pay.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payToSplits(\n uint256 _splitsProjectId,\n uint256 _splitsDomain,\n uint256 _splitsGroup,\n address _token,\n uint256 _amount,\n uint256 _decimals\n ) internal virtual returns (uint256 leftoverAmount) {\n // Get a reference to the splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup);\n\n // Set the leftover amount to the initial balance.\n leftoverAmount = _amount;\n\n // Settle between all splits.\n for (uint256 i = 0; i < _splits.length; i++) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[i];\n\n // The amount to send towards the split.\n uint256 _splitAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n if (_splitAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n _token,\n _splitAmount,\n _decimals,\n defaultProjectId,\n 0,\n _split\n );\n\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN)\n IERC20(_token).approve(address(_split.allocator), _splitAmount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _splitAmount : 0;\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n if (_split.preferAddToBalance)\n _addToBalanceOf(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n defaultMemo,\n defaultMetadata\n );\n } else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _split.beneficiary != address(0) ? _split.beneficiary : payable(msg.sender),\n _splitAmount\n );\n // Or, transfer the ERC20.\n else {\n IERC20(_token).transfer(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n _splitAmount\n );\n }\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _splitAmount;\n }\n\n emit DistributeToSplit(\n _splitsProjectId,\n _splitsDomain,\n _splitsGroup,\n _split,\n _splitAmount,\n msg.sender\n );\n }\n }\n}\n" }, "contracts/interfaces/IJBSplitsPayer/1.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './../../structs/JBSplit.sol';\nimport './../IJBSplitsStore/1.sol';\n\ninterface IJBSplitsPayer is IERC165 {\n event SetDefaultSplits(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n address caller\n );\n event Pay(\n uint256 indexed projectId,\n address beneficiary,\n address token,\n uint256 amount,\n uint256 decimals,\n uint256 leftoverAmount,\n uint256 minReturnedTokens,\n bool preferClaimedTokens,\n string memo,\n bytes metadata,\n address caller\n );\n\n event AddToBalance(\n uint256 indexed projectId,\n address beneficiary,\n address token,\n uint256 amount,\n uint256 decimals,\n uint256 leftoverAmount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DistributeToSplit(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n JBSplit split,\n uint256 amount,\n address caller\n );\n\n function defaultSplitsProjectId() external view returns (uint256);\n\n function defaultSplitsDomain() external view returns (uint256);\n\n function defaultSplitsGroup() external view returns (uint256);\n\n function splitsStore() external view returns (IJBSplitsStore);\n\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) external;\n}\n" }, - "contracts/JBETHERC20ProjectPayer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport './interfaces/IJBProjectPayer.sol';\nimport './libraries/JBTokens.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ERC165: Introspection on interface adherance. \n*/\ncontract JBETHERC20ProjectPayer is IJBProjectPayer, Ownable, ERC165 {\n //*********************************************************************//\n // -------------------------- custom errors -------------------------- //\n //*********************************************************************//\n error INCORRECT_DECIMAL_AMOUNT();\n error NO_MSG_VALUE_ALLOWED();\n error TERMINAL_NOT_FOUND();\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice \n A contract storing directories of terminals and controllers for each project.\n */\n IJBDirectory public immutable override directory;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The ID of the project that should be used to forward this contract's received payments.\n */\n uint256 public override defaultProjectId;\n\n /** \n @notice \n The beneficiary that should be used in the payment made when this contract receives payments.\n */\n address payable public override defaultBeneficiary;\n\n /** \n @notice \n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\n */\n bool public override defaultPreferClaimedTokens;\n\n /** \n @notice \n The memo that should be used in the payment made when this contract receives payments.\n */\n string public override defaultMemo;\n\n /** \n @notice \n The metadata that should be used in the payment made when this contract receives payments.\n */\n bytes public override defaultMetadata;\n\n /**\n @notice \n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n bool public override defaultPreferAddToBalance;\n\n //*********************************************************************//\n // ------------------------- public views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) {\n defaultProjectId = _defaultProjectId;\n defaultBeneficiary = _defaultBeneficiary;\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\n defaultMemo = _defaultMemo;\n defaultMetadata = _defaultMetadata;\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n directory = _directory;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default project ID using the stored default properties.\n\n @dev\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override {\n if (defaultPreferAddToBalance)\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.ETH,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n defaultProjectId,\n JBTokens.ETH,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultBeneficiary == address(0) ? msg.sender : defaultBeneficiary,\n 0, // Can't determine expectation of returned tokens ahead of time.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\n\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _beneficiary The address that'll receive the project's tokens. \n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _memo The memo that'll be used. \n @param _metadata The metadata that'll be sent. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external virtual override onlyOwner {\n // Set the default project ID if it has changed.\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\n\n // Set the default beneficiary if it has changed.\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\n\n // Set the default claimed token preference if it has changed.\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\n defaultPreferClaimedTokens = _preferClaimedTokens;\n\n // Set the default memo if it has changed.\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\n defaultMemo = _memo;\n\n // Set the default metadata if it has changed.\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\n defaultMetadata = _metadata;\n\n // Set the add to balance preference if it has changed.\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n\n emit SetDefaultValues(\n _projectId,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata,\n _defaultPreferAddToBalance,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _pay(\n _projectId,\n _token,\n _amount,\n _decimals,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. \n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source and delegate, if provided.\n */\n function _pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.ETH) IERC20(_token).approve(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\n\n // Send funds to the terminal.\n // If the token is ETH, send it in msg.value.\n _terminal.pay{value: _payableValue}(\n _projectId,\n _amount, // ignored if the token is JBTokens.ETH.\n _token,\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.ETH) IERC20(_token).approve(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\n\n // Add to balance so tokens don't get issued.\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\n }\n}\n" + "contracts/JBGasTokenERC20ProjectPayer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport './interfaces/IJBProjectPayer.sol';\nimport './libraries/JBTokens.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ERC165: Introspection on interface adherance. \n*/\ncontract JBGasTokenERC20ProjectPayer is IJBProjectPayer, Ownable, ERC165 {\n //*********************************************************************//\n // -------------------------- custom errors -------------------------- //\n //*********************************************************************//\n error INCORRECT_DECIMAL_AMOUNT();\n error NO_MSG_VALUE_ALLOWED();\n error TERMINAL_NOT_FOUND();\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice \n A contract storing directories of terminals and controllers for each project.\n */\n IJBDirectory public immutable override directory;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The ID of the project that should be used to forward this contract's received payments.\n */\n uint256 public override defaultProjectId;\n\n /** \n @notice \n The beneficiary that should be used in the payment made when this contract receives payments.\n */\n address payable public override defaultBeneficiary;\n\n /** \n @notice \n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\n */\n bool public override defaultPreferClaimedTokens;\n\n /** \n @notice \n The memo that should be used in the payment made when this contract receives payments.\n */\n string public override defaultMemo;\n\n /** \n @notice \n The metadata that should be used in the payment made when this contract receives payments.\n */\n bytes public override defaultMetadata;\n\n /**\n @notice \n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n bool public override defaultPreferAddToBalance;\n\n //*********************************************************************//\n // ------------------------- public views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) {\n defaultProjectId = _defaultProjectId;\n defaultBeneficiary = _defaultBeneficiary;\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\n defaultMemo = _defaultMemo;\n defaultMetadata = _defaultMetadata;\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n directory = _directory;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default project ID using the stored default properties.\n\n @dev\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override {\n if (defaultPreferAddToBalance)\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultBeneficiary == address(0) ? msg.sender : defaultBeneficiary,\n 0, // Can't determine expectation of returned tokens ahead of time.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\n\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _beneficiary The address that'll receive the project's tokens. \n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _memo The memo that'll be used. \n @param _metadata The metadata that'll be sent. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external virtual override onlyOwner {\n // Set the default project ID if it has changed.\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\n\n // Set the default beneficiary if it has changed.\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\n\n // Set the default claimed token preference if it has changed.\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\n defaultPreferClaimedTokens = _preferClaimedTokens;\n\n // Set the default memo if it has changed.\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\n defaultMemo = _memo;\n\n // Set the default metadata if it has changed.\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\n defaultMetadata = _metadata;\n\n // Set the add to balance preference if it has changed.\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n\n emit SetDefaultValues(\n _projectId,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata,\n _defaultPreferAddToBalance,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _pay(\n _projectId,\n _token,\n _amount,\n _decimals,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. \n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source and delegate, if provided.\n */\n function _pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).approve(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send funds to the terminal.\n // If the token is ETH, send it in msg.value.\n _terminal.pay{value: _payableValue}(\n _projectId,\n _amount, // ignored if the token is JBTokens.GAS_TOKEN.\n _token,\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).approve(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Add to balance so tokens don't get issued.\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\n }\n}\n" }, "contracts/interfaces/IJBProjectPayer.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './IJBDirectory.sol';\n\ninterface IJBProjectPayer is IERC165 {\n event SetDefaultValues(\n uint256 indexed projectId,\n address indexed beneficiary,\n bool preferClaimedTokens,\n string memo,\n bytes metadata,\n bool preferAddToBalance,\n address caller\n );\n\n function directory() external view returns (IJBDirectory);\n\n function defaultProjectId() external view returns (uint256);\n\n function defaultBeneficiary() external view returns (address payable);\n\n function defaultPreferClaimedTokens() external view returns (bool);\n\n function defaultMemo() external view returns (string memory);\n\n function defaultMetadata() external view returns (bytes memory);\n\n function defaultPreferAddToBalance() external view returns (bool);\n\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external;\n\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) external payable;\n\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) external payable;\n\n receive() external payable;\n}\n" }, - "contracts/JBETHERC20SplitsPayerDeployer/1.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './../interfaces/IJBETHERC20SplitsPayerDeployer/1.sol';\nimport './../JBETHERC20SplitsPayer/1.sol';\n\n/** \n @notice \n Deploys splits payer contracts.\n\n @dev\n Adheres to -\n IJBETHERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBETHERC20SplitsPayerDeployer is IJBETHERC20SplitsPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBSplitsPayer splitsPayer) {\n // Deploy the splits payer.\n splitsPayer = new JBETHERC20SplitsPayer(\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeploySplitsPayer(\n splitsPayer,\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner,\n msg.sender\n );\n }\n}\n" + "contracts/JBGasTokenERC20SplitsPayerDeployer/1.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './../interfaces/IJBGasTokenERC20SplitsPayerDeployer/1.sol';\nimport './../JBGasTokenERC20SplitsPayer/1.sol';\n\n/** \n @notice \n Deploys splits payer contracts.\n\n @dev\n Adheres to -\n IJBGasTokenERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBGasTokenERC20SplitsPayerDeployer is IJBGasTokenERC20SplitsPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBSplitsPayer splitsPayer) {\n // Deploy the splits payer.\n splitsPayer = new JBGasTokenERC20SplitsPayer(\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeploySplitsPayer(\n splitsPayer,\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner,\n msg.sender\n );\n }\n}\n" }, - "contracts/interfaces/IJBETHERC20SplitsPayerDeployer/1.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './../IJBSplitsPayer/1.sol';\nimport './../IJBSplitsStore/1.sol';\n\ninterface IJBETHERC20SplitsPayerDeployer {\n event DeploySplitsPayer(\n IJBSplitsPayer indexed splitsPayer,\n uint256 defaultSplitsProjectId,\n uint256 defaultSplitsDomain,\n uint256 defaultSplitsGroup,\n IJBSplitsStore splitsStore,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n address owner,\n address caller\n );\n\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string calldata _defaultMemo,\n bytes calldata _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n}\n" + "contracts/interfaces/IJBGasTokenERC20SplitsPayerDeployer/1.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './../IJBSplitsPayer/1.sol';\nimport './../IJBSplitsStore/1.sol';\n\ninterface IJBGasTokenERC20SplitsPayerDeployer {\n event DeploySplitsPayer(\n IJBSplitsPayer indexed splitsPayer,\n uint256 defaultSplitsProjectId,\n uint256 defaultSplitsDomain,\n uint256 defaultSplitsGroup,\n IJBSplitsStore splitsStore,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n address owner,\n address caller\n );\n\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string calldata _defaultMemo,\n bytes calldata _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n}\n" }, "contracts/JBSplitsStore/2.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './../abstract/JBOperatable.sol';\nimport './../interfaces/IJBDirectory.sol';\nimport './../interfaces/IJBSplitsStore/2.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBOperations.sol';\n\n/**\n @notice\n Stores splits for each project.\n\n @dev\n Adheres to -\n IJBSplitsStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\ncontract JBSplitsStore is IJBSplitsStore, JBOperatable {\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_LOCKED_UNTIL();\n error INVALID_PROJECT_ID();\n error INVALID_SPLIT_PERCENT();\n error INVALID_TOTAL_PERCENT();\n error PREVIOUS_LOCKED_SPLITS_NOT_INCLUDED();\n\n //*********************************************************************//\n // --------------------- private stored properties ------------------- //\n //*********************************************************************//\n\n /** \n @notice\n The number of splits currently set for each project ID's configurations.\n\n _projectId The ID of the project to get the split count for.\n _domain An identifier within which the returned splits should be considered active.\n _group The identifying group of the splits.\n */\n mapping(uint256 => mapping(uint256 => mapping(uint256 => uint256))) private _splitCountOf;\n\n /** \n @notice\n Packed data of splits for each project ID's configurations.\n\n _projectId The ID of the project to get packed splits data for.\n _domain An identifier within which the returned splits should be considered active.\n _group The identifying group of the splits.\n _index The indexed order that the split was set at.\n */\n mapping(uint256 => mapping(uint256 => mapping(uint256 => mapping(uint256 => uint256))))\n private _packedSplitParts1Of;\n\n /** \n @notice\n More packed data of splits for each project ID's configurations.\n\n @dev\n This packed data is often 0.\n\n _projectId The ID of the project to get packed splits data for.\n _domain An identifier within which the returned splits should be considered active.\n _group The identifying group of the splits.\n _index The indexed order that the split was set at.\n */\n mapping(uint256 => mapping(uint256 => mapping(uint256 => mapping(uint256 => uint256))))\n private _packedSplitParts2Of;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /** \n @notice \n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /** \n @notice \n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice \n Get all splits for the specified project ID, within the specified domain, for the specified group.\n\n @param _projectId The ID of the project to get splits for.\n @param _domain An identifier within which the returned splits should be considered active.\n @param _group The identifying group of the splits.\n\n @return An array of all splits for the project.\n*/\n function splitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) external view override returns (JBSplit[] memory) {\n return _getStructsFor(_projectId, _domain, _group);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n */\n constructor(\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory\n ) JBOperatable(_operatorStore) {\n projects = _projects;\n directory = _directory;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets a project's splits.\n\n @dev\n Only the owner or operator of a project, or the current controller contract of the project, can set its splits.\n\n @dev\n The new splits must include any currently set splits that are locked.\n\n @param _projectId The ID of the project for which splits are being added.\n @param _domain An identifier within which the splits should be considered active.\n @param _groupedSplits An array of splits to set for any number of groups. \n */\n function set(\n uint256 _projectId,\n uint256 _domain,\n JBGroupedSplits[] calldata _groupedSplits\n )\n external\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.SET_SPLITS,\n address(directory.controllerOf(_projectId)) == msg.sender\n )\n {\n // Push array length in stack\n uint256 _groupedSplitsLength = _groupedSplits.length;\n\n // Set each grouped splits.\n for (uint256 _i = 0; _i < _groupedSplitsLength; ) {\n // Get a reference to the grouped split being iterated on.\n JBGroupedSplits memory _groupedSplit = _groupedSplits[_i];\n\n // Set the splits for the group.\n _set(_projectId, _domain, _groupedSplit.group, _groupedSplit.splits);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets a project's splits.\n\n @dev\n Only the owner or operator of a project, or the current controller contract of the project, can set its splits.\n\n @dev\n The new splits must include any currently set splits that are locked.\n\n @param _projectId The ID of the project for which splits are being added.\n @param _domain An identifier within which the splits should be considered active.\n @param _group An identifier between of splits being set. All splits within this _group must add up to within 100%.\n @param _splits The splits to set.\n */\n function _set(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n JBSplit[] memory _splits\n ) internal {\n // Get a reference to the project's current splits.\n JBSplit[] memory _currentSplits = _getStructsFor(_projectId, _domain, _group);\n\n // Check to see if all locked splits are included.\n for (uint256 _i = 0; _i < _currentSplits.length; _i++) {\n // If not locked, continue.\n if (block.timestamp >= _currentSplits[_i].lockedUntil) continue;\n\n // Keep a reference to whether or not the locked split being iterated on is included.\n bool _includesLocked = false;\n\n for (uint256 _j = 0; _j < _splits.length; _j++) {\n // Check for sameness.\n if (\n _splits[_j].percent == _currentSplits[_i].percent &&\n _splits[_j].beneficiary == _currentSplits[_i].beneficiary &&\n _splits[_j].allocator == _currentSplits[_i].allocator &&\n _splits[_j].projectId == _currentSplits[_i].projectId &&\n // Allow lock extention.\n _splits[_j].lockedUntil >= _currentSplits[_i].lockedUntil\n ) _includesLocked = true;\n }\n\n if (!_includesLocked) revert PREVIOUS_LOCKED_SPLITS_NOT_INCLUDED();\n }\n\n // Add up all the percents to make sure they cumulative are under 100%.\n uint256 _percentTotal = 0;\n\n for (uint256 _i = 0; _i < _splits.length; _i++) {\n // The percent should be greater than 0.\n if (_splits[_i].percent == 0) revert INVALID_SPLIT_PERCENT();\n\n // ProjectId should be within a uint56\n if (_splits[_i].projectId > type(uint56).max) revert INVALID_PROJECT_ID();\n\n // Add to the total percents.\n _percentTotal = _percentTotal + _splits[_i].percent;\n\n // Validate the total does not exceed the expected value.\n if (_percentTotal > JBConstants.SPLITS_TOTAL_PERCENT) revert INVALID_TOTAL_PERCENT();\n\n uint256 _packedSplitParts1;\n\n // prefer claimed in bit 0.\n if (_splits[_i].preferClaimed) _packedSplitParts1 = 1;\n // prefer add to balance in bit 1.\n if (_splits[_i].preferAddToBalance) _packedSplitParts1 |= 1 << 1;\n // percent in bits 2-33.\n _packedSplitParts1 |= _splits[_i].percent << 2;\n // projectId in bits 32-89.\n _packedSplitParts1 |= _splits[_i].projectId << 34;\n // beneficiary in bits 90-249.\n _packedSplitParts1 |= uint256(uint160(address(_splits[_i].beneficiary))) << 90;\n\n // Store the first spit part.\n _packedSplitParts1Of[_projectId][_domain][_group][_i] = _packedSplitParts1;\n\n // If there's data to store in the second packed split part, pack and store.\n if (_splits[_i].lockedUntil > 0 || _splits[_i].allocator != IJBSplitAllocator(address(0))) {\n // Locked until should be within a uint48\n if (_splits[_i].lockedUntil > type(uint48).max) revert INVALID_LOCKED_UNTIL();\n\n // lockedUntil in bits 0-47.\n uint256 _packedSplitParts2 = uint48(_splits[_i].lockedUntil);\n // allocator in bits 48-207.\n _packedSplitParts2 |= uint256(uint160(address(_splits[_i].allocator))) << 48;\n\n // Store the second split part.\n _packedSplitParts2Of[_projectId][_domain][_group][_i] = _packedSplitParts2;\n\n // Otherwise if there's a value stored in the indexed position, delete it.\n } else if (_packedSplitParts2Of[_projectId][_domain][_group][_i] > 0)\n delete _packedSplitParts2Of[_projectId][_domain][_group][_i];\n\n emit SetSplit(_projectId, _domain, _group, _splits[_i], msg.sender);\n }\n\n // Set the new length of the splits.\n _splitCountOf[_projectId][_domain][_group] = _splits.length;\n }\n\n /**\n @notice \n Unpack splits' packed stored values into easy-to-work-with spit structs.\n\n @param _projectId The ID of the project to which the split belongs.\n @param _domain The identifier within which the returned splits should be considered active.\n @param _group The identifying group of the splits.\n\n @return splits The split structs.\n */\n function _getStructsFor(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) private view returns (JBSplit[] memory) {\n // Get a reference to the number of splits that need to be added to the returned array.\n uint256 _splitCount = _splitCountOf[_projectId][_domain][_group];\n\n // Initialize an array to be returned that has the set length.\n JBSplit[] memory _splits = new JBSplit[](_splitCount);\n\n // Loop through each split and unpack the values into structs.\n for (uint256 _i = 0; _i < _splitCount; _i++) {\n // Get a reference to the fist packed data.\n uint256 _packedSplitPart1 = _packedSplitParts1Of[_projectId][_domain][_group][_i];\n\n // Populate the split struct.\n JBSplit memory _split;\n\n // prefer claimed in bit 0.\n _split.preferClaimed = _packedSplitPart1 & 1 == 1;\n // prefer add to balance in bit 1.\n _split.preferAddToBalance = (_packedSplitPart1 >> 1) & 1 == 1;\n // percent in bits 2-33.\n _split.percent = uint256(uint32(_packedSplitPart1 >> 2));\n // projectId in bits 32-89.\n _split.projectId = uint256(uint56(_packedSplitPart1 >> 34));\n // beneficiary in bits 90-249.\n _split.beneficiary = payable(address(uint160(_packedSplitPart1 >> 90)));\n\n // Get a reference to the second packed data.\n uint256 _packedSplitPart2 = _packedSplitParts2Of[_projectId][_domain][_group][_i];\n\n // If there's anything in it, unpack.\n if (_packedSplitPart2 > 0) {\n // lockedUntil in bits 0-47.\n _split.lockedUntil = uint256(uint48(_packedSplitPart2));\n // allocator in bits 48-207.\n _split.allocator = IJBSplitAllocator(address(uint160(_packedSplitPart2 >> 48)));\n }\n\n // Add the split to the value being returned.\n _splits[_i] = _split;\n }\n\n return _splits;\n }\n}\n" @@ -344,13 +344,13 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../abstract/JBOperatable.sol';\nimport './../interfaces/IJBController/2.sol';\nimport './../interfaces/IJBMigratable.sol';\nimport './../interfaces/IJBOperatorStore.sol';\nimport './../interfaces/IJBPaymentTerminal.sol';\nimport './../interfaces/IJBProjects.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBSplitsGroups.sol';\n\n/**\n @notice\n Stitches together funding cycles and community tokens, making sure all activity is accounted for and correct.\n\n @dev\n Adheres to -\n IJBController: General interface for the generic controller methods in this contract that interacts with funding cycles and tokens according to the protocol's rules.\n IJBMigratable: Allows migrating to this contract, with a hook called to prepare for the migration.\n\n @dev\n Inherits from -\n JBOperatable: Several functions in this contract can only be accessed by a project owner, or an address that has been preconfifigured to be an operator of the project.\n ERC165: Introspection on interface adherance. \n*/\ncontract JBController is IJBController, IJBMigratable, JBOperatable, ERC165 {\n // A library that parses the packed funding cycle metadata into a more friendly format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error BURN_PAUSED_AND_SENDER_NOT_VALID_TERMINAL_DELEGATE();\n error CANT_MIGRATE_TO_CURRENT_CONTROLLER();\n error CHANGE_TOKEN_NOT_ALLOWED();\n error FUNDING_CYCLE_ALREADY_LAUNCHED();\n error INVALID_BALLOT_REDEMPTION_RATE();\n error INVALID_DISTRIBUTION_LIMIT();\n error INVALID_DISTRIBUTION_LIMIT_CURRENCY();\n error INVALID_OVERFLOW_ALLOWANCE();\n error INVALID_OVERFLOW_ALLOWANCE_CURRENCY();\n error INVALID_REDEMPTION_RATE();\n error INVALID_RESERVED_RATE();\n error MIGRATION_NOT_ALLOWED();\n error MINT_NOT_ALLOWED_AND_NOT_TERMINAL_DELEGATE();\n error NO_BURNABLE_TOKENS();\n error NOT_CURRENT_CONTROLLER();\n error ZERO_TOKENS_TO_MINT();\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n The difference between the processed token tracker of a project and the project's token's total supply is the amount of tokens that still need to have reserves minted against them.\n\n _projectId The ID of the project to get the tracker of.\n */\n mapping(uint256 => int256) internal _processedTokenTrackerOf;\n\n /**\n @notice\n Data regarding the distribution limit of a project during a configuration.\n\n @dev\n bits 0-231: The amount of token that a project can distribute per funding cycle.\n\n @dev\n bits 232-255: The currency of amount that a project can distribute.\n\n _projectId The ID of the project to get the packed distribution limit data of.\n _configuration The configuration during which the packed distribution limit data applies.\n _terminal The terminal from which distributions are being limited.\n _token The token for which distributions are being limited.\n */\n mapping(uint256 => mapping(uint256 => mapping(IJBPaymentTerminal => mapping(address => uint256))))\n internal _packedDistributionLimitDataOf;\n\n /**\n @notice\n Data regarding the overflow allowance of a project during a configuration.\n\n @dev\n bits 0-231: The amount of overflow that a project is allowed to tap into on-demand throughout the configuration.\n\n @dev\n bits 232-255: The currency of the amount of overflow that a project is allowed to tap.\n\n _projectId The ID of the project to get the packed overflow allowance data of.\n _configuration The configuration during which the packed overflow allowance data applies.\n _terminal The terminal managing the overflow.\n _token The token for which overflow is being allowed.\n */\n mapping(uint256 => mapping(uint256 => mapping(IJBPaymentTerminal => mapping(address => uint256))))\n internal _packedOverflowAllowanceDataOf;\n\n //*********************************************************************//\n // --------------- public immutable stored properties ---------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that manages token minting and burning.\n */\n IJBTokenStore public immutable override tokenStore;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of token that a project can distribute per funding cycle, and the currency it's in terms of.\n\n @dev\n The number of decimals in the returned fixed point amount is the same as that of the specified terminal. \n\n @param _projectId The ID of the project to get the distribution limit of.\n @param _configuration The configuration during which the distribution limit applies.\n @param _terminal The terminal from which distributions are being limited.\n @param _token The token for which the distribution limit applies.\n\n @return The distribution limit, as a fixed point number with the same number of decimals as the provided terminal.\n @return The currency of the distribution limit.\n */\n function distributionLimitOf(\n uint256 _projectId,\n uint256 _configuration,\n IJBPaymentTerminal _terminal,\n address _token\n ) external view override returns (uint256, uint256) {\n // Get a reference to the packed data.\n uint256 _data = _packedDistributionLimitDataOf[_projectId][_configuration][_terminal][_token];\n\n // The limit is in bits 0-231. The currency is in bits 232-255.\n return (uint256(uint232(_data)), _data >> 232);\n }\n\n /**\n @notice\n The amount of overflow that a project is allowed to tap into on-demand throughout a configuration, and the currency it's in terms of.\n\n @dev\n The number of decimals in the returned fixed point amount is the same as that of the specified terminal. \n\n @param _projectId The ID of the project to get the overflow allowance of.\n @param _configuration The configuration of the during which the allowance applies.\n @param _terminal The terminal managing the overflow.\n @param _token The token for which the overflow allowance applies.\n\n @return The overflow allowance, as a fixed point number with the same number of decimals as the provided terminal.\n @return The currency of the overflow allowance.\n */\n function overflowAllowanceOf(\n uint256 _projectId,\n uint256 _configuration,\n IJBPaymentTerminal _terminal,\n address _token\n ) external view override returns (uint256, uint256) {\n // Get a reference to the packed data.\n uint256 _data = _packedOverflowAllowanceDataOf[_projectId][_configuration][_terminal][_token];\n\n // The allowance is in bits 0-231. The currency is in bits 232-255.\n return (uint256(uint232(_data)), _data >> 232);\n }\n\n /**\n @notice\n Gets the amount of reserved tokens that a project has available to distribute.\n\n @param _projectId The ID of the project to get a reserved token balance of.\n @param _reservedRate The reserved rate to use when making the calculation.\n\n @return The current amount of reserved tokens.\n */\n function reservedTokenBalanceOf(uint256 _projectId, uint256 _reservedRate)\n external\n view\n override\n returns (uint256)\n {\n return\n _reservedTokenAmountFrom(\n _processedTokenTrackerOf[_projectId],\n _reservedRate,\n tokenStore.totalSupplyOf(_projectId)\n );\n }\n\n /**\n @notice\n Gets the current total amount of outstanding tokens for a project, given a reserved rate.\n\n @param _projectId The ID of the project to get total outstanding tokens of.\n @param _reservedRate The reserved rate to use when making the calculation.\n\n @return The current total amount of outstanding tokens for the project.\n */\n function totalOutstandingTokensOf(uint256 _projectId, uint256 _reservedRate)\n external\n view\n override\n returns (uint256)\n {\n // Get the total number of tokens in circulation.\n uint256 _totalSupply = tokenStore.totalSupplyOf(_projectId);\n\n // Get the number of reserved tokens the project has.\n uint256 _reservedTokenAmount = _reservedTokenAmountFrom(\n _processedTokenTrackerOf[_projectId],\n _reservedRate,\n _totalSupply\n );\n\n // Add the reserved tokens to the total supply.\n return _totalSupply + _reservedTokenAmount;\n }\n\n /** \n @notice\n A project's funding cycle for the specified configuration along with its metadata.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n \n @return fundingCycle The funding cycle.\n @return metadata The funding cycle's metadata.\n */\n function getFundingCycleOf(uint256 _projectId, uint256 _configuration)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata)\n {\n fundingCycle = fundingCycleStore.get(_projectId, _configuration);\n metadata = fundingCycle.expandMetadata();\n }\n\n /** \n @notice\n A project's latest configured funding cycle along with its metadata and the ballot state of the configuration.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n \n @return fundingCycle The latest configured funding cycle.\n @return metadata The latest configured funding cycle's metadata.\n @return ballotState The state of the configuration.\n */\n function latestConfiguredFundingCycleOf(uint256 _projectId)\n external\n view\n override\n returns (\n JBFundingCycle memory fundingCycle,\n JBFundingCycleMetadata memory metadata,\n JBBallotState ballotState\n )\n {\n (fundingCycle, ballotState) = fundingCycleStore.latestConfiguredOf(_projectId);\n metadata = fundingCycle.expandMetadata();\n }\n\n /** \n @notice\n A project's current funding cycle along with its metadata.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n \n @return fundingCycle The current funding cycle.\n @return metadata The current funding cycle's metadata.\n */\n function currentFundingCycleOf(uint256 _projectId)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata)\n {\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n metadata = fundingCycle.expandMetadata();\n }\n\n /** \n @notice\n A project's queued funding cycle along with its metadata.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n \n @return fundingCycle The queued funding cycle.\n @return metadata The queued funding cycle's metadata.\n */\n function queuedFundingCycleOf(uint256 _projectId)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata)\n {\n fundingCycle = fundingCycleStore.queuedOf(_projectId);\n metadata = fundingCycle.expandMetadata();\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBController).interfaceId ||\n _interfaceId == type(IJBMigratable).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // ---------------------------- constructor -------------------------- //\n //*********************************************************************//\n\n /**\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _tokenStore A contract that manages token minting and burning.\n @param _splitsStore A contract that stores splits for each project.\n */\n constructor(\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBTokenStore _tokenStore,\n IJBSplitsStore _splitsStore\n ) JBOperatable(_operatorStore) {\n projects = _projects;\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n tokenStore = _tokenStore;\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // --------------------- external transactions ----------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Creates a project. This will mint an ERC-721 into the specified owner's account, configure a first funding cycle, and set up any splits.\n\n @dev\n Each operation within this transaction can be done in sequence separately.\n\n @dev\n Anyone can deploy a project on an owner's behalf.\n\n @param _owner The address to set as the owner of the project. The project ERC-721 will be owned by this address.\n @param _projectMetadata Metadata to associate with the project within a particular domain. This can be updated any time by the owner of the project.\n @param _data Data that defines the project's first funding cycle. These properties will remain fixed for the duration of the funding cycle.\n @param _metadata Metadata specifying the controller specific params that a funding cycle can have. These properties will remain fixed for the duration of the funding cycle.\n @param _mustStartAtOrAfter The time before which the configured funding cycle cannot start.\n @param _groupedSplits An array of splits to set for any number of groups. \n @param _fundAccessConstraints An array containing amounts that a project can use from its treasury for each payment terminal. Amounts are fixed point numbers using the same number of decimals as the accompanying terminal. The `_distributionLimit` and `_overflowAllowance` parameters must fit in a `uint232`.\n @param _terminals Payment terminals to add for the project.\n @param _memo A memo to pass along to the emitted event.\n\n @return projectId The ID of the project.\n */\n function launchProjectFor(\n address _owner,\n JBProjectMetadata calldata _projectMetadata,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] calldata _groupedSplits,\n JBFundAccessConstraints[] calldata _fundAccessConstraints,\n IJBPaymentTerminal[] memory _terminals,\n string memory _memo\n ) external virtual override returns (uint256 projectId) {\n // Mint the project into the wallet of the message sender.\n projectId = projects.createFor(_owner, _projectMetadata);\n\n // Set this contract as the project's controller in the directory.\n directory.setControllerOf(projectId, address(this));\n\n // Configure the first funding cycle.\n uint256 _configuration = _configure(\n projectId,\n _data,\n _metadata,\n _mustStartAtOrAfter,\n _groupedSplits,\n _fundAccessConstraints\n );\n\n // Add the provided terminals to the list of terminals.\n if (_terminals.length > 0) directory.setTerminalsOf(projectId, _terminals);\n\n emit LaunchProject(_configuration, projectId, _memo, msg.sender);\n }\n\n /**\n @notice\n Creates a funding cycle for an already existing project ERC-721.\n\n @dev\n Each operation within this transaction can be done in sequence separately.\n\n @dev\n Only a project owner or operator can launch its funding cycles.\n\n @param _projectId The ID of the project to launch funding cycles for.\n @param _data Data that defines the project's first funding cycle. These properties will remain fixed for the duration of the funding cycle.\n @param _metadata Metadata specifying the controller specific params that a funding cycle can have. These properties will remain fixed for the duration of the funding cycle.\n @param _mustStartAtOrAfter The time before which the configured funding cycle cannot start.\n @param _groupedSplits An array of splits to set for any number of groups. \n @param _fundAccessConstraints An array containing amounts that a project can use from its treasury for each payment terminal. Amounts are fixed point numbers using the same number of decimals as the accompanying terminal. The `_distributionLimit` and `_overflowAllowance` parameters must fit in a `uint232`.\n @param _terminals Payment terminals to add for the project.\n @param _memo A memo to pass along to the emitted event.\n\n @return configuration The configuration of the funding cycle that was successfully created.\n */\n function launchFundingCyclesFor(\n uint256 _projectId,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] calldata _groupedSplits,\n JBFundAccessConstraints[] memory _fundAccessConstraints,\n IJBPaymentTerminal[] memory _terminals,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.RECONFIGURE)\n returns (uint256 configuration)\n {\n // If there is a previous configuration, reconfigureFundingCyclesOf should be called instead\n if (fundingCycleStore.latestConfigurationOf(_projectId) > 0)\n revert FUNDING_CYCLE_ALREADY_LAUNCHED();\n\n // Set this contract as the project's controller in the directory.\n directory.setControllerOf(_projectId, address(this));\n\n // Configure the first funding cycle.\n configuration = _configure(\n _projectId,\n _data,\n _metadata,\n _mustStartAtOrAfter,\n _groupedSplits,\n _fundAccessConstraints\n );\n\n // Add the provided terminals to the list of terminals.\n if (_terminals.length > 0) directory.setTerminalsOf(_projectId, _terminals);\n\n emit LaunchFundingCycles(configuration, _projectId, _memo, msg.sender);\n }\n\n /**\n @notice\n Proposes a configuration of a subsequent funding cycle that will take effect once the current one expires if it is approved by the current funding cycle's ballot.\n\n @dev\n Only a project's owner or a designated operator can configure its funding cycles.\n\n @param _projectId The ID of the project whose funding cycles are being reconfigured.\n @param _data Data that defines the funding cycle. These properties will remain fixed for the duration of the funding cycle.\n @param _metadata Metadata specifying the controller specific params that a funding cycle can have. These properties will remain fixed for the duration of the funding cycle.\n @param _mustStartAtOrAfter The time before which the configured funding cycle cannot start.\n @param _groupedSplits An array of splits to set for any number of groups. \n @param _fundAccessConstraints An array containing amounts that a project can use from its treasury for each payment terminal. Amounts are fixed point numbers using the same number of decimals as the accompanying terminal. The `_distributionLimit` and `_overflowAllowance` parameters must fit in a `uint232`.\n @param _memo A memo to pass along to the emitted event.\n\n @return configuration The configuration of the funding cycle that was successfully reconfigured.\n */\n function reconfigureFundingCyclesOf(\n uint256 _projectId,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] calldata _groupedSplits,\n JBFundAccessConstraints[] calldata _fundAccessConstraints,\n string calldata _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.RECONFIGURE)\n returns (uint256 configuration)\n {\n // Configure the next funding cycle.\n configuration = _configure(\n _projectId,\n _data,\n _metadata,\n _mustStartAtOrAfter,\n _groupedSplits,\n _fundAccessConstraints\n );\n\n emit ReconfigureFundingCycles(configuration, _projectId, _memo, msg.sender);\n }\n\n /**\n @notice\n Issues an owner's ERC20 JBTokens that'll be used when claiming tokens.\n\n @dev\n Deploys a project's ERC20 JBToken contract.\n\n @dev\n Only a project's owner or operator can issue its token.\n\n @param _projectId The ID of the project being issued tokens.\n @param _name The ERC20's name.\n @param _symbol The ERC20's symbol.\n */\n function issueTokenFor(\n uint256 _projectId,\n string calldata _name,\n string calldata _symbol\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.ISSUE)\n returns (IJBToken token)\n {\n // Issue the token in the store.\n return tokenStore.issueFor(_projectId, _name, _symbol);\n }\n\n /**\n @notice\n Swap the current project's token that is minted and burned for another, and transfer ownership of the current token to another address if needed.\n\n @dev\n Only a project's owner or operator can change its token.\n\n @param _projectId The ID of the project to which the changed token belongs.\n @param _token The new token.\n @param _newOwner An address to transfer the current token's ownership to. This is optional, but it cannot be done later.\n */\n function changeTokenOf(\n uint256 _projectId,\n IJBToken _token,\n address _newOwner\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.CHANGE_TOKEN)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (!_fundingCycle.changeTokenAllowed()) revert CHANGE_TOKEN_NOT_ALLOWED();\n\n // Change the token in the store.\n tokenStore.changeFor(_projectId, _token, _newOwner);\n }\n\n /**\n @notice\n Mint new token supply into an account, and optionally reserve a supply to be distributed according to the project's current funding cycle configuration.\n\n @dev\n Only a project's owner, a designated operator, one of its terminals, or the current data source can mint its tokens.\n\n @param _projectId The ID of the project to which the tokens being minted belong.\n @param _tokenCount The amount of tokens to mint in total, counting however many should be reserved.\n @param _beneficiary The account that the tokens are being minted for.\n @param _memo A memo to pass along to the emitted event.\n @param _preferClaimedTokens A flag indicating whether a project's attached token contract should be minted if they have been issued.\n @param _useReservedRate Whether to use the current funding cycle's reserved rate in the mint calculation.\n\n @return beneficiaryTokenCount The amount of tokens minted for the beneficiary.\n */\n function mintTokensOf(\n uint256 _projectId,\n uint256 _tokenCount,\n address _beneficiary,\n string calldata _memo,\n bool _preferClaimedTokens,\n bool _useReservedRate\n ) external virtual override returns (uint256 beneficiaryTokenCount) {\n // There should be tokens to mint.\n if (_tokenCount == 0) revert ZERO_TOKENS_TO_MINT();\n\n // Define variables that will be needed outside scoped section below.\n // Keep a reference to the reserved rate to use\n uint256 _reservedRate;\n\n // Scoped section prevents stack too deep. `_fundingCycle` only used within scope.\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Minting limited to: project owner, authorized callers, project terminal and current funding cycle data source\n _requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.MINT,\n directory.isTerminalOf(_projectId, IJBPaymentTerminal(msg.sender)) ||\n msg.sender == address(_fundingCycle.dataSource())\n );\n\n // If the message sender is not a terminal or a datasource, the current funding cycle must allow minting.\n if (\n !_fundingCycle.mintingAllowed() &&\n !directory.isTerminalOf(_projectId, IJBPaymentTerminal(msg.sender)) &&\n msg.sender != address(_fundingCycle.dataSource())\n ) revert MINT_NOT_ALLOWED_AND_NOT_TERMINAL_DELEGATE();\n\n // Determine the reserved rate to use.\n _reservedRate = _useReservedRate ? _fundingCycle.reservedRate() : 0;\n }\n\n if (_reservedRate == JBConstants.MAX_RESERVED_RATE)\n // Subtract the total weighted amount from the tracker so the full reserved token amount can be printed later.\n _processedTokenTrackerOf[_projectId] =\n _processedTokenTrackerOf[_projectId] -\n int256(_tokenCount);\n else {\n // The unreserved token count that will be minted for the beneficiary.\n beneficiaryTokenCount = PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_RESERVED_RATE - _reservedRate,\n JBConstants.MAX_RESERVED_RATE\n );\n\n if (_reservedRate == 0)\n // If there's no reserved rate, increment the tracker with the newly minted tokens.\n _processedTokenTrackerOf[_projectId] =\n _processedTokenTrackerOf[_projectId] +\n int256(beneficiaryTokenCount);\n\n // Mint the tokens.\n tokenStore.mintFor(_beneficiary, _projectId, beneficiaryTokenCount, _preferClaimedTokens);\n }\n\n emit MintTokens(\n _beneficiary,\n _projectId,\n _tokenCount,\n beneficiaryTokenCount,\n _memo,\n _reservedRate,\n msg.sender\n );\n }\n\n /**\n @notice\n Burns a token holder's supply.\n\n @dev\n Only a token's holder, a designated operator, or a project's terminal can burn it.\n\n @param _holder The account that is having its tokens burned.\n @param _projectId The ID of the project to which the tokens being burned belong.\n @param _tokenCount The number of tokens to burn.\n @param _memo A memo to pass along to the emitted event.\n @param _preferClaimedTokens A flag indicating whether a project's attached token contract should be burned first if they have been issued.\n */\n function burnTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string calldata _memo,\n bool _preferClaimedTokens\n )\n external\n virtual\n override\n requirePermissionAllowingOverride(\n _holder,\n _projectId,\n JBOperations.BURN,\n directory.isTerminalOf(_projectId, IJBPaymentTerminal(msg.sender))\n )\n {\n // There should be tokens to burn\n if (_tokenCount == 0) revert NO_BURNABLE_TOKENS();\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // If the message sender is not a terminal, the current funding cycle must not be paused.\n if (\n _fundingCycle.burnPaused() &&\n !directory.isTerminalOf(_projectId, IJBPaymentTerminal(msg.sender))\n ) revert BURN_PAUSED_AND_SENDER_NOT_VALID_TERMINAL_DELEGATE();\n\n // Update the token tracker so that reserved tokens will still be correctly mintable.\n _processedTokenTrackerOf[_projectId] =\n _processedTokenTrackerOf[_projectId] -\n int256(_tokenCount);\n\n // Burn the tokens.\n tokenStore.burnFrom(_holder, _projectId, _tokenCount, _preferClaimedTokens);\n\n emit BurnTokens(_holder, _projectId, _tokenCount, _memo, msg.sender);\n }\n\n /**\n @notice\n Distributes all outstanding reserved tokens for a project.\n\n @param _projectId The ID of the project to which the reserved tokens belong.\n @param _memo A memo to pass along to the emitted event.\n\n @return The amount of minted reserved tokens.\n */\n function distributeReservedTokensOf(uint256 _projectId, string calldata _memo)\n external\n virtual\n override\n returns (uint256)\n {\n return _distributeReservedTokensOf(_projectId, _memo);\n }\n\n /**\n @notice\n Allows other controllers to signal to this one that a migration is expected for the specified project.\n\n @dev\n This controller should not yet be the project's controller.\n\n @param _projectId The ID of the project that will be migrated to this controller.\n @param _from The controller being migrated from.\n */\n function prepForMigrationOf(uint256 _projectId, address _from) external virtual override {\n // This controller must not be the project's current controller.\n if (directory.controllerOf(_projectId) == address(this))\n revert CANT_MIGRATE_TO_CURRENT_CONTROLLER();\n\n // Set the tracker as the total supply.\n _processedTokenTrackerOf[_projectId] = int256(tokenStore.totalSupplyOf(_projectId));\n\n emit PrepMigration(_projectId, _from, msg.sender);\n }\n\n /**\n @notice\n Allows a project to migrate from this controller to another.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project that will be migrated from this controller.\n @param _to The controller to which the project is migrating.\n */\n function migrate(uint256 _projectId, IJBMigratable _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_CONTROLLER)\n {\n // This controller must be the project's current controller.\n if (directory.controllerOf(_projectId) != address(this)) revert NOT_CURRENT_CONTROLLER();\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.controllerMigrationAllowed()) revert MIGRATION_NOT_ALLOWED();\n\n // All reserved tokens must be minted before migrating.\n if (uint256(_processedTokenTrackerOf[_projectId]) != tokenStore.totalSupplyOf(_projectId))\n _distributeReservedTokensOf(_projectId, '');\n\n // Make sure the new controller is prepped for the migration.\n _to.prepForMigrationOf(_projectId, address(this));\n\n // Set the new controller.\n directory.setControllerOf(_projectId, address(_to));\n\n emit Migrate(_projectId, _to, msg.sender);\n }\n\n //*********************************************************************//\n // ------------------------ internal functions ----------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Distributes all outstanding reserved tokens for a project.\n\n @param _projectId The ID of the project to which the reserved tokens belong.\n @param _memo A memo to pass along to the emitted event.\n\n @return tokenCount The amount of minted reserved tokens.\n */\n function _distributeReservedTokensOf(uint256 _projectId, string memory _memo)\n internal\n returns (uint256 tokenCount)\n {\n // Get the current funding cycle to read the reserved rate from.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to new total supply of tokens before minting reserved tokens.\n uint256 _totalTokens = tokenStore.totalSupplyOf(_projectId);\n\n // Get a reference to the number of tokens that need to be minted.\n tokenCount = _reservedTokenAmountFrom(\n _processedTokenTrackerOf[_projectId],\n _fundingCycle.reservedRate(),\n _totalTokens\n );\n\n // Set the tracker to be the new total supply.\n _processedTokenTrackerOf[_projectId] = int256(_totalTokens + tokenCount);\n\n // Get a reference to the project owner.\n address _owner = projects.ownerOf(_projectId);\n\n // Distribute tokens to splits and get a reference to the leftover amount to mint after all splits have gotten their share.\n uint256 _leftoverTokenCount = tokenCount == 0\n ? 0\n : _distributeToReservedTokenSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n JBSplitsGroups.RESERVED_TOKENS,\n tokenCount\n );\n\n // Mint any leftover tokens to the project owner.\n if (_leftoverTokenCount > 0) tokenStore.mintFor(_owner, _projectId, _leftoverTokenCount, false);\n\n emit DistributeReservedTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _owner,\n tokenCount,\n _leftoverTokenCount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Distribute tokens to the splits according to the specified funding cycle configuration.\n\n @param _projectId The ID of the project for which reserved token splits are being distributed.\n @param _domain The domain of the splits to distribute the reserved tokens between.\n @param _group The group of the splits to distribute the reserved tokens between.\n @param _amount The total amount of tokens to mint.\n\n @return leftoverAmount If the splits percents dont add up to 100%, the leftover amount is returned.\n */\n function _distributeToReservedTokenSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount\n ) internal returns (uint256 leftoverAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n\n // Get a reference to the project's reserved token splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n //Transfer between all splits.\n for (uint256 _i = 0; _i < _splits.length; _i++) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _tokenCount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n // Mints tokens for the split if needed.\n if (_tokenCount > 0) {\n tokenStore.mintFor(\n // If an allocator is set in the splits, set it as the beneficiary.\n // Otherwise if a projectId is set in the split, set the project's owner as the beneficiary.\n // If the split has a beneficiary send to the split's beneficiary. Otherwise send to the msg.sender.\n _split.allocator != IJBSplitAllocator(address(0))\n ? address(_split.allocator)\n : _split.projectId != 0\n ? projects.ownerOf(_split.projectId)\n : _split.beneficiary != address(0)\n ? _split.beneficiary\n : msg.sender,\n _projectId,\n _tokenCount,\n _split.preferClaimed\n );\n\n // If there's an allocator set, trigger its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0)))\n _split.allocator.allocate(\n JBSplitAllocationData(\n address(tokenStore.tokenOf(_projectId)),\n _tokenCount,\n 18,\n _projectId,\n _group,\n _split\n )\n );\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _tokenCount;\n }\n\n emit DistributeToReservedTokenSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _tokenCount,\n msg.sender\n );\n }\n }\n\n /**\n @notice\n Configures a funding cycle and stores information pertinent to the configuration.\n\n @param _projectId The ID of the project whose funding cycles are being reconfigured.\n @param _data Data that defines the funding cycle. These properties will remain fixed for the duration of the funding cycle.\n @param _metadata Metadata specifying the controller specific params that a funding cycle can have. These properties will remain fixed for the duration of the funding cycle.\n @param _mustStartAtOrAfter The time before which the configured funding cycle cannot start.\n @param _groupedSplits An array of splits to set for any number of groups. \n @param _fundAccessConstraints An array containing amounts that a project can use from its treasury for each payment terminal. Amounts are fixed point numbers using the same number of decimals as the accompanying terminal.\n\n @return configuration The configuration of the funding cycle that was successfully reconfigured.\n */\n function _configure(\n uint256 _projectId,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] memory _groupedSplits,\n JBFundAccessConstraints[] memory _fundAccessConstraints\n ) internal returns (uint256) {\n // Make sure the provided reserved rate is valid.\n if (_metadata.reservedRate > JBConstants.MAX_RESERVED_RATE) revert INVALID_RESERVED_RATE();\n\n // Make sure the provided redemption rate is valid.\n if (_metadata.redemptionRate > JBConstants.MAX_REDEMPTION_RATE)\n revert INVALID_REDEMPTION_RATE();\n\n // Make sure the provided ballot redemption rate is valid.\n if (_metadata.ballotRedemptionRate > JBConstants.MAX_REDEMPTION_RATE)\n revert INVALID_BALLOT_REDEMPTION_RATE();\n\n // Configure the funding cycle's properties.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.configureFor(\n _projectId,\n _data,\n JBFundingCycleMetadataResolver.packFundingCycleMetadata(_metadata),\n _mustStartAtOrAfter\n );\n\n // Set splits for the group.\n splitsStore.set(_projectId, _fundingCycle.configuration, _groupedSplits);\n\n // Set distribution limits if there are any.\n for (uint256 _i; _i < _fundAccessConstraints.length; _i++) {\n JBFundAccessConstraints memory _constraints = _fundAccessConstraints[_i];\n\n // If distribution limit value is larger than 232 bits, revert.\n if (_constraints.distributionLimit > type(uint232).max) revert INVALID_DISTRIBUTION_LIMIT();\n\n // If distribution limit currency value is larger than 24 bits, revert.\n if (_constraints.distributionLimitCurrency > type(uint24).max)\n revert INVALID_DISTRIBUTION_LIMIT_CURRENCY();\n\n // If overflow allowance value is larger than 232 bits, revert.\n if (_constraints.overflowAllowance > type(uint232).max) revert INVALID_OVERFLOW_ALLOWANCE();\n\n // If overflow allowance currency value is larger than 24 bits, revert.\n if (_constraints.overflowAllowanceCurrency > type(uint24).max)\n revert INVALID_OVERFLOW_ALLOWANCE_CURRENCY();\n\n // Set the distribution limit if there is one.\n if (_constraints.distributionLimit > 0)\n _packedDistributionLimitDataOf[_projectId][_fundingCycle.configuration][\n _constraints.terminal\n ][_constraints.token] =\n _constraints.distributionLimit |\n (_constraints.distributionLimitCurrency << 232);\n\n // Set the overflow allowance if there is one.\n if (_constraints.overflowAllowance > 0)\n _packedOverflowAllowanceDataOf[_projectId][_fundingCycle.configuration][\n _constraints.terminal\n ][_constraints.token] =\n _constraints.overflowAllowance |\n (_constraints.overflowAllowanceCurrency << 232);\n\n emit SetFundAccessConstraints(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _constraints,\n msg.sender\n );\n }\n\n return _fundingCycle.configuration;\n }\n\n /**\n @notice\n Gets the amount of reserved tokens currently tracked for a project given a reserved rate.\n\n @param _processedTokenTracker The tracker to make the calculation with.\n @param _reservedRate The reserved rate to use to make the calculation.\n @param _totalEligibleTokens The total amount to make the calculation with.\n\n @return amount reserved token amount.\n */\n function _reservedTokenAmountFrom(\n int256 _processedTokenTracker,\n uint256 _reservedRate,\n uint256 _totalEligibleTokens\n ) internal pure returns (uint256) {\n // Get a reference to the amount of tokens that are unprocessed.\n uint256 _unprocessedTokenBalanceOf = _processedTokenTracker >= 0\n ? _totalEligibleTokens - uint256(_processedTokenTracker)\n : _totalEligibleTokens + uint256(-_processedTokenTracker);\n\n // If there are no unprocessed tokens, return.\n if (_unprocessedTokenBalanceOf == 0) return 0;\n\n // If all tokens are reserved, return the full unprocessed amount.\n if (_reservedRate == JBConstants.MAX_RESERVED_RATE) return _unprocessedTokenBalanceOf;\n\n return\n PRBMath.mulDiv(\n _unprocessedTokenBalanceOf,\n JBConstants.MAX_RESERVED_RATE,\n JBConstants.MAX_RESERVED_RATE - _reservedRate\n ) - _unprocessedTokenBalanceOf;\n }\n}\n" }, "contracts/JBETHPaymentTerminal/2.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './../abstract/JBPayoutRedemptionPaymentTerminal/2.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n JBTokens.ETH,\n 18, // 18 decimals.\n JBCurrencies.ETH,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal pure override {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './../abstract/JBPayoutRedemptionPaymentTerminal/2.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n JBTokens.GAS_TOKEN,\n 18, // 18 decimals.\n JBCurrencies.GAS_CURRENCY,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal pure override {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n}\n" }, "contracts/JBERC20PaymentTerminal/2.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol';\nimport './../abstract/JBPayoutRedemptionPaymentTerminal/2.sol';\n\n/** \n @notice \n Manages the inflows and outflows of an ERC-20 token.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\ncontract JBERC20PaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n IERC20Metadata _token,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n address(_token),\n _token.decimals(),\n _currency,\n _baseWeightCurrency,\n _payoutSplitsGroup,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from == address(this)\n ? IERC20(token).transfer(_to, _amount)\n : IERC20(token).transferFrom(_from, _to, _amount);\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal override {\n IERC20(token).approve(_to, _amount);\n }\n}\n" }, "contracts/JBSingleTokenPaymentTerminalStore/2.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController/2.sol';\nimport './../interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBSingleTokenPaymentTerminalStore is IJBSingleTokenPaymentTerminalStore, ReentrancyGuard {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n Mint's 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegate A delegate contract to use for subsequent calls.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n IJBPayDelegate delegate,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay()) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegate) = IJBFundingCycleDataSource(fundingCycle.dataSource()).payParams(\n _data\n );\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegate, memo);\n\n // Add the amount to the token balance of the project.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount.value;\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegate, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegate A delegate contract to use for subsequent calls.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n IJBRedemptionDelegate delegate,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\n _projectId,\n fundingCycle.reservedRate()\n );\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow > 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem()) {\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n fundingCycle.redemptionRate(),\n fundingCycle.ballotRedemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegate) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .redeemParams(_data);\n } else {\n memo = _memo;\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (reclaimAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (reclaimAmount > 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n reclaimAmount;\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n return _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i = 0; _i < _terminals.length; _i++)\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.ETH\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.ETH, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController/2.sol';\nimport './../interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBSingleTokenPaymentTerminalStore is IJBSingleTokenPaymentTerminalStore, ReentrancyGuard {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n Mint's 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegate A delegate contract to use for subsequent calls.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n IJBPayDelegate delegate,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay()) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegate) = IJBFundingCycleDataSource(fundingCycle.dataSource()).payParams(\n _data\n );\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegate, memo);\n\n // Add the amount to the token balance of the project.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount.value;\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegate, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegate A delegate contract to use for subsequent calls.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n IJBRedemptionDelegate delegate,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\n _projectId,\n fundingCycle.reservedRate()\n );\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow > 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem()) {\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n fundingCycle.redemptionRate(),\n fundingCycle.ballotRedemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegate) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .redeemParams(_data);\n } else {\n memo = _memo;\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (reclaimAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (reclaimAmount > 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n reclaimAmount;\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n return _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i = 0; _i < _terminals.length; _i++)\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.GAS_CURRENCY\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.GAS_CURRENCY, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" }, "contracts/JBFundingCycleStore/2.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../abstract/JBControllerUtility.sol';\nimport './../libraries/JBConstants.sol';\n\n/** \n @notice \n Manages funding cycle configurations and scheduling.\n\n @dev\n Adheres to -\n IJBTokenStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBControllerUtility: Includes convenience functionality for checking if the message sender is the current controller of the project whose data is being manipulated.\n*/\ncontract JBFundingCycleStore is IJBFundingCycleStore, JBControllerUtility {\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_DISCOUNT_RATE();\n error INVALID_DURATION();\n error INVALID_WEIGHT();\n error NO_SAME_BLOCK_RECONFIGURATION();\n\n //*********************************************************************//\n // --------------------- private stored properties ------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Stores the user defined properties of each funding cycle, packed into one storage slot.\n\n _projectId The ID of the project to get properties of.\n _configuration The funding cycle configuration to get properties of.\n */\n mapping(uint256 => mapping(uint256 => uint256)) private _packedUserPropertiesOf;\n\n /** \n @notice\n Stores the properties added by the mechanism to manage and schedule each funding cycle, packed into one storage slot.\n \n _projectId The ID of the project to get instrinsic properties of.\n _configuration The funding cycle configuration to get properties of.\n */\n mapping(uint256 => mapping(uint256 => uint256)) private _packedIntrinsicPropertiesOf;\n\n /** \n @notice\n Stores the metadata for each funding cycle configuration, packed into one storage slot.\n\n _projectId The ID of the project to get metadata of.\n _configuration The funding cycle configuration to get metadata of.\n */\n mapping(uint256 => mapping(uint256 => uint256)) private _metadataOf;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The latest funding cycle configuration for each project.\n\n _projectId The ID of the project to get the latest funding cycle configuration of.\n */\n mapping(uint256 => uint256) public override latestConfigurationOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice \n Get the funding cycle with the given configuration for the specified project.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n @param _configuration The configuration of the funding cycle to get.\n\n @return fundingCycle The funding cycle.\n */\n function get(uint256 _projectId, uint256 _configuration)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle)\n {\n return _getStructFor(_projectId, _configuration);\n }\n\n /**\n @notice \n The latest funding cycle to be configured for the specified project, and its current ballot state.\n\n @param _projectId The ID of the project to get the latest configured funding cycle of.\n\n @return fundingCycle The project's queued funding cycle.\n @return ballotState The state of the ballot for the reconfiguration.\n */\n function latestConfiguredOf(uint256 _projectId)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle, JBBallotState ballotState)\n {\n // Get a reference to the latest funding cycle configuration.\n uint256 _fundingCycleConfiguration = latestConfigurationOf[_projectId];\n\n // Resolve the funding cycle for the latest configuration.\n fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n // Resolve the ballot state.\n ballotState = _ballotStateOf(\n _projectId,\n fundingCycle.configuration,\n fundingCycle.start,\n fundingCycle.basedOn\n );\n }\n\n /**\n @notice \n The funding cycle that's next up for the specified project.\n\n @dev\n If a queued funding cycle of the project is not found, returns an empty funding cycle with all properties set to 0.\n\n @param _projectId The ID of the project to get the queued funding cycle of.\n\n @return fundingCycle The project's queued funding cycle.\n */\n function queuedOf(uint256 _projectId)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle)\n {\n // If the project does not have a funding cycle, return an empty struct.\n if (latestConfigurationOf[_projectId] == 0) return _getStructFor(0, 0);\n\n // Get a reference to the configuration of the standby funding cycle.\n uint256 _standbyFundingCycleConfiguration = _standbyOf(_projectId);\n\n // If it exists, return its funding cycle if it is approved.\n if (_standbyFundingCycleConfiguration > 0) {\n fundingCycle = _getStructFor(_projectId, _standbyFundingCycleConfiguration);\n\n if (_isApproved(_projectId, fundingCycle)) return fundingCycle;\n\n // Resolve the funding cycle for the latest configured funding cycle.\n fundingCycle = _getStructFor(_projectId, fundingCycle.basedOn);\n } else {\n // Resolve the funding cycle for the latest configured funding cycle.\n fundingCycle = _getStructFor(_projectId, latestConfigurationOf[_projectId]);\n\n // If the latest funding cycle starts in the future, it must start in the distant future\n // since its not in standby. In this case base the queued cycles on the base cycle.\n if (fundingCycle.start > block.timestamp)\n fundingCycle = _getStructFor(_projectId, fundingCycle.basedOn);\n }\n\n // There's no queued if the current has a duration of 0.\n if (fundingCycle.duration == 0) return _getStructFor(0, 0);\n\n // Check to see if this funding cycle's ballot is approved.\n // If so, return a funding cycle based on it.\n if (_isApproved(_projectId, fundingCycle)) return _mockFundingCycleBasedOn(fundingCycle, false);\n\n // Get the funding cycle of its base funding cycle, which carries the last approved configuration.\n fundingCycle = _getStructFor(_projectId, fundingCycle.basedOn);\n\n // There's no queued if the base, which must still be the current, has a duration of 0.\n if (fundingCycle.duration == 0) return _getStructFor(0, 0);\n\n // Return a mock of the next up funding cycle.\n return _mockFundingCycleBasedOn(fundingCycle, false);\n }\n\n /**\n @notice \n The funding cycle that is currently active for the specified project.\n\n @dev\n If a current funding cycle of the project is not found, returns an empty funding cycle with all properties set to 0.\n\n @param _projectId The ID of the project to get the current funding cycle of.\n\n @return fundingCycle The project's current funding cycle.\n */\n function currentOf(uint256 _projectId)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle)\n {\n // If the project does not have a funding cycle, return an empty struct.\n if (latestConfigurationOf[_projectId] == 0) return _getStructFor(0, 0);\n\n // Get a reference to the configuration of the eligible funding cycle.\n uint256 _fundingCycleConfiguration = _eligibleOf(_projectId);\n\n // Keep a reference to the eligible funding cycle.\n JBFundingCycle memory _fundingCycle;\n\n // If an eligible funding cycle exists...\n if (_fundingCycleConfiguration > 0) {\n // Resolve the funding cycle for the eligible configuration.\n _fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n // Check to see if this funding cycle's ballot is approved.\n // If so, return it.\n if (_isApproved(_projectId, _fundingCycle)) return _fundingCycle;\n\n // If it hasn't been approved, set the funding cycle configuration to be the configuration of the funding cycle that it's based on,\n // which carries the last approved configuration.\n _fundingCycleConfiguration = _fundingCycle.basedOn;\n } else {\n // No upcoming funding cycle found that is eligible to become active,\n // so use the last configuration.\n _fundingCycleConfiguration = latestConfigurationOf[_projectId];\n\n // Get the funding cycle for the latest ID.\n _fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n // If it's not approved or if it hasn't yet started, get a reference to the funding cycle that the latest is based on, which has the latest approved configuration.\n if (!_isApproved(_projectId, _fundingCycle) || block.timestamp < _fundingCycle.start)\n _fundingCycleConfiguration = _fundingCycle.basedOn;\n }\n\n // If there is not funding cycle to base the current one on, there can't be a current one.\n if (_fundingCycleConfiguration == 0) return _getStructFor(0, 0);\n\n // The funding cycle to base a current one on.\n _fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n // If the base has no duration, it's still the current one.\n if (_fundingCycle.duration == 0) return _fundingCycle;\n\n // Return a mock of the current funding cycle.\n return _mockFundingCycleBasedOn(_fundingCycle, true);\n }\n\n /** \n @notice \n The current ballot state of the project.\n\n @param _projectId The ID of the project to check the ballot state of.\n\n @return The project's current ballot's state.\n */\n function currentBallotStateOf(uint256 _projectId) external view override returns (JBBallotState) {\n // Get a reference to the latest funding cycle configuration.\n uint256 _fundingCycleConfiguration = latestConfigurationOf[_projectId];\n\n // Resolve the funding cycle for the latest configuration.\n JBFundingCycle memory _fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n return\n _ballotStateOf(\n _projectId,\n _fundingCycle.configuration,\n _fundingCycle.start,\n _fundingCycle.basedOn\n );\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _directory A contract storing directories of terminals and controllers for each project.\n */\n // solhint-disable-next-line no-empty-blocks\n constructor(IJBDirectory _directory) JBControllerUtility(_directory) {}\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice \n Configures the next eligible funding cycle for the specified project.\n\n @dev\n Only a project's current controller can configure its funding cycles.\n\n @param _projectId The ID of the project being configured.\n @param _data The funding cycle configuration data.\n @param _metadata Arbitrary extra data to associate with this funding cycle configuration that's not used within.\n @param _mustStartAtOrAfter The time before which the initialized funding cycle cannot start.\n\n @return The funding cycle that the configuration will take effect during.\n */\n function configureFor(\n uint256 _projectId,\n JBFundingCycleData calldata _data,\n uint256 _metadata,\n uint256 _mustStartAtOrAfter\n ) external override onlyController(_projectId) returns (JBFundingCycle memory) {\n // Duration must fit in a uint64.\n if (_data.duration > type(uint64).max) revert INVALID_DURATION();\n\n // Discount rate must be less than or equal to 100%.\n if (_data.discountRate > JBConstants.MAX_DISCOUNT_RATE) revert INVALID_DISCOUNT_RATE();\n\n // Weight must fit into a uint88.\n if (_data.weight > type(uint88).max) revert INVALID_WEIGHT();\n\n // The configuration timestamp is now.\n uint256 _configuration = block.timestamp;\n\n // Set up a reconfiguration by configuring intrinsic properties.\n _configureIntrinsicPropertiesFor(\n _projectId,\n _configuration,\n _data.weight,\n // Must start on or after the current timestamp.\n _mustStartAtOrAfter > block.timestamp ? _mustStartAtOrAfter : block.timestamp\n );\n\n // Efficiently stores a funding cycles provided user defined properties.\n // If all user config properties are zero, no need to store anything as the default value will have the same outcome.\n if (\n _data.ballot != IJBFundingCycleBallot(address(0)) ||\n _data.duration > 0 ||\n _data.discountRate > 0\n ) {\n // ballot in bits 0-159 bytes.\n uint256 packed = uint160(address(_data.ballot));\n\n // duration in bits 160-223 bytes.\n packed |= _data.duration << 160;\n\n // discountRate in bits 224-255 bytes.\n packed |= _data.discountRate << 224;\n\n // Set in storage.\n _packedUserPropertiesOf[_projectId][_configuration] = packed;\n }\n\n // Set the metadata if needed.\n if (_metadata > 0) _metadataOf[_projectId][_configuration] = _metadata;\n\n emit Configure(_configuration, _projectId, _data, _metadata, _mustStartAtOrAfter, msg.sender);\n\n // Return the funding cycle for the new configuration.\n return _getStructFor(_projectId, _configuration);\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice \n Updates the configurable funding cycle for this project if it exists, otherwise creates one.\n\n @param _projectId The ID of the project to find a configurable funding cycle for.\n @param _configuration The time at which the funding cycle was configured.\n @param _weight The weight to store in the configured funding cycle.\n @param _mustStartAtOrAfter The time before which the initialized funding cycle can't start.\n */\n function _configureIntrinsicPropertiesFor(\n uint256 _projectId,\n uint256 _configuration,\n uint256 _weight,\n uint256 _mustStartAtOrAfter\n ) private {\n // If there's not yet a funding cycle for the project, initialize one.\n if (latestConfigurationOf[_projectId] == 0)\n // Use an empty funding cycle as the base.\n return\n _initFor(_projectId, _getStructFor(0, 0), _configuration, _mustStartAtOrAfter, _weight);\n\n // Get the active funding cycle's configuration.\n uint256 _currentConfiguration = _eligibleOf(_projectId);\n\n // If an eligible funding cycle does not exist, get a reference to the latest funding cycle configuration for the project.\n if (_currentConfiguration == 0)\n // Get the latest funding cycle's configuration.\n _currentConfiguration = latestConfigurationOf[_projectId];\n\n // Get a reference to the funding cycle.\n JBFundingCycle memory _baseFundingCycle = _getStructFor(_projectId, _currentConfiguration);\n\n if (!_isApproved(_projectId, _baseFundingCycle) || block.timestamp < _baseFundingCycle.start)\n // If it hasn't been approved or hasn't yet started, set the ID to be the funding cycle it's based on,\n // which carries the latest approved configuration.\n _baseFundingCycle = _getStructFor(_projectId, _baseFundingCycle.basedOn);\n\n // The configuration can't be the same as the base configuration.\n if (_baseFundingCycle.configuration == _configuration) revert NO_SAME_BLOCK_RECONFIGURATION();\n\n // The time after the ballot of the provided funding cycle has expired.\n // If the provided funding cycle has no ballot, return the current timestamp.\n uint256 _timestampAfterBallot = _baseFundingCycle.ballot == IJBFundingCycleBallot(address(0))\n ? 0\n : _configuration + _baseFundingCycle.ballot.duration();\n\n _initFor(\n _projectId,\n _baseFundingCycle,\n _configuration,\n // Can only start after the ballot.\n _timestampAfterBallot > _mustStartAtOrAfter ? _timestampAfterBallot : _mustStartAtOrAfter,\n _weight\n );\n }\n\n /**\n @notice \n Initializes a funding cycle with the specified properties.\n\n @param _projectId The ID of the project to which the funding cycle being initialized belongs.\n @param _baseFundingCycle The funding cycle to base the initialized one on.\n @param _configuration The configuration of the funding cycle being initialized.\n @param _mustStartAtOrAfter The time before which the initialized funding cycle cannot start.\n @param _weight The weight to give the newly initialized funding cycle.\n */\n function _initFor(\n uint256 _projectId,\n JBFundingCycle memory _baseFundingCycle,\n uint256 _configuration,\n uint256 _mustStartAtOrAfter,\n uint256 _weight\n ) private {\n // If there is no base, initialize a first cycle.\n if (_baseFundingCycle.number == 0) {\n // The first number is 1.\n uint256 _number = 1;\n\n // Set fresh intrinsic properties.\n _packAndStoreIntrinsicPropertiesOf(\n _configuration,\n _projectId,\n _number,\n _weight,\n _baseFundingCycle.configuration,\n _mustStartAtOrAfter\n );\n } else {\n // Derive the correct next start time from the base.\n uint256 _start = _deriveStartFrom(_baseFundingCycle, _mustStartAtOrAfter);\n\n // A weight of 1 is treated as a weight of 0.\n // This is to allow a weight of 0 (default) to represent inheriting the discounted weight of the previous funding cycle.\n _weight = _weight > 0\n ? (_weight == 1 ? 0 : _weight)\n : _deriveWeightFrom(_baseFundingCycle, _start);\n\n // Derive the correct number.\n uint256 _number = _deriveNumberFrom(_baseFundingCycle, _start);\n\n // Update the intrinsic properties.\n _packAndStoreIntrinsicPropertiesOf(\n _configuration,\n _projectId,\n _number,\n _weight,\n _baseFundingCycle.configuration,\n _start\n );\n }\n\n // Set the project's latest funding cycle configuration.\n latestConfigurationOf[_projectId] = _configuration;\n\n emit Init(_configuration, _projectId, _baseFundingCycle.configuration);\n }\n\n /**\n @notice \n Efficiently stores a funding cycle's provided intrinsic properties.\n\n @param _configuration The configuration of the funding cycle to pack and store.\n @param _projectId The ID of the project to which the funding cycle belongs.\n @param _number The number of the funding cycle.\n @param _weight The weight of the funding cycle.\n @param _basedOn The configuration of the base funding cycle.\n @param _start The start time of this funding cycle.\n */\n function _packAndStoreIntrinsicPropertiesOf(\n uint256 _configuration,\n uint256 _projectId,\n uint256 _number,\n uint256 _weight,\n uint256 _basedOn,\n uint256 _start\n ) private {\n // weight in bits 0-87.\n uint256 packed = _weight;\n\n // basedOn in bits 88-143.\n packed |= _basedOn << 88;\n\n // start in bits 144-199.\n packed |= _start << 144;\n\n // number in bits 200-255.\n packed |= _number << 200;\n\n // Store the packed value.\n _packedIntrinsicPropertiesOf[_projectId][_configuration] = packed;\n }\n\n /**\n @notice \n The project's stored funding cycle that hasn't yet started and should be used next, if one exists.\n\n @dev\n A value of 0 is returned if no funding cycle was found.\n\n @dev\n Assumes the project has a latest configuration.\n \n @param _projectId The ID of a project to look through for a standby cycle.\n\n @return configuration The configuration of the standby funding cycle if one exists, or 0 if one doesn't exist.\n */\n function _standbyOf(uint256 _projectId) private view returns (uint256 configuration) {\n // Get a reference to the project's latest funding cycle.\n configuration = latestConfigurationOf[_projectId];\n\n // Get the necessary properties for the latest funding cycle.\n JBFundingCycle memory _fundingCycle = _getStructFor(_projectId, configuration);\n\n // There is no upcoming funding cycle if the latest funding cycle has already started.\n if (block.timestamp >= _fundingCycle.start) return 0;\n\n // If this is the first funding cycle, it is queued.\n if (_fundingCycle.number == 1) return configuration;\n\n // Get the necessary properties for the base funding cycle.\n JBFundingCycle memory _baseFundingCycle = _getStructFor(_projectId, _fundingCycle.basedOn);\n\n // If the latest configuration doesn't start until after another base cycle, return 0.\n if (\n _baseFundingCycle.duration > 0 &&\n block.timestamp < _fundingCycle.start - _baseFundingCycle.duration\n ) return 0;\n }\n\n /**\n @notice \n The project's stored funding cycle that has started and hasn't yet expired.\n \n @dev\n A value of 0 is returned if no funding cycle was found.\n\n @dev\n Assumes the project has a latest configuration.\n\n @param _projectId The ID of the project to look through.\n\n @return configuration The configuration of an eligible funding cycle if one exists, or 0 if one doesn't exist.\n */\n function _eligibleOf(uint256 _projectId) private view returns (uint256 configuration) {\n // Get a reference to the project's latest funding cycle.\n configuration = latestConfigurationOf[_projectId];\n\n // Get the latest funding cycle.\n JBFundingCycle memory _fundingCycle = _getStructFor(_projectId, configuration);\n\n // If the latest is expired, return an empty funding cycle.\n // A duration of 0 cannot be expired.\n if (\n _fundingCycle.duration > 0 && block.timestamp >= _fundingCycle.start + _fundingCycle.duration\n ) return 0;\n\n // Return the funding cycle's configuration if it has started.\n if (block.timestamp >= _fundingCycle.start) return _fundingCycle.configuration;\n\n // Get a reference to the cycle's base configuration.\n JBFundingCycle memory _baseFundingCycle = _getStructFor(_projectId, _fundingCycle.basedOn);\n\n // If the base cycle isn't eligible, the project has no eligible cycle.\n // A duration of 0 is always eligible.\n if (\n _baseFundingCycle.duration > 0 &&\n block.timestamp >= _baseFundingCycle.start + _baseFundingCycle.duration\n ) return 0;\n\n // Return the configuration that the latest funding cycle is based on.\n configuration = _fundingCycle.basedOn;\n }\n\n /** \n @notice \n A view of the funding cycle that would be created based on the provided one if the project doesn't make a reconfiguration.\n\n @dev\n Returns an empty funding cycle if there can't be a mock funding cycle based on the provided one.\n\n @dev\n Assumes a funding cycle with a duration of 0 will never be asked to be the base of a mock.\n\n @param _baseFundingCycle The funding cycle that the resulting funding cycle should follow.\n @param _allowMidCycle A flag indicating if the mocked funding cycle is allowed to already be mid cycle.\n\n @return A mock of what the next funding cycle will be.\n */\n function _mockFundingCycleBasedOn(JBFundingCycle memory _baseFundingCycle, bool _allowMidCycle)\n private\n view\n returns (JBFundingCycle memory)\n {\n // Get the distance of the current time to the start of the next possible funding cycle.\n // If the returned mock cycle must not yet have started, the start time of the mock must be in the future.\n uint256 _mustStartAtOrAfter = !_allowMidCycle\n ? block.timestamp + 1\n : block.timestamp - _baseFundingCycle.duration + 1;\n\n // Derive what the start time should be.\n uint256 _start = _deriveStartFrom(_baseFundingCycle, _mustStartAtOrAfter);\n\n // Derive what the number should be.\n uint256 _number = _deriveNumberFrom(_baseFundingCycle, _start);\n\n return\n JBFundingCycle(\n _number,\n _baseFundingCycle.configuration,\n _baseFundingCycle.basedOn,\n _start,\n _baseFundingCycle.duration,\n _deriveWeightFrom(_baseFundingCycle, _start),\n _baseFundingCycle.discountRate,\n _baseFundingCycle.ballot,\n _baseFundingCycle.metadata\n );\n }\n\n /** \n @notice \n The date that is the nearest multiple of the specified funding cycle's duration from its end.\n\n @param _baseFundingCycle The funding cycle to base the calculation on.\n @param _mustStartAtOrAfter A date that the derived start must be on or come after.\n\n @return start The next start time.\n */\n function _deriveStartFrom(JBFundingCycle memory _baseFundingCycle, uint256 _mustStartAtOrAfter)\n private\n pure\n returns (uint256 start)\n {\n // A subsequent cycle to one with a duration of 0 should start as soon as possible.\n if (_baseFundingCycle.duration == 0) return _mustStartAtOrAfter;\n\n // The time when the funding cycle immediately after the specified funding cycle starts.\n uint256 _nextImmediateStart = _baseFundingCycle.start + _baseFundingCycle.duration;\n\n // If the next immediate start is now or in the future, return it.\n if (_nextImmediateStart >= _mustStartAtOrAfter) return _nextImmediateStart;\n\n // The amount of seconds since the `_mustStartAtOrAfter` time which results in a start time that might satisfy the specified constraints.\n uint256 _timeFromImmediateStartMultiple = (_mustStartAtOrAfter - _nextImmediateStart) %\n _baseFundingCycle.duration;\n\n // A reference to the first possible start timestamp.\n start = _mustStartAtOrAfter - _timeFromImmediateStartMultiple;\n\n // Add increments of duration as necessary to satisfy the threshold.\n while (_mustStartAtOrAfter > start) start = start + _baseFundingCycle.duration;\n }\n\n /** \n @notice \n The accumulated weight change since the specified funding cycle.\n\n @param _baseFundingCycle The funding cycle to base the calculation on.\n @param _start The start time of the funding cycle to derive a number for.\n\n @return weight The derived weight, as a fixed point number with 18 decimals.\n */\n function _deriveWeightFrom(JBFundingCycle memory _baseFundingCycle, uint256 _start)\n private\n pure\n returns (uint256 weight)\n {\n // A subsequent cycle to one with a duration of 0 should have the next possible weight.\n if (_baseFundingCycle.duration == 0)\n return\n PRBMath.mulDiv(\n _baseFundingCycle.weight,\n JBConstants.MAX_DISCOUNT_RATE - _baseFundingCycle.discountRate,\n JBConstants.MAX_DISCOUNT_RATE\n );\n\n // The weight should be based off the base funding cycle's weight.\n weight = _baseFundingCycle.weight;\n\n // If the discount is 0, the weight doesn't change.\n if (_baseFundingCycle.discountRate == 0) return weight;\n\n // The difference between the start of the base funding cycle and the proposed start.\n uint256 _startDistance = _start - _baseFundingCycle.start;\n\n // Apply the base funding cycle's discount rate for each cycle that has passed.\n uint256 _discountMultiple = _startDistance / _baseFundingCycle.duration;\n\n for (uint256 i = 0; i < _discountMultiple; i++) {\n // The number of times to apply the discount rate.\n // Base the new weight on the specified funding cycle's weight.\n weight = PRBMath.mulDiv(\n weight,\n JBConstants.MAX_DISCOUNT_RATE - _baseFundingCycle.discountRate,\n JBConstants.MAX_DISCOUNT_RATE\n );\n // The calculation doesn't need to continue if the weight is 0.\n if (weight == 0) break;\n }\n }\n\n /** \n @notice \n The number of the next funding cycle given the specified funding cycle.\n\n @param _baseFundingCycle The funding cycle to base the calculation on.\n @param _start The start time of the funding cycle to derive a number for.\n\n @return The funding cycle number.\n */\n function _deriveNumberFrom(JBFundingCycle memory _baseFundingCycle, uint256 _start)\n private\n pure\n returns (uint256)\n {\n // A subsequent cycle to one with a duration of 0 should be the next number.\n if (_baseFundingCycle.duration == 0) return _baseFundingCycle.number + 1;\n\n // The difference between the start of the base funding cycle and the proposed start.\n uint256 _startDistance = _start - _baseFundingCycle.start;\n\n // Find the number of base cycles that fit in the start distance.\n return _baseFundingCycle.number + (_startDistance / _baseFundingCycle.duration);\n }\n\n /** \n @notice \n Checks to see if the provided funding cycle is approved according to the correct ballot.\n\n @param _projectId The ID of the project to which the funding cycle belongs. \n @param _fundingCycle The funding cycle to get an approval flag for.\n\n @return The approval flag.\n */\n function _isApproved(uint256 _projectId, JBFundingCycle memory _fundingCycle)\n private\n view\n returns (bool)\n {\n return\n _ballotStateOf(\n _projectId,\n _fundingCycle.configuration,\n _fundingCycle.start,\n _fundingCycle.basedOn\n ) == JBBallotState.Approved;\n }\n\n /**\n @notice \n A project's latest funding cycle configuration approval status.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n @param _configuration The funding cycle configuration to get the ballot state of.\n @param _start The start time of the funding cycle configuration to get the ballot state of.\n @param _ballotFundingCycleConfiguration The configuration of the funding cycle which is configured with the ballot that should be used.\n\n @return The ballot state of the project.\n */\n function _ballotStateOf(\n uint256 _projectId,\n uint256 _configuration,\n uint256 _start,\n uint256 _ballotFundingCycleConfiguration\n ) private view returns (JBBallotState) {\n // If there is no ballot funding cycle, implicitly approve.\n if (_ballotFundingCycleConfiguration == 0) return JBBallotState.Approved;\n\n // Get the ballot funding cycle.\n JBFundingCycle memory _ballotFundingCycle = _getStructFor(\n _projectId,\n _ballotFundingCycleConfiguration\n );\n\n // If there is no ballot, the ID is auto approved.\n // Otherwise if the ballot's duration hasn't passed, its still active.\n // Otherwise, return the ballot's state.\n if (_ballotFundingCycle.ballot == IJBFundingCycleBallot(address(0)))\n return JBBallotState.Approved;\n else if (_ballotFundingCycle.ballot.duration() >= block.timestamp - _configuration)\n return JBBallotState.Active;\n else return _ballotFundingCycle.ballot.stateOf(_projectId, _configuration, _start);\n }\n\n /**\n @notice \n Unpack a funding cycle's packed stored values into an easy-to-work-with funding cycle struct.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n @param _configuration The funding cycle configuration to get the full struct for.\n\n @return fundingCycle A funding cycle struct.\n */\n function _getStructFor(uint256 _projectId, uint256 _configuration)\n private\n view\n returns (JBFundingCycle memory fundingCycle)\n {\n // Return an empty funding cycle if the configuration specified is 0.\n if (_configuration == 0) return fundingCycle;\n\n fundingCycle.configuration = _configuration;\n\n uint256 _packedIntrinsicProperties = _packedIntrinsicPropertiesOf[_projectId][_configuration];\n\n // weight in bits 0-87 bits.\n fundingCycle.weight = uint256(uint88(_packedIntrinsicProperties));\n // basedOn in bits 88-143 bits.\n fundingCycle.basedOn = uint256(uint56(_packedIntrinsicProperties >> 88));\n // start in bits 144-199 bits.\n fundingCycle.start = uint256(uint56(_packedIntrinsicProperties >> 144));\n // number in bits 200-255 bits.\n fundingCycle.number = uint256(uint56(_packedIntrinsicProperties >> 200));\n\n uint256 _packedUserProperties = _packedUserPropertiesOf[_projectId][_configuration];\n\n // ballot in bits 0-159 bits.\n fundingCycle.ballot = IJBFundingCycleBallot(address(uint160(_packedUserProperties)));\n // duration in bits 160-223 bits.\n fundingCycle.duration = uint256(uint64(_packedUserProperties >> 160));\n // discountRate in bits 224-255 bits.\n fundingCycle.discountRate = uint256(uint32(_packedUserProperties >> 224));\n\n fundingCycle.metadata = _metadataOf[_projectId][_configuration];\n }\n}\n" @@ -359,7 +359,7 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './../../structs/JBFundAccessConstraints.sol';\nimport './../../structs/JBFundingCycleData.sol';\nimport './../../structs/JBFundingCycleMetadata.sol';\nimport './../../structs/JBGroupedSplits.sol';\nimport './../../structs/JBProjectMetadata.sol';\nimport './../IJBDirectory.sol';\nimport './../IJBFundingCycleStore.sol';\nimport './../IJBMigratable.sol';\nimport './../IJBPaymentTerminal.sol';\nimport './../IJBSplitsStore/2.sol';\nimport './../IJBToken.sol';\nimport './../IJBTokenStore.sol';\n\ninterface IJBController is IERC165 {\n event LaunchProject(uint256 configuration, uint256 projectId, string memo, address caller);\n\n event LaunchFundingCycles(uint256 configuration, uint256 projectId, string memo, address caller);\n\n event ReconfigureFundingCycles(\n uint256 configuration,\n uint256 projectId,\n string memo,\n address caller\n );\n\n event SetFundAccessConstraints(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n JBFundAccessConstraints constraints,\n address caller\n );\n\n event DistributeReservedTokens(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address beneficiary,\n uint256 tokenCount,\n uint256 beneficiaryTokenCount,\n string memo,\n address caller\n );\n\n event DistributeToReservedTokenSplit(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n JBSplit split,\n uint256 tokenCount,\n address caller\n );\n\n event MintTokens(\n address indexed beneficiary,\n uint256 indexed projectId,\n uint256 tokenCount,\n uint256 beneficiaryTokenCount,\n string memo,\n uint256 reservedRate,\n address caller\n );\n\n event BurnTokens(\n address indexed holder,\n uint256 indexed projectId,\n uint256 tokenCount,\n string memo,\n address caller\n );\n\n event Migrate(uint256 indexed projectId, IJBMigratable to, address caller);\n\n event PrepMigration(uint256 indexed projectId, address from, address caller);\n\n function projects() external view returns (IJBProjects);\n\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\n\n function tokenStore() external view returns (IJBTokenStore);\n\n function splitsStore() external view returns (IJBSplitsStore);\n\n function directory() external view returns (IJBDirectory);\n\n function reservedTokenBalanceOf(uint256 _projectId, uint256 _reservedRate)\n external\n view\n returns (uint256);\n\n function distributionLimitOf(\n uint256 _projectId,\n uint256 _configuration,\n IJBPaymentTerminal _terminal,\n address _token\n ) external view returns (uint256 distributionLimit, uint256 distributionLimitCurrency);\n\n function overflowAllowanceOf(\n uint256 _projectId,\n uint256 _configuration,\n IJBPaymentTerminal _terminal,\n address _token\n ) external view returns (uint256 overflowAllowance, uint256 overflowAllowanceCurrency);\n\n function totalOutstandingTokensOf(uint256 _projectId, uint256 _reservedRate)\n external\n view\n returns (uint256);\n\n function getFundingCycleOf(uint256 _projectId, uint256 _configuration)\n external\n view\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\n\n function latestConfiguredFundingCycleOf(uint256 _projectId)\n external\n view\n returns (\n JBFundingCycle memory,\n JBFundingCycleMetadata memory metadata,\n JBBallotState\n );\n\n function currentFundingCycleOf(uint256 _projectId)\n external\n view\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\n\n function queuedFundingCycleOf(uint256 _projectId)\n external\n view\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\n\n function launchProjectFor(\n address _owner,\n JBProjectMetadata calldata _projectMetadata,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] memory _groupedSplits,\n JBFundAccessConstraints[] memory _fundAccessConstraints,\n IJBPaymentTerminal[] memory _terminals,\n string calldata _memo\n ) external returns (uint256 projectId);\n\n function launchFundingCyclesFor(\n uint256 _projectId,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] memory _groupedSplits,\n JBFundAccessConstraints[] memory _fundAccessConstraints,\n IJBPaymentTerminal[] memory _terminals,\n string calldata _memo\n ) external returns (uint256 configuration);\n\n function reconfigureFundingCyclesOf(\n uint256 _projectId,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] memory _groupedSplits,\n JBFundAccessConstraints[] memory _fundAccessConstraints,\n string calldata _memo\n ) external returns (uint256);\n\n function issueTokenFor(\n uint256 _projectId,\n string calldata _name,\n string calldata _symbol\n ) external returns (IJBToken token);\n\n function changeTokenOf(\n uint256 _projectId,\n IJBToken _token,\n address _newOwner\n ) external;\n\n function mintTokensOf(\n uint256 _projectId,\n uint256 _tokenCount,\n address _beneficiary,\n string calldata _memo,\n bool _preferClaimedTokens,\n bool _useReservedRate\n ) external returns (uint256 beneficiaryTokenCount);\n\n function burnTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string calldata _memo,\n bool _preferClaimedTokens\n ) external;\n\n function distributeReservedTokensOf(uint256 _projectId, string memory _memo)\n external\n returns (uint256);\n\n function migrate(uint256 _projectId, IJBMigratable _to) external;\n}\n" }, "contracts/abstract/JBPayoutRedemptionPaymentTerminal/2.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../../interfaces/IJBController/2.sol';\nimport './../../interfaces/IJBPayoutRedemptionPaymentTerminal/2.sol';\nimport './../../libraries/JBConstants.sol';\nimport './../../libraries/JBCurrencies.sol';\nimport './../../libraries/JBFixedPointNumber.sol';\nimport './../../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../../libraries/JBOperations.sol';\nimport './../../libraries/JBSplitsGroups.sol';\nimport './../../libraries/JBTokens.sol';\nimport './../../structs/JBTokenAmount.sol';\nimport './../JBOperatable.sol';\nimport './../JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal is\n IJBPayoutRedemptionPaymentTerminal,\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n ReentrancyGuard\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The protocol project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _PROTOCOL_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.ETH)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.ETH, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.ETH) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i = 0; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @dev\n If the fee gauge reverts when called upon while a project is attempting to distribute its funds, a project's funds will be locked. This is a known risk.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual;\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual;\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegate` only used within scope.\n {\n IJBRedemptionDelegate _delegate;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegate, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If a delegate was returned by the data source, issue a callback to it.\n if (_delegate != IJBRedemptionDelegate(address(0))) {\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _beneficiary,\n _memo,\n _metadata\n );\n _delegate.didRedeem(_data);\n emit DelegateDidRedeem(_delegate, _data, msg.sender);\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convinience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n\n // Take the fee.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || _feeEligibleDistributionAmount == 0\n ? 0\n : _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n );\n\n // Get a reference to how much to distribute to the project owner, which is the leftover amount minus any fees.\n\n unchecked {\n netLeftoverDistributionAmount = _leftoverDistributionAmount == 0\n ? 0\n : _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n }\n\n // Transfer any remaining balance to the project owner.\n if (netLeftoverDistributionAmount > 0)\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convinience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i = 0; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount;\n\n if (_payoutAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (isFeelessAddress[address(_split.allocator)])\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _netPayoutAmount : 0;\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n _netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // Save gas if this contract is being used as the terminal.\n if (_terminal == this) {\n // This distribution does not incur a fee.\n _netPayoutAmount = _payoutAmount;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\n else\n _pay(\n _netPayoutAmount,\n address(this),\n _split.projectId,\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n } else {\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (isFeelessAddress[address(_terminal)])\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _netPayoutAmount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _terminal.addToBalanceOf{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n '',\n _projectMetadata\n );\n else\n _terminal.pay{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n }\n } else {\n unchecked {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(\n address(this),\n _split.beneficiary != address(0) ? _split.beneficiary : payable(msg.sender),\n _netPayoutAmount\n );\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _PROTOCOL_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n */\n function _processFee(uint256 _amount, address _beneficiary) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_PROTOCOL_PROJECT_ID, token);\n\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\n if (_terminal == this)\n _pay(_amount, address(this), _PROTOCOL_PROJECT_ID, _beneficiary, 0, false, '', bytes('')); // Use the local pay call.\n else {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _amount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _amount : 0;\n\n // Send the payment.\n _terminal.pay{value: _payableValue}(\n _PROTOCOL_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the external pay call of the correct terminal.\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegate` and `_tokenCount` only used within scope.\n {\n IJBPayDelegate _delegate;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegate, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If a delegate was returned by the data source, issue a callback to it.\n if (_delegate != IJBPayDelegate(address(0))) {\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n _delegate.didPay(_data);\n emit DelegateDidPay(_delegate, _data, msg.sender);\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i = 0; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n unchecked {\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256 feeDiscount) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (directory.primaryTerminalOf(_PROTOCOL_PROJECT_ID, token) == IJBPaymentTerminal(address(0)))\n return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge == IJBFeeGauge(address(0)))\n feeDiscount = 0;\n // If the guage reverts, set the discount to 0.\n else\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n feeDiscount = discount;\n } catch {\n feeDiscount = 0;\n }\n\n // If the fee discount is greater than the max, nullify the discount.\n if (feeDiscount > JBConstants.MAX_FEE_DISCOUNT) feeDiscount = 0;\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../../interfaces/IJBController/2.sol';\nimport './../../interfaces/IJBPayoutRedemptionPaymentTerminal/2.sol';\nimport './../../libraries/JBConstants.sol';\nimport './../../libraries/JBCurrencies.sol';\nimport './../../libraries/JBFixedPointNumber.sol';\nimport './../../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../../libraries/JBOperations.sol';\nimport './../../libraries/JBSplitsGroups.sol';\nimport './../../libraries/JBTokens.sol';\nimport './../../structs/JBTokenAmount.sol';\nimport './../JBOperatable.sol';\nimport './../JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal is\n IJBPayoutRedemptionPaymentTerminal,\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n ReentrancyGuard\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The protocol project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _PROTOCOL_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.GAS_CURRENCY)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.GAS_CURRENCY, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.GAS_TOKEN) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i = 0; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @dev\n If the fee gauge reverts when called upon while a project is attempting to distribute its funds, a project's funds will be locked. This is a known risk.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual;\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual;\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegate` only used within scope.\n {\n IJBRedemptionDelegate _delegate;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegate, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If a delegate was returned by the data source, issue a callback to it.\n if (_delegate != IJBRedemptionDelegate(address(0))) {\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _beneficiary,\n _memo,\n _metadata\n );\n _delegate.didRedeem(_data);\n emit DelegateDidRedeem(_delegate, _data, msg.sender);\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convinience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n\n // Take the fee.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || _feeEligibleDistributionAmount == 0\n ? 0\n : _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n );\n\n // Get a reference to how much to distribute to the project owner, which is the leftover amount minus any fees.\n\n unchecked {\n netLeftoverDistributionAmount = _leftoverDistributionAmount == 0\n ? 0\n : _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n }\n\n // Transfer any remaining balance to the project owner.\n if (netLeftoverDistributionAmount > 0)\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convinience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i = 0; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount;\n\n if (_payoutAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (isFeelessAddress[address(_split.allocator)])\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0;\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n _netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // Save gas if this contract is being used as the terminal.\n if (_terminal == this) {\n // This distribution does not incur a fee.\n _netPayoutAmount = _payoutAmount;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\n else\n _pay(\n _netPayoutAmount,\n address(this),\n _split.projectId,\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n } else {\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (isFeelessAddress[address(_terminal)])\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _terminal.addToBalanceOf{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n '',\n _projectMetadata\n );\n else\n _terminal.pay{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n }\n } else {\n unchecked {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(\n address(this),\n _split.beneficiary != address(0) ? _split.beneficiary : payable(msg.sender),\n _netPayoutAmount\n );\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _PROTOCOL_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n */\n function _processFee(uint256 _amount, address _beneficiary) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_PROTOCOL_PROJECT_ID, token);\n\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\n if (_terminal == this)\n _pay(_amount, address(this), _PROTOCOL_PROJECT_ID, _beneficiary, 0, false, '', bytes('')); // Use the local pay call.\n else {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _amount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send the payment.\n _terminal.pay{value: _payableValue}(\n _PROTOCOL_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the external pay call of the correct terminal.\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegate` and `_tokenCount` only used within scope.\n {\n IJBPayDelegate _delegate;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegate, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If a delegate was returned by the data source, issue a callback to it.\n if (_delegate != IJBPayDelegate(address(0))) {\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n _delegate.didPay(_data);\n emit DelegateDidPay(_delegate, _data, msg.sender);\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i = 0; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n unchecked {\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256 feeDiscount) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (directory.primaryTerminalOf(_PROTOCOL_PROJECT_ID, token) == IJBPaymentTerminal(address(0)))\n return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge == IJBFeeGauge(address(0)))\n feeDiscount = 0;\n // If the guage reverts, set the discount to 0.\n else\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n feeDiscount = discount;\n } catch {\n feeDiscount = 0;\n }\n\n // If the fee discount is greater than the max, nullify the discount.\n if (feeDiscount > JBConstants.MAX_FEE_DISCOUNT) feeDiscount = 0;\n }\n}\n" }, "contracts/interfaces/IJBPayoutRedemptionPaymentTerminal/2.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/token/ERC721/IERC721.sol';\nimport './../../structs/JBFee.sol';\nimport './../IJBAllowanceTerminal.sol';\nimport './../IJBDirectory.sol';\nimport './../IJBFeeGauge.sol';\nimport './../IJBPayDelegate.sol';\nimport './../IJBPaymentTerminal.sol';\nimport './../IJBPayoutTerminal.sol';\nimport './../IJBPrices.sol';\nimport './../IJBProjects.sol';\nimport './../IJBRedemptionDelegate.sol';\nimport './../IJBRedemptionTerminal.sol';\nimport './../IJBSingleTokenPaymentTerminal.sol';\nimport './../IJBSingleTokenPaymentTerminalStore.sol';\nimport './../IJBSplitsStore/2.sol';\n\ninterface IJBPayoutRedemptionPaymentTerminal is\n IJBPaymentTerminal,\n IJBPayoutTerminal,\n IJBAllowanceTerminal,\n IJBRedemptionTerminal\n{\n event AddToBalance(\n uint256 indexed projectId,\n uint256 amount,\n uint256 refundedFees,\n string memo,\n bytes metadata,\n address caller\n );\n\n event Migrate(\n uint256 indexed projectId,\n IJBPaymentTerminal indexed to,\n uint256 amount,\n address caller\n );\n\n event DistributePayouts(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address beneficiary,\n uint256 amount,\n uint256 distributedAmount,\n uint256 fee,\n uint256 beneficiaryDistributionAmount,\n string memo,\n address caller\n );\n\n event UseAllowance(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address beneficiary,\n uint256 amount,\n uint256 distributedAmount,\n uint256 netDistributedamount,\n string memo,\n address caller\n );\n\n event HoldFee(\n uint256 indexed projectId,\n uint256 indexed amount,\n uint256 indexed fee,\n uint256 feeDiscount,\n address beneficiary,\n address caller\n );\n\n event ProcessFee(\n uint256 indexed projectId,\n uint256 indexed amount,\n bool indexed wasHeld,\n address beneficiary,\n address caller\n );\n\n event RefundHeldFees(\n uint256 indexed projectId,\n uint256 indexed amount,\n uint256 indexed refundedFees,\n uint256 leftoverAmount,\n address caller\n );\n\n event Pay(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address payer,\n address beneficiary,\n uint256 amount,\n uint256 beneficiaryTokenCount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DelegateDidPay(IJBPayDelegate indexed delegate, JBDidPayData data, address caller);\n\n event RedeemTokens(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address holder,\n address beneficiary,\n uint256 tokenCount,\n uint256 reclaimedAmount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DelegateDidRedeem(\n IJBRedemptionDelegate indexed delegate,\n JBDidRedeemData data,\n address caller\n );\n\n event DistributeToPayoutSplit(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n JBSplit split,\n uint256 amount,\n address caller\n );\n\n event SetFee(uint256 fee, address caller);\n\n event SetFeeGauge(IJBFeeGauge indexed feeGauge, address caller);\n\n event SetFeelessAddress(address indexed addrs, bool indexed flag, address caller);\n\n function projects() external view returns (IJBProjects);\n\n function splitsStore() external view returns (IJBSplitsStore);\n\n function directory() external view returns (IJBDirectory);\n\n function prices() external view returns (IJBPrices);\n\n function store() external view returns (IJBSingleTokenPaymentTerminalStore);\n\n function baseWeightCurrency() external view returns (uint256);\n\n function payoutSplitsGroup() external view returns (uint256);\n\n function heldFeesOf(uint256 _projectId) external view returns (JBFee[] memory);\n\n function fee() external view returns (uint256);\n\n function feeGauge() external view returns (IJBFeeGauge);\n\n function isFeelessAddress(address _contract) external view returns (bool);\n\n function migrate(uint256 _projectId, IJBPaymentTerminal _to) external returns (uint256 balance);\n\n function processFees(uint256 _projectId) external;\n\n function setFee(uint256 _fee) external;\n\n function setFeeGauge(IJBFeeGauge _feeGauge) external;\n\n function setFeelessAddress(address _contract, bool _flag) external;\n}\n" @@ -394,29 +394,29 @@ "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface AggregatorV3Interface {\n\n function decimals()\n external\n view\n returns (\n uint8\n );\n\n function description()\n external\n view\n returns (\n string memory\n );\n\n function version()\n external\n view\n returns (\n uint256\n );\n\n // getRoundData and latestRoundData should both raise \"No data present\"\n // if they do not have data to report, instead of returning unset values\n // which could be misinterpreted as actual reported values.\n function getRoundData(\n uint80 _roundId\n )\n external\n view\n returns (\n uint80 roundId,\n int256 answer,\n uint256 startedAt,\n uint256 updatedAt,\n uint80 answeredInRound\n );\n\n function latestRoundData()\n external\n view\n returns (\n uint80 roundId,\n int256 answer,\n uint256 startedAt,\n uint256 updatedAt,\n uint80 answeredInRound\n );\n\n}\n" }, - "contracts/JBETHERC20SplitsPayer/2.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBSplitsPayer/2.sol';\nimport './../interfaces/IJBSplitsStore/2.sol';\nimport './../libraries/JBConstants.sol';\nimport './../JBETHERC20ProjectPayer.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\n\n @dev\n Adheres to -\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBETHERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBETHERC20SplitsPayer is IJBSplitsPayer, JBETHERC20ProjectPayer, ReentrancyGuard {\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The ID of project for which the default splits are stored. \n */\n uint256 public override defaultSplitsProjectId;\n\n /**\n @notice\n The domain within which the default splits are stored. \n */\n uint256 public override defaultSplitsDomain;\n\n /**\n @notice\n The group within which the default splits are stored. \n */\n uint256 public override defaultSplitsGroup;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBETHERC20ProjectPayer, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n )\n JBETHERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _preferAddToBalance,\n _splitsStore.directory(),\n _owner\n )\n {\n defaultSplitsProjectId = _defaultSplitsProjectId;\n defaultSplitsDomain = _defaultSplitsDomain;\n defaultSplitsGroup = _defaultSplitsGroup;\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default split group using the stored default properties.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override nonReentrant {\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n JBTokens.ETH,\n address(this).balance,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender\n );\n\n // If there is no leftover amount, nothing left to pay.\n if (_leftoverAmount == 0) return;\n\n // If there's a default project ID, try to pay it.\n if (defaultProjectId != 0)\n if (defaultPreferAddToBalance)\n // Pay the project by adding to its balance if prefered.\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.ETH,\n _leftoverAmount,\n 18, // decimals.\n defaultMemo,\n defaultMetadata\n );\n // Otherwise, issue a payment to the project.\n else\n _pay(\n defaultProjectId,\n JBTokens.ETH,\n _leftoverAmount,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n 0, // min returned tokens.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n // If no project was specified, send the funds directly to the beneficiary or the msg.sender.\n else\n Address.sendValue(\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(msg.sender),\n _leftoverAmount\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the location of the splits that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n */\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) external virtual override onlyOwner {\n // Set the default splits project ID if it's changing.\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\n\n // Set the default splits domain if it's changing.\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\n\n // Set the default splits group if it's changing.\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\n\n emit SetDefaultSplits(_projectId, _domain, _group, msg.sender);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender\n );\n\n // Pay any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to pay it.\n if (_projectId != 0) {\n _pay(\n _projectId,\n _token,\n _leftoverAmount,\n _decimals,\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n // If no project was specified, send the funds directly to the beneficiary or the msg.sender.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _beneficiary != address(0) ? payable(_beneficiary) : payable(msg.sender),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).transfer(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _leftoverAmount\n );\n }\n }\n\n emit Pay(\n _projectId,\n _beneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event. \n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender\n );\n\n // Distribute any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to add to its balance.\n if (_projectId != 0)\n // Add to the project's balance.\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\n\n // Otherwise, send a payment to the beneficiary.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(msg.sender),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).transfer(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _leftoverAmount\n );\n }\n }\n\n emit AddToBalance(\n _projectId,\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splitsProjectId The ID of the project to which the splits belong.\n @param _splitsDomain The splits domain to which the group belongs.\n @param _splitsGroup The splits group to pay.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payToSplits(\n uint256 _splitsProjectId,\n uint256 _splitsDomain,\n uint256 _splitsGroup,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Get a reference to the splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup);\n\n // Set the leftover amount to the initial balance.\n leftoverAmount = _amount;\n\n // Settle between all splits.\n for (uint256 i = 0; i < _splits.length; i++) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[i];\n\n // The amount to send towards the split.\n uint256 _splitAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n if (_splitAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n _token,\n _splitAmount,\n _decimals,\n defaultProjectId,\n 0,\n _split\n );\n\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\n if (_token != JBTokens.ETH)\n IERC20(_token).approve(address(_split.allocator), _splitAmount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _splitAmount : 0;\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n if (_split.preferAddToBalance)\n _addToBalanceOf(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n 0,\n _split.preferClaimed,\n defaultMemo,\n defaultMetadata\n );\n } else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _split.beneficiary != address(0) ? _split.beneficiary : payable(_defaultBeneficiary),\n _splitAmount\n );\n // Or, transfer the ERC20.\n else {\n IERC20(_token).transfer(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n _splitAmount\n );\n }\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _splitAmount;\n }\n\n emit DistributeToSplit(\n _splitsProjectId,\n _splitsDomain,\n _splitsGroup,\n _split,\n _splitAmount,\n msg.sender\n );\n }\n }\n}\n" + "contracts/JBGasTokenERC20SplitsPayer/2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBSplitsPayer/2.sol';\nimport './../interfaces/IJBSplitsStore/2.sol';\nimport './../libraries/JBConstants.sol';\nimport './../JBGasTokenERC20ProjectPayer.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\n\n @dev\n Adheres to -\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBGasTokenERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBGasTokenERC20SplitsPayer is IJBSplitsPayer, JBGasTokenERC20ProjectPayer, ReentrancyGuard {\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The ID of project for which the default splits are stored. \n */\n uint256 public override defaultSplitsProjectId;\n\n /**\n @notice\n The domain within which the default splits are stored. \n */\n uint256 public override defaultSplitsDomain;\n\n /**\n @notice\n The group within which the default splits are stored. \n */\n uint256 public override defaultSplitsGroup;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBGasTokenERC20ProjectPayer, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n )\n JBGasTokenERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _preferAddToBalance,\n _splitsStore.directory(),\n _owner\n )\n {\n defaultSplitsProjectId = _defaultSplitsProjectId;\n defaultSplitsDomain = _defaultSplitsDomain;\n defaultSplitsGroup = _defaultSplitsGroup;\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default split group using the stored default properties.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override nonReentrant {\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender\n );\n\n // If there is no leftover amount, nothing left to pay.\n if (_leftoverAmount == 0) return;\n\n // If there's a default project ID, try to pay it.\n if (defaultProjectId != 0)\n if (defaultPreferAddToBalance)\n // Pay the project by adding to its balance if prefered.\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n _leftoverAmount,\n 18, // decimals.\n defaultMemo,\n defaultMetadata\n );\n // Otherwise, issue a payment to the project.\n else\n _pay(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n _leftoverAmount,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n 0, // min returned tokens.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n // If no project was specified, send the funds directly to the beneficiary or the msg.sender.\n else\n Address.sendValue(\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(msg.sender),\n _leftoverAmount\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the location of the splits that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n */\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) external virtual override onlyOwner {\n // Set the default splits project ID if it's changing.\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\n\n // Set the default splits domain if it's changing.\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\n\n // Set the default splits group if it's changing.\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\n\n emit SetDefaultSplits(_projectId, _domain, _group, msg.sender);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender\n );\n\n // Pay any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to pay it.\n if (_projectId != 0) {\n _pay(\n _projectId,\n _token,\n _leftoverAmount,\n _decimals,\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n // If no project was specified, send the funds directly to the beneficiary or the msg.sender.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _beneficiary != address(0) ? payable(_beneficiary) : payable(msg.sender),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).transfer(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _leftoverAmount\n );\n }\n }\n\n emit Pay(\n _projectId,\n _beneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event. \n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender\n );\n\n // Distribute any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to add to its balance.\n if (_projectId != 0)\n // Add to the project's balance.\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\n\n // Otherwise, send a payment to the beneficiary.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(msg.sender),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).transfer(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _leftoverAmount\n );\n }\n }\n\n emit AddToBalance(\n _projectId,\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splitsProjectId The ID of the project to which the splits belong.\n @param _splitsDomain The splits domain to which the group belongs.\n @param _splitsGroup The splits group to pay.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payToSplits(\n uint256 _splitsProjectId,\n uint256 _splitsDomain,\n uint256 _splitsGroup,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Get a reference to the splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup);\n\n // Set the leftover amount to the initial balance.\n leftoverAmount = _amount;\n\n // Settle between all splits.\n for (uint256 i = 0; i < _splits.length; i++) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[i];\n\n // The amount to send towards the split.\n uint256 _splitAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n if (_splitAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n _token,\n _splitAmount,\n _decimals,\n defaultProjectId,\n 0,\n _split\n );\n\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN)\n IERC20(_token).approve(address(_split.allocator), _splitAmount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _splitAmount : 0;\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n if (_split.preferAddToBalance)\n _addToBalanceOf(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n 0,\n _split.preferClaimed,\n defaultMemo,\n defaultMetadata\n );\n } else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _split.beneficiary != address(0) ? _split.beneficiary : payable(_defaultBeneficiary),\n _splitAmount\n );\n // Or, transfer the ERC20.\n else {\n IERC20(_token).transfer(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n _splitAmount\n );\n }\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _splitAmount;\n }\n\n emit DistributeToSplit(\n _splitsProjectId,\n _splitsDomain,\n _splitsGroup,\n _split,\n _splitAmount,\n msg.sender\n );\n }\n }\n}\n" }, "contracts/interfaces/IJBSplitsPayer/2.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './../../structs/JBSplit.sol';\nimport './../IJBSplitsStore/2.sol';\n\ninterface IJBSplitsPayer is IERC165 {\n event SetDefaultSplits(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n address caller\n );\n event Pay(\n uint256 indexed projectId,\n address beneficiary,\n address token,\n uint256 amount,\n uint256 decimals,\n uint256 leftoverAmount,\n uint256 minReturnedTokens,\n bool preferClaimedTokens,\n string memo,\n bytes metadata,\n address caller\n );\n\n event AddToBalance(\n uint256 indexed projectId,\n address beneficiary,\n address token,\n uint256 amount,\n uint256 decimals,\n uint256 leftoverAmount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DistributeToSplit(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n JBSplit split,\n uint256 amount,\n address caller\n );\n\n function defaultSplitsProjectId() external view returns (uint256);\n\n function defaultSplitsDomain() external view returns (uint256);\n\n function defaultSplitsGroup() external view returns (uint256);\n\n function splitsStore() external view returns (IJBSplitsStore);\n\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) external;\n}\n" }, "contracts/system_tests/TestEIP165_2.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './helpers/TestBaseWorkflow_2.sol';\nimport '../JBReconfigurationBufferBallot.sol';\nimport '../JBETHERC20SplitsPayer/2.sol';\n\ncontract TestEIP165 is TestBaseWorkflow_2 {\n bytes4 constant notSupportedInterface = 0xffffffff;\n\n uint256 constant projectId = 2;\n uint256 constant splitsProjectID = 3;\n address payable constant splitsBeneficiary = payable(address(420));\n uint256 constant splitsDomain = 1;\n uint256 constant splitsGroup = 1;\n bool constant splitsPreferClaimedTokens = false;\n string constant splitsMemo = '';\n bytes constant splitsMetadata = '';\n bool constant splitsPreferAddToBalance = true;\n address constant splitsOwner = address(420);\n\n function testJBController() public {\n JBController controller = jbController();\n\n // Should support these interfaces\n assertTrue(controller.supportsInterface(type(IERC165).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBController).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBMigratable).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!controller.supportsInterface(notSupportedInterface));\n }\n\n function testJBERC20PaymentTerminal() public {\n JBERC20PaymentTerminal terminal = new JBERC20PaymentTerminal(\n jbToken(),\n jbLibraries().USD(), // currency\n jbLibraries().ETH(), // base weight currency\n 1, // JBSplitsGroupe\n jbOperatorStore(),\n jbProjects(),\n jbDirectory(),\n jbSplitsStore(),\n jbPrices(),\n jbPaymentTerminalStore(),\n multisig()\n );\n\n // Should support these interfaces\n assertTrue(terminal.supportsInterface(type(IERC165).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBRedemptionTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBSingleTokenPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!terminal.supportsInterface(notSupportedInterface));\n }\n\n function testJBETHPaymentTerminal() public {\n JBETHPaymentTerminal terminal = jbETHPaymentTerminal();\n\n // Should support these interfaces\n assertTrue(terminal.supportsInterface(type(IERC165).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBRedemptionTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBSingleTokenPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!terminal.supportsInterface(notSupportedInterface));\n }\n\n function testJBProjects() public {\n JBProjects projects = jbProjects();\n\n // Should support these interfaces\n assertTrue(projects.supportsInterface(type(IERC165).interfaceId));\n assertTrue(projects.supportsInterface(type(IERC721).interfaceId));\n assertTrue(projects.supportsInterface(type(IERC721Metadata).interfaceId));\n assertTrue(projects.supportsInterface(type(IJBProjects).interfaceId));\n assertTrue(projects.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!projects.supportsInterface(notSupportedInterface));\n }\n\n function testJBReconfigurationBufferBallot() public {\n JBReconfigurationBufferBallot ballot = new JBReconfigurationBufferBallot(\n 3000,\n jbFundingCycleStore()\n );\n\n // Should support these interfaces\n assertTrue(ballot.supportsInterface(type(IERC165).interfaceId));\n assertTrue(ballot.supportsInterface(type(IJBReconfigurationBufferBallot).interfaceId));\n assertTrue(ballot.supportsInterface(type(IJBFundingCycleBallot).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!ballot.supportsInterface(notSupportedInterface));\n }\n\n function testJBETHERC20SplitsPayer() public {\n JBETHERC20SplitsPayer splitsPayer = new JBETHERC20SplitsPayer(\n splitsProjectID,\n splitsDomain,\n splitsGroup,\n jbSplitsStore(),\n projectId,\n splitsBeneficiary,\n splitsPreferClaimedTokens,\n splitsMemo,\n splitsMetadata,\n splitsPreferAddToBalance,\n splitsOwner\n );\n\n // Should support these interfaces\n assertTrue(splitsPayer.supportsInterface(type(IERC165).interfaceId));\n assertTrue(splitsPayer.supportsInterface(type(IJBSplitsPayer).interfaceId));\n assertTrue(splitsPayer.supportsInterface(type(IJBProjectPayer).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!splitsPayer.supportsInterface(notSupportedInterface));\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './helpers/TestBaseWorkflow_2.sol';\nimport '../JBReconfigurationBufferBallot.sol';\nimport '../JBGasTokenERC20SplitsPayer/2.sol';\n\ncontract TestEIP165 is TestBaseWorkflow_2 {\n bytes4 constant notSupportedInterface = 0xffffffff;\n\n uint256 constant projectId = 2;\n uint256 constant splitsProjectID = 3;\n address payable constant splitsBeneficiary = payable(address(420));\n uint256 constant splitsDomain = 1;\n uint256 constant splitsGroup = 1;\n bool constant splitsPreferClaimedTokens = false;\n string constant splitsMemo = '';\n bytes constant splitsMetadata = '';\n bool constant splitsPreferAddToBalance = true;\n address constant splitsOwner = address(420);\n\n function testJBController() public {\n JBController controller = jbController();\n\n // Should support these interfaces\n assertTrue(controller.supportsInterface(type(IERC165).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBController).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBMigratable).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!controller.supportsInterface(notSupportedInterface));\n }\n\n function testJBERC20PaymentTerminal() public {\n JBERC20PaymentTerminal terminal = new JBERC20PaymentTerminal(\n jbToken(),\n jbLibraries().USD(), // currency\n jbLibraries().ETH(), // base weight currency\n 1, // JBSplitsGroupe\n jbOperatorStore(),\n jbProjects(),\n jbDirectory(),\n jbSplitsStore(),\n jbPrices(),\n jbPaymentTerminalStore(),\n multisig()\n );\n\n // Should support these interfaces\n assertTrue(terminal.supportsInterface(type(IERC165).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBRedemptionTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBSingleTokenPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!terminal.supportsInterface(notSupportedInterface));\n }\n\n function testJBETHPaymentTerminal() public {\n JBETHPaymentTerminal terminal = jbETHPaymentTerminal();\n\n // Should support these interfaces\n assertTrue(terminal.supportsInterface(type(IERC165).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBRedemptionTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBSingleTokenPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!terminal.supportsInterface(notSupportedInterface));\n }\n\n function testJBProjects() public {\n JBProjects projects = jbProjects();\n\n // Should support these interfaces\n assertTrue(projects.supportsInterface(type(IERC165).interfaceId));\n assertTrue(projects.supportsInterface(type(IERC721).interfaceId));\n assertTrue(projects.supportsInterface(type(IERC721Metadata).interfaceId));\n assertTrue(projects.supportsInterface(type(IJBProjects).interfaceId));\n assertTrue(projects.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!projects.supportsInterface(notSupportedInterface));\n }\n\n function testJBReconfigurationBufferBallot() public {\n JBReconfigurationBufferBallot ballot = new JBReconfigurationBufferBallot(\n 3000,\n jbFundingCycleStore()\n );\n\n // Should support these interfaces\n assertTrue(ballot.supportsInterface(type(IERC165).interfaceId));\n assertTrue(ballot.supportsInterface(type(IJBReconfigurationBufferBallot).interfaceId));\n assertTrue(ballot.supportsInterface(type(IJBFundingCycleBallot).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!ballot.supportsInterface(notSupportedInterface));\n }\n\n function testJBGasTokenERC20SplitsPayer() public {\n JBGasTokenERC20SplitsPayer splitsPayer = new JBGasTokenERC20SplitsPayer(\n splitsProjectID,\n splitsDomain,\n splitsGroup,\n jbSplitsStore(),\n projectId,\n splitsBeneficiary,\n splitsPreferClaimedTokens,\n splitsMemo,\n splitsMetadata,\n splitsPreferAddToBalance,\n splitsOwner\n );\n\n // Should support these interfaces\n assertTrue(splitsPayer.supportsInterface(type(IERC165).interfaceId));\n assertTrue(splitsPayer.supportsInterface(type(IJBSplitsPayer).interfaceId));\n assertTrue(splitsPayer.supportsInterface(type(IJBProjectPayer).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!splitsPayer.supportsInterface(notSupportedInterface));\n }\n}\n" }, - "contracts/JBETHERC20SplitsPayerDeployer/2.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './../interfaces/IJBETHERC20SplitsPayerDeployer/2.sol';\nimport './../JBETHERC20SplitsPayer/2.sol';\n\n/** \n @notice \n Deploys splits payer contracts.\n\n @dev\n Adheres to -\n IJBETHERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBETHERC20SplitsPayerDeployer is IJBETHERC20SplitsPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBSplitsPayer splitsPayer) {\n // Deploy the splits payer.\n splitsPayer = new JBETHERC20SplitsPayer(\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeploySplitsPayer(\n splitsPayer,\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner,\n msg.sender\n );\n }\n}\n" + "contracts/JBGasTokenERC20SplitsPayerDeployer/2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './../interfaces/IJBGasTokenERC20SplitsPayerDeployer/2.sol';\nimport './../JBGasTokenERC20SplitsPayer/2.sol';\n\n/** \n @notice \n Deploys splits payer contracts.\n\n @dev\n Adheres to -\n IJBGasTokenERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBGasTokenERC20SplitsPayerDeployer is IJBGasTokenERC20SplitsPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBSplitsPayer splitsPayer) {\n // Deploy the splits payer.\n splitsPayer = new JBGasTokenERC20SplitsPayer(\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeploySplitsPayer(\n splitsPayer,\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner,\n msg.sender\n );\n }\n}\n" }, - "contracts/interfaces/IJBETHERC20SplitsPayerDeployer/2.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './../IJBSplitsPayer/2.sol';\nimport './../IJBSplitsStore/2.sol';\n\ninterface IJBETHERC20SplitsPayerDeployer {\n event DeploySplitsPayer(\n IJBSplitsPayer indexed splitsPayer,\n uint256 defaultSplitsProjectId,\n uint256 defaultSplitsDomain,\n uint256 defaultSplitsGroup,\n IJBSplitsStore splitsStore,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n address owner,\n address caller\n );\n\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string calldata _defaultMemo,\n bytes calldata _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n}\n" + "contracts/interfaces/IJBGasTokenERC20SplitsPayerDeployer/2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './../IJBSplitsPayer/2.sol';\nimport './../IJBSplitsStore/2.sol';\n\ninterface IJBGasTokenERC20SplitsPayerDeployer {\n event DeploySplitsPayer(\n IJBSplitsPayer indexed splitsPayer,\n uint256 defaultSplitsProjectId,\n uint256 defaultSplitsDomain,\n uint256 defaultSplitsGroup,\n IJBSplitsStore splitsStore,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n address owner,\n address caller\n );\n\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string calldata _defaultMemo,\n bytes calldata _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n}\n" }, "contracts/interfaces/IJBTerminalUtility.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './IJBDirectory.sol';\n\ninterface IJBPaymentTerminalUtility {\n function directory() external view returns (IJBDirectory);\n}\n" }, - "contracts/interfaces/IJBETHERC20ProjectPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './IJBDirectory.sol';\nimport './IJBProjectPayer.sol';\n\ninterface IJBETHERC20ProjectPayerDeployer {\n event DeployProjectPayer(\n IJBProjectPayer indexed projectPayer,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n IJBDirectory directory,\n address owner,\n address caller\n );\n\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external returns (IJBProjectPayer projectPayer);\n}\n" + "contracts/interfaces/IJBGasTokenERC20ProjectPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './IJBDirectory.sol';\nimport './IJBProjectPayer.sol';\n\ninterface IJBGasTokenERC20ProjectPayerDeployer {\n event DeployProjectPayer(\n IJBProjectPayer indexed projectPayer,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n IJBDirectory directory,\n address owner,\n address caller\n );\n\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external returns (IJBProjectPayer projectPayer);\n}\n" }, - "contracts/JBETHERC20ProjectPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './interfaces/IJBETHERC20ProjectPayerDeployer.sol';\nimport './JBETHERC20ProjectPayer.sol';\n\n/** \n @notice \n Deploys project payer contracts.\n\n @dev\n Adheres to -\n IJBETHERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBETHERC20ProjectPayerDeployer is IJBETHERC20ProjectPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new project payer contract.\n\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the project payer contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the project payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the project payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the project payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the project payer.\n\n @return projectPayer The project payer contract.\n */\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external override returns (IJBProjectPayer projectPayer) {\n // Deploy the project payer.\n projectPayer = new JBETHERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner\n );\n\n emit DeployProjectPayer(\n projectPayer,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner,\n msg.sender\n );\n }\n}\n" + "contracts/JBGasTokenERC20ProjectPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './interfaces/IJBGasTokenERC20ProjectPayerDeployer.sol';\nimport './JBGasTokenERC20ProjectPayer.sol';\n\n/** \n @notice \n Deploys project payer contracts.\n\n @dev\n Adheres to -\n IJBGasTokenERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBGasTokenERC20ProjectPayerDeployer is IJBGasTokenERC20ProjectPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new project payer contract.\n\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the project payer contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the project payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the project payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the project payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the project payer.\n\n @return projectPayer The project payer contract.\n */\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external override returns (IJBProjectPayer projectPayer) {\n // Deploy the project payer.\n projectPayer = new JBGasTokenERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner\n );\n\n emit DeployProjectPayer(\n projectPayer,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner,\n msg.sender\n );\n }\n}\n" }, "contracts/system_tests/TestLaunchProject.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './helpers/TestBaseWorkflow.sol';\n\ncontract TestLaunchProject is TestBaseWorkflow {\n JBController controller;\n JBProjectMetadata _projectMetadata;\n JBFundingCycleData _data;\n JBFundingCycleMetadata _metadata;\n JBGroupedSplits[] _groupedSplits; // Default empty\n JBFundAccessConstraints[] _fundAccessConstraints; // Default empty\n IJBPaymentTerminal[] _terminals; // Default empty\n\n function setUp() public override {\n super.setUp();\n\n controller = jbController();\n\n _projectMetadata = JBProjectMetadata({content: 'myIPFSHash', domain: 1});\n\n _data = JBFundingCycleData({\n duration: 14,\n weight: 1000 * 10**18,\n discountRate: 450000000,\n ballot: IJBFundingCycleBallot(address(0))\n });\n\n _metadata = JBFundingCycleMetadata({\n global: JBGlobalFundingCycleMetadata({allowSetTerminals: false, allowSetController: false}),\n reservedRate: 5000, //50%\n redemptionRate: 5000, //50%\n ballotRedemptionRate: 0,\n pausePay: false,\n pauseDistributions: false,\n pauseRedeem: false,\n pauseBurn: false,\n allowMinting: false,\n allowChangeToken: false,\n allowTerminalMigration: false,\n allowControllerMigration: false,\n holdFees: false,\n useTotalOverflowForRedemptions: false,\n useDataSourceForPay: false,\n useDataSourceForRedeem: false,\n dataSource: address(0)\n });\n }\n\n function testLaunchProject() public {\n uint256 projectId = controller.launchProjectFor(\n msg.sender,\n _projectMetadata,\n _data,\n _metadata,\n block.timestamp,\n _groupedSplits,\n _fundAccessConstraints,\n _terminals,\n ''\n );\n\n JBFundingCycle memory fundingCycle = jbFundingCycleStore().currentOf(projectId); //, latestConfig);\n\n assertEq(fundingCycle.number, 1);\n assertEq(fundingCycle.weight, 1000 * 10**18);\n }\n\n function testLaunchProjectFuzzWeight(uint256 WEIGHT) public {\n _data = JBFundingCycleData({\n duration: 14,\n weight: WEIGHT,\n discountRate: 450000000,\n ballot: IJBFundingCycleBallot(address(0))\n });\n\n uint256 projectId;\n\n // expectRevert on the next call if weight overflowing\n if (WEIGHT > type(uint88).max) {\n evm.expectRevert(abi.encodeWithSignature('INVALID_WEIGHT()'));\n\n projectId = controller.launchProjectFor(\n msg.sender,\n _projectMetadata,\n _data,\n _metadata,\n block.timestamp,\n _groupedSplits,\n _fundAccessConstraints,\n _terminals,\n ''\n );\n } else {\n projectId = controller.launchProjectFor(\n msg.sender,\n _projectMetadata,\n _data,\n _metadata,\n block.timestamp,\n _groupedSplits,\n _fundAccessConstraints,\n _terminals,\n ''\n );\n\n JBFundingCycle memory fundingCycle = jbFundingCycleStore().currentOf(projectId); //, latestConfig);\n\n assertEq(fundingCycle.number, 1);\n assertEq(fundingCycle.weight, WEIGHT);\n }\n }\n}\n" diff --git a/deployments/mainnet/solcInputs/60cd95dca5edde649565e9f7f43720b6.json b/deployments/mainnet/solcInputs/60cd95dca5edde649565e9f7f43720b6.json index 215c23ded..66f6f66d0 100644 --- a/deployments/mainnet/solcInputs/60cd95dca5edde649565e9f7f43720b6.json +++ b/deployments/mainnet/solcInputs/60cd95dca5edde649565e9f7f43720b6.json @@ -164,7 +164,7 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './../structs/JBFundAccessConstraints.sol';\nimport './../structs/JBFundingCycleData.sol';\nimport './../structs/JBFundingCycleMetadata.sol';\nimport './../structs/JBGroupedSplits.sol';\nimport './../structs/JBProjectMetadata.sol';\nimport './IJBDirectory.sol';\nimport './IJBFundingCycleStore.sol';\nimport './IJBMigratable.sol';\nimport './IJBPaymentTerminal.sol';\nimport './IJBSplitsStore.sol';\nimport './IJBTokenStore.sol';\n\ninterface IJBController is IERC165 {\n event LaunchProject(uint256 configuration, uint256 projectId, string memo, address caller);\n\n event LaunchFundingCycles(uint256 configuration, uint256 projectId, string memo, address caller);\n\n event ReconfigureFundingCycles(\n uint256 configuration,\n uint256 projectId,\n string memo,\n address caller\n );\n\n event SetFundAccessConstraints(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n JBFundAccessConstraints constraints,\n address caller\n );\n\n event DistributeReservedTokens(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address beneficiary,\n uint256 tokenCount,\n uint256 beneficiaryTokenCount,\n string memo,\n address caller\n );\n\n event DistributeToReservedTokenSplit(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n JBSplit split,\n uint256 tokenCount,\n address caller\n );\n\n event MintTokens(\n address indexed beneficiary,\n uint256 indexed projectId,\n uint256 tokenCount,\n uint256 beneficiaryTokenCount,\n string memo,\n uint256 reservedRate,\n address caller\n );\n\n event BurnTokens(\n address indexed holder,\n uint256 indexed projectId,\n uint256 tokenCount,\n string memo,\n address caller\n );\n\n event Migrate(uint256 indexed projectId, IJBMigratable to, address caller);\n\n event PrepMigration(uint256 indexed projectId, address from, address caller);\n\n function projects() external view returns (IJBProjects);\n\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\n\n function tokenStore() external view returns (IJBTokenStore);\n\n function splitsStore() external view returns (IJBSplitsStore);\n\n function directory() external view returns (IJBDirectory);\n\n function reservedTokenBalanceOf(uint256 _projectId, uint256 _reservedRate)\n external\n view\n returns (uint256);\n\n function distributionLimitOf(\n uint256 _projectId,\n uint256 _configuration,\n IJBPaymentTerminal _terminal,\n address _token\n ) external view returns (uint256 distributionLimit, uint256 distributionLimitCurrency);\n\n function overflowAllowanceOf(\n uint256 _projectId,\n uint256 _configuration,\n IJBPaymentTerminal _terminal,\n address _token\n ) external view returns (uint256 overflowAllowance, uint256 overflowAllowanceCurrency);\n\n function totalOutstandingTokensOf(uint256 _projectId, uint256 _reservedRate)\n external\n view\n returns (uint256);\n\n function getFundingCycleOf(uint256 _projectId, uint256 _configuration)\n external\n view\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\n\n function latestConfiguredFundingCycleOf(uint256 _projectId)\n external\n view\n returns (\n JBFundingCycle memory,\n JBFundingCycleMetadata memory metadata,\n JBBallotState\n );\n\n function currentFundingCycleOf(uint256 _projectId)\n external\n view\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\n\n function queuedFundingCycleOf(uint256 _projectId)\n external\n view\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\n\n function launchProjectFor(\n address _owner,\n JBProjectMetadata calldata _projectMetadata,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] memory _groupedSplits,\n JBFundAccessConstraints[] memory _fundAccessConstraints,\n IJBPaymentTerminal[] memory _terminals,\n string calldata _memo\n ) external returns (uint256 projectId);\n\n function launchFundingCyclesFor(\n uint256 _projectId,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] memory _groupedSplits,\n JBFundAccessConstraints[] memory _fundAccessConstraints,\n IJBPaymentTerminal[] memory _terminals,\n string calldata _memo\n ) external returns (uint256 configuration);\n\n function reconfigureFundingCyclesOf(\n uint256 _projectId,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] memory _groupedSplits,\n JBFundAccessConstraints[] memory _fundAccessConstraints,\n string calldata _memo\n ) external returns (uint256);\n\n function mintTokensOf(\n uint256 _projectId,\n uint256 _tokenCount,\n address _beneficiary,\n string calldata _memo,\n bool _preferClaimedTokens,\n bool _useReservedRate\n ) external returns (uint256 beneficiaryTokenCount);\n\n function burnTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string calldata _memo,\n bool _preferClaimedTokens\n ) external;\n\n function distributeReservedTokensOf(uint256 _projectId, string memory _memo)\n external\n returns (uint256);\n\n function migrate(uint256 _projectId, IJBMigratable _to) external;\n}\n" }, "contracts/JBSingleTokenPaymentTerminalStore3_1.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController3_1.sol';\nimport './interfaces/IJBFundingCycleDataSource.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './structs/JBPayDelegateAllocation.sol';\nimport './structs/JBPayParamsData.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n\n @dev\n This Store expects a project's controller to be an IJBController3_1. This is the only difference between this version and the original.\n*/\ncontract JBSingleTokenPaymentTerminalStore3_1 is\n ReentrancyGuard,\n IJBSingleTokenPaymentTerminalStore\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId);\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n JBPayDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .payParams(_data);\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\n {\n // Keep a reference to the amount that should be added to the project's balance.\n uint256 _balanceDiff = _amount.value;\n\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\n if (delegateAllocations.length != 0) {\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0) {\n // Can't delegate more than was paid.\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\n\n // Decrement the total amount being added to the balance.\n _balanceDiff = _balanceDiff - _delegatedAmount;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Add the correct balance difference to the token balance of the project.\n if (_balanceDiff != 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _balanceDiff;\n }\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId);\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow != 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\n {\n // Get a reference to the ballot state.\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\n\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n _state == JBBallotState.Active\n ? fundingCycle.ballotRedemptionRate()\n : fundingCycle.redemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\n fundingCycle.dataSource()\n ).redeemParams(_data);\n }\n } else {\n memo = _memo;\n }\n }\n\n // Keep a reference to the amount that should be subtracted from the project's balance.\n uint256 _balanceDiff = reclaimAmount;\n\n if (delegateAllocations.length != 0) {\n // Validate all delegated amounts.\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0)\n // Increment the total amount being subtracted from the balance.\n _balanceDiff = _balanceDiff + _delegatedAmount;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (_balanceDiff != 0) {\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n _balanceDiff;\n }\n }\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).fundAccessConstraintsStore().distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).fundAccessConstraintsStore().overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).fundAccessConstraintsStore().distributionLimitOf(\n _projectId,\n _fundingCycle.configuration,\n _terminal,\n _terminal.token()\n );\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n unchecked {\n return\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i; _i < _terminals.length; ) {\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n unchecked {\n ++_i;\n }\n }\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.ETH\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.ETH, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController3_1.sol';\nimport './interfaces/IJBFundingCycleDataSource.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './structs/JBPayDelegateAllocation.sol';\nimport './structs/JBPayParamsData.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n\n @dev\n This Store expects a project's controller to be an IJBController3_1. This is the only difference between this version and the original.\n*/\ncontract JBSingleTokenPaymentTerminalStore3_1 is\n ReentrancyGuard,\n IJBSingleTokenPaymentTerminalStore\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId);\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n JBPayDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .payParams(_data);\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\n {\n // Keep a reference to the amount that should be added to the project's balance.\n uint256 _balanceDiff = _amount.value;\n\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\n if (delegateAllocations.length != 0) {\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0) {\n // Can't delegate more than was paid.\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\n\n // Decrement the total amount being added to the balance.\n _balanceDiff = _balanceDiff - _delegatedAmount;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Add the correct balance difference to the token balance of the project.\n if (_balanceDiff != 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _balanceDiff;\n }\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId);\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow != 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\n {\n // Get a reference to the ballot state.\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\n\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n _state == JBBallotState.Active\n ? fundingCycle.ballotRedemptionRate()\n : fundingCycle.redemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\n fundingCycle.dataSource()\n ).redeemParams(_data);\n }\n } else {\n memo = _memo;\n }\n }\n\n // Keep a reference to the amount that should be subtracted from the project's balance.\n uint256 _balanceDiff = reclaimAmount;\n\n if (delegateAllocations.length != 0) {\n // Validate all delegated amounts.\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0)\n // Increment the total amount being subtracted from the balance.\n _balanceDiff = _balanceDiff + _delegatedAmount;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (_balanceDiff != 0) {\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n _balanceDiff;\n }\n }\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).fundAccessConstraintsStore().distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).fundAccessConstraintsStore().overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).fundAccessConstraintsStore().distributionLimitOf(\n _projectId,\n _fundingCycle.configuration,\n _terminal,\n _terminal.token()\n );\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n unchecked {\n return\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i; _i < _terminals.length; ) {\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n unchecked {\n ++_i;\n }\n }\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.GAS_CURRENCY\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.GAS_CURRENCY, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" }, "@openzeppelin/contracts/security/ReentrancyGuard.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n constructor() {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n // On the first call to nonReentrant, _notEntered will be true\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n\n _;\n\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n}\n" @@ -224,7 +224,7 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IJBPriceFeed {\n function currentPrice(uint256 _targetDecimals) external view returns (uint256);\n}\n" }, "contracts/JBSingleTokenPaymentTerminalStore.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController.sol';\nimport './interfaces/IJBFundingCycleDataSource.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './structs/JBPayDelegateAllocation.sol';\nimport './structs/JBPayParamsData.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBSingleTokenPaymentTerminalStore is ReentrancyGuard, IJBSingleTokenPaymentTerminalStore {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n JBPayDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .payParams(_data);\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\n {\n // Keep a reference to the amount that should be added to the project's balance.\n uint256 _balanceDiff = _amount.value;\n\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\n if (delegateAllocations.length != 0) {\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0) {\n // Can't delegate more than was paid.\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\n\n // Decrement the total amount being added to the balance.\n _balanceDiff = _balanceDiff - _delegatedAmount;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Add the correct balance difference to the token balance of the project.\n if (_balanceDiff != 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _balanceDiff;\n }\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\n _projectId,\n fundingCycle.reservedRate()\n );\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow != 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\n {\n // Get a reference to the ballot state.\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\n\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n _state == JBBallotState.Active\n ? fundingCycle.ballotRedemptionRate()\n : fundingCycle.redemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\n fundingCycle.dataSource()\n ).redeemParams(_data);\n }\n } else {\n memo = _memo;\n }\n }\n\n // Keep a reference to the amount that should be subtracted from the project's balance.\n uint256 _balanceDiff = reclaimAmount;\n\n if (delegateAllocations.length != 0) {\n // Validate all delegated amounts.\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0)\n // Increment the total amount being subtracted from the balance.\n _balanceDiff = _balanceDiff + _delegatedAmount;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (_balanceDiff != 0) {\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n _balanceDiff;\n }\n }\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n unchecked {\n return\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i; _i < _terminals.length; ) {\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n unchecked {\n ++_i;\n }\n }\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.ETH\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.ETH, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController.sol';\nimport './interfaces/IJBFundingCycleDataSource.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './structs/JBPayDelegateAllocation.sol';\nimport './structs/JBPayParamsData.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBSingleTokenPaymentTerminalStore is ReentrancyGuard, IJBSingleTokenPaymentTerminalStore {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n JBPayDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .payParams(_data);\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\n {\n // Keep a reference to the amount that should be added to the project's balance.\n uint256 _balanceDiff = _amount.value;\n\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\n if (delegateAllocations.length != 0) {\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0) {\n // Can't delegate more than was paid.\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\n\n // Decrement the total amount being added to the balance.\n _balanceDiff = _balanceDiff - _delegatedAmount;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Add the correct balance difference to the token balance of the project.\n if (_balanceDiff != 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _balanceDiff;\n }\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\n _projectId,\n fundingCycle.reservedRate()\n );\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow != 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\n {\n // Get a reference to the ballot state.\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\n\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n _state == JBBallotState.Active\n ? fundingCycle.ballotRedemptionRate()\n : fundingCycle.redemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\n fundingCycle.dataSource()\n ).redeemParams(_data);\n }\n } else {\n memo = _memo;\n }\n }\n\n // Keep a reference to the amount that should be subtracted from the project's balance.\n uint256 _balanceDiff = reclaimAmount;\n\n if (delegateAllocations.length != 0) {\n // Validate all delegated amounts.\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0)\n // Increment the total amount being subtracted from the balance.\n _balanceDiff = _balanceDiff + _delegatedAmount;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (_balanceDiff != 0) {\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n _balanceDiff;\n }\n }\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n unchecked {\n return\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i; _i < _terminals.length; ) {\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n unchecked {\n ++_i;\n }\n }\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.GAS_CURRENCY\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.GAS_CURRENCY, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" }, "contracts/interfaces/IJBPayoutRedemptionPaymentTerminal3_1.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './../structs/JBFee.sol';\nimport './IJBAllowanceTerminal3_1.sol';\nimport './IJBDirectory.sol';\nimport './IJBFeeGauge.sol';\nimport './IJBFeeHoldingTerminal.sol';\nimport './IJBPayDelegate.sol';\nimport './IJBPaymentTerminal.sol';\nimport './IJBPayoutTerminal3_1.sol';\nimport './IJBPrices.sol';\nimport './IJBProjects.sol';\nimport './IJBRedemptionDelegate.sol';\nimport './IJBRedemptionTerminal.sol';\nimport './IJBSingleTokenPaymentTerminalStore.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBPayoutRedemptionPaymentTerminal3_1 is\n IJBPaymentTerminal,\n IJBPayoutTerminal3_1,\n IJBAllowanceTerminal3_1,\n IJBRedemptionTerminal,\n IJBFeeHoldingTerminal\n{\n event AddToBalance(\n uint256 indexed projectId,\n uint256 amount,\n uint256 refundedFees,\n string memo,\n bytes metadata,\n address caller\n );\n\n event Migrate(\n uint256 indexed projectId,\n IJBPaymentTerminal indexed to,\n uint256 amount,\n address caller\n );\n\n event DistributePayouts(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address beneficiary,\n uint256 amount,\n uint256 distributedAmount,\n uint256 fee,\n uint256 beneficiaryDistributionAmount,\n bytes metadata,\n address caller\n );\n\n event UseAllowance(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address beneficiary,\n uint256 amount,\n uint256 distributedAmount,\n uint256 netDistributedamount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event HoldFee(\n uint256 indexed projectId,\n uint256 indexed amount,\n uint256 indexed fee,\n uint256 feeDiscount,\n address beneficiary,\n address caller\n );\n\n event ProcessFee(\n uint256 indexed projectId,\n uint256 indexed amount,\n bool indexed wasHeld,\n address beneficiary,\n address caller\n );\n\n event RefundHeldFees(\n uint256 indexed projectId,\n uint256 indexed amount,\n uint256 indexed refundedFees,\n uint256 leftoverAmount,\n address caller\n );\n\n event Pay(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address payer,\n address beneficiary,\n uint256 amount,\n uint256 beneficiaryTokenCount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DelegateDidPay(\n IJBPayDelegate indexed delegate,\n JBDidPayData data,\n uint256 delegatedAmount,\n address caller\n );\n\n event RedeemTokens(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address holder,\n address beneficiary,\n uint256 tokenCount,\n uint256 reclaimedAmount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DelegateDidRedeem(\n IJBRedemptionDelegate indexed delegate,\n JBDidRedeemData data,\n uint256 delegatedAmount,\n address caller\n );\n\n event DistributeToPayoutSplit(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n JBSplit split,\n uint256 amount,\n uint256 netAmount,\n address caller\n );\n\n event SetFee(uint256 fee, address caller);\n\n event SetFeeGauge(IJBFeeGauge indexed feeGauge, address caller);\n\n event SetFeelessAddress(address indexed addrs, bool indexed flag, address caller);\n\n event PayoutReverted(uint256 indexed projectId, JBSplit split, uint256 amount, bytes reason, address caller);\n\n event FeeReverted(\n uint256 indexed projectId,\n uint256 indexed feeProjectId,\n uint256 amount,\n bytes reason,\n address caller\n );\n\n function projects() external view returns (IJBProjects);\n\n function splitsStore() external view returns (IJBSplitsStore);\n\n function directory() external view returns (IJBDirectory);\n\n function prices() external view returns (IJBPrices);\n\n function store() external view returns (IJBSingleTokenPaymentTerminalStore);\n\n function baseWeightCurrency() external view returns (uint256);\n\n function payoutSplitsGroup() external view returns (uint256);\n\n function heldFeesOf(uint256 _projectId) external view returns (JBFee[] memory);\n\n function fee() external view returns (uint256);\n\n function feeGauge() external view returns (IJBFeeGauge);\n\n function isFeelessAddress(address _contract) external view returns (bool);\n\n function migrate(uint256 _projectId, IJBPaymentTerminal _to) external returns (uint256 balance);\n\n function processFees(uint256 _projectId) external;\n\n function setFee(uint256 _fee) external;\n\n function setFeeGauge(IJBFeeGauge _feeGauge) external;\n\n function setFeelessAddress(address _contract, bool _flag) external;\n}\n" @@ -284,10 +284,10 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nlibrary JBSplitsGroups {\n uint256 public constant ETH_PAYOUT = 1;\n uint256 public constant RESERVED_TOKENS = 2;\n}\n" }, "contracts/JBETHPaymentTerminal3_1.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal3_1.sol';\nimport './libraries/JBSplitsGroups.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal3_1: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal3_1 is JBPayoutRedemptionPaymentTerminal3_1 {\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return address(this).balance;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal3_1(\n JBTokens.ETH,\n 18, // 18 decimals.\n JBCurrencies.ETH,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal3_1.sol';\nimport './libraries/JBSplitsGroups.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal3_1: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal3_1 is JBPayoutRedemptionPaymentTerminal3_1 {\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return address(this).balance;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal3_1(\n JBTokens.GAS_TOKEN,\n 18, // 18 decimals.\n JBCurrencies.GAS_CURRENCY,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n}\n" }, "contracts/abstract/JBPayoutRedemptionPaymentTerminal3_1.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/utils/introspection/ERC165Checker.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal3_1.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBPayDelegateAllocation.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal3_1: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal3_1 is\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n IJBPayoutRedemptionPaymentTerminal3_1\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n @dev\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.ETH)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.ETH, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal3_1).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal3_1).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal3_1).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance.\n */\n function _balance() internal view virtual returns (uint256);\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n bytes calldata _metadata\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _metadata);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes calldata _metadata\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _useAllowanceOf(\n _projectId,\n _amount,\n _currency,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n // Do not refund held fees by default.\n addToBalanceOf(_projectId, _amount, _token, false, _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary, _projectId);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n bool _shouldRefundHeldFees,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.ETH) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance.\n _addToBalanceOf(_projectId, _amount, _shouldRefundHeldFees, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual {\n _from; // Prevents unused var compiler and natspec complaints.\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered if a transfer should be undone\n\n @param _to The address to which the transfer went.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _cancelTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\n {\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\n\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _forwardedAmount,\n _beneficiary,\n _memo,\n _metadata\n );\n\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\n\n emit DelegateDidRedeem(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n bytes calldata _metadata\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n }\n\n // Take the fee.\n _fee = _feeEligibleDistributionAmount != 0\n ? _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n )\n : 0;\n\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\n if (_leftoverDistributionAmount != 0) {\n // Subtract the fee from the net leftover amount.\n netLeftoverDistributionAmount =\n _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n\n // Transfer the amount to the project owner.\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes calldata _metadata\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n // The total percentage available to split\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = _split.percent == leftoverPercentage\n ? leftoverAmount\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\n\n // Decrement the leftover percentage.\n leftoverPercentage -= _split.percent;\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount = _distributeToPayoutSplit(\n _split,\n _projectId,\n _group,\n _payoutAmount,\n _feeDiscount\n );\n\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (_netPayoutAmount != 0 && _netPayoutAmount != _payoutAmount)\n feeEligibleDistributionAmount += _payoutAmount;\n\n if (_payoutAmount > 0) {\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _payoutAmount,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Pays out a split for a project's funding cycle configuration.\n \n @param _split The split to distribute payouts to.\n @param _amount The total amount being distributed to the split, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return netPayoutAmount The amount sent to the split after subtracting fees.\n */\n function _distributeToPayoutSplit(\n JBSplit memory _split,\n uint256 _projectId,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 netPayoutAmount) {\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_split.allocator)]\n )\n netPayoutAmount = _amount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\n }\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), netPayoutAmount);\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n uint256 _error;\n bytes memory _reason;\n\n if (\n ERC165Checker.supportsInterface(\n address(_split.allocator),\n type(IJBSplitAllocator).interfaceId\n )\n )\n // If this terminal's token is ETH, send it in msg.value.\n try _split.allocator.allocate{value: token == JBTokens.ETH ? netPayoutAmount : 0}(_data) {\n\n } catch (bytes memory reason) {\n _reason = reason;\n _error = 1;\n }\n else _error = 2;\n\n\n if (_error != 0) {\n // Trigger any inhereted post-transfer cancelation logic.\n _cancelTransferTo(address(_split.allocator), netPayoutAmount);\n\n // Set the net payout amount to 0 to signal the reversion.\n netPayoutAmount = 0;\n\n // Add undistributed amount back to project's balance.\n store.recordAddedBalanceFor(_projectId, _amount);\n\n emit PayoutReverted(_projectId, _split, _amount, _error == 1 ? _reason : abi.encode(\"IERC165 fail\"), msg.sender);\n }\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (\n _terminal == this ||\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\n isFeelessAddress[address(_terminal)]\n )\n netPayoutAmount = _amount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\n }\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), netPayoutAmount);\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n try\n _terminal.addToBalanceOf{value: token == JBTokens.ETH ? netPayoutAmount : 0}(\n _split.projectId,\n netPayoutAmount,\n token,\n '',\n _projectMetadata\n )\n {} catch (bytes memory reason) {\n // Trigger any inhereted post-transfer cancelation logic.\n _cancelTransferTo(address(_terminal), netPayoutAmount);\n\n // Set the net payout amount to 0 to signal the reversion.\n netPayoutAmount = 0;\n\n // Add undistributed amount back to project's balance.\n store.recordAddedBalanceFor(_projectId, _amount);\n\n emit PayoutReverted(_projectId, _split, _amount, reason, msg.sender);\n }\n else\n try\n _terminal.pay{value: token == JBTokens.ETH ? netPayoutAmount : 0}(\n _split.projectId,\n netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n )\n {} catch (bytes memory reason) {\n // Trigger any inhereted post-transfer cancelation logic.\n _cancelTransferTo(address(_terminal), netPayoutAmount);\n\n // Set the net payout amount to 0 to signal the reversion.\n netPayoutAmount = 0;\n\n // Add undistributed amount back to project's balance.\n store.recordAddedBalanceFor(_projectId, _amount);\n\n emit PayoutReverted(_projectId, _split, _amount, reason, msg.sender);\n }\n } else {\n // Keep a reference to the beneficiary.\n address payable _beneficiary = _split.beneficiary != address(0)\n ? _split.beneficiary\n : payable(msg.sender);\n\n // If there's a full discount, this distribution is not eligible for a fee.\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\n netPayoutAmount = _amount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\n else {\n unchecked {\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\n }\n }\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(address(this), _beneficiary, netPayoutAmount);\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary, _projectId); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n @param _from The project ID the fee is being paid from.\n */\n function _processFee(\n uint256 _amount,\n address _beneficiary,\n uint256 _from\n ) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _amount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_from));\n\n // Trigger any inherited pre-transfer logic if funds will be transferred.\n if (address(_terminal) != address(this)) _beforeTransferTo(address(_terminal), _amount);\n\n try\n // Send the fee.\n _terminal.pay{value: _payableValue}(\n _FEE_BENEFICIARY_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n _projectMetadata\n )\n {} catch (bytes memory reason) {\n // Trigger any inhereted post-transfer cancelation logic if the pre-transfer logic was triggered.\n if (address(_terminal) != address(this)) _cancelTransferTo(address(_terminal), _amount);\n\n // Add fee amount back to project's balance.\n store.recordAddedBalanceFor(_from, _amount);\n\n emit FeeReverted(_from, _FEE_BENEFICIARY_PROJECT_ID, _amount, reason, msg.sender);\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\n {\n JBPayDelegateAllocation[] memory _delegateAllocations;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n _forwardedAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n // Get a reference to the number of delegates to allocate to.\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\n\n emit DelegateDidPay(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n unchecked {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\n IJBPaymentTerminal(address(0))\n ) return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge != IJBFeeGauge(address(0)))\n // If the guage reverts, keep the discount at 0.\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n // If the fee discount is greater than the max, we ignore the return value\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\n } catch {\n return 0;\n }\n\n return 0;\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/utils/introspection/ERC165Checker.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal3_1.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBPayDelegateAllocation.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal3_1: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal3_1 is\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n IJBPayoutRedemptionPaymentTerminal3_1\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n @dev\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.GAS_CURRENCY)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.GAS_CURRENCY, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal3_1).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal3_1).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal3_1).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance.\n */\n function _balance() internal view virtual returns (uint256);\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n bytes calldata _metadata\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _metadata);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes calldata _metadata\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _useAllowanceOf(\n _projectId,\n _amount,\n _currency,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n // Do not refund held fees by default.\n addToBalanceOf(_projectId, _amount, _token, false, _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary, _projectId);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n bool _shouldRefundHeldFees,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.GAS_TOKEN) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance.\n _addToBalanceOf(_projectId, _amount, _shouldRefundHeldFees, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual {\n _from; // Prevents unused var compiler and natspec complaints.\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered if a transfer should be undone\n\n @param _to The address to which the transfer went.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _cancelTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\n {\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\n\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _forwardedAmount,\n _beneficiary,\n _memo,\n _metadata\n );\n\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\n\n emit DelegateDidRedeem(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n bytes calldata _metadata\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n }\n\n // Take the fee.\n _fee = _feeEligibleDistributionAmount != 0\n ? _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n )\n : 0;\n\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\n if (_leftoverDistributionAmount != 0) {\n // Subtract the fee from the net leftover amount.\n netLeftoverDistributionAmount =\n _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n\n // Transfer the amount to the project owner.\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes calldata _metadata\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n // The total percentage available to split\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = _split.percent == leftoverPercentage\n ? leftoverAmount\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\n\n // Decrement the leftover percentage.\n leftoverPercentage -= _split.percent;\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount = _distributeToPayoutSplit(\n _split,\n _projectId,\n _group,\n _payoutAmount,\n _feeDiscount\n );\n\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (_netPayoutAmount != 0 && _netPayoutAmount != _payoutAmount)\n feeEligibleDistributionAmount += _payoutAmount;\n\n if (_payoutAmount > 0) {\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _payoutAmount,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Pays out a split for a project's funding cycle configuration.\n \n @param _split The split to distribute payouts to.\n @param _amount The total amount being distributed to the split, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return netPayoutAmount The amount sent to the split after subtracting fees.\n */\n function _distributeToPayoutSplit(\n JBSplit memory _split,\n uint256 _projectId,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 netPayoutAmount) {\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_split.allocator)]\n )\n netPayoutAmount = _amount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\n }\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), netPayoutAmount);\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n uint256 _error;\n bytes memory _reason;\n\n if (\n ERC165Checker.supportsInterface(\n address(_split.allocator),\n type(IJBSplitAllocator).interfaceId\n )\n )\n // If this terminal's token is ETH, send it in msg.value.\n try _split.allocator.allocate{value: token == JBTokens.GAS_TOKEN ? netPayoutAmount : 0}(_data) {\n\n } catch (bytes memory reason) {\n _reason = reason;\n _error = 1;\n }\n else _error = 2;\n\n\n if (_error != 0) {\n // Trigger any inhereted post-transfer cancelation logic.\n _cancelTransferTo(address(_split.allocator), netPayoutAmount);\n\n // Set the net payout amount to 0 to signal the reversion.\n netPayoutAmount = 0;\n\n // Add undistributed amount back to project's balance.\n store.recordAddedBalanceFor(_projectId, _amount);\n\n emit PayoutReverted(_projectId, _split, _amount, _error == 1 ? _reason : abi.encode(\"IERC165 fail\"), msg.sender);\n }\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (\n _terminal == this ||\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\n isFeelessAddress[address(_terminal)]\n )\n netPayoutAmount = _amount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\n }\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), netPayoutAmount);\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n try\n _terminal.addToBalanceOf{value: token == JBTokens.GAS_TOKEN ? netPayoutAmount : 0}(\n _split.projectId,\n netPayoutAmount,\n token,\n '',\n _projectMetadata\n )\n {} catch (bytes memory reason) {\n // Trigger any inhereted post-transfer cancelation logic.\n _cancelTransferTo(address(_terminal), netPayoutAmount);\n\n // Set the net payout amount to 0 to signal the reversion.\n netPayoutAmount = 0;\n\n // Add undistributed amount back to project's balance.\n store.recordAddedBalanceFor(_projectId, _amount);\n\n emit PayoutReverted(_projectId, _split, _amount, reason, msg.sender);\n }\n else\n try\n _terminal.pay{value: token == JBTokens.GAS_TOKEN ? netPayoutAmount : 0}(\n _split.projectId,\n netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n )\n {} catch (bytes memory reason) {\n // Trigger any inhereted post-transfer cancelation logic.\n _cancelTransferTo(address(_terminal), netPayoutAmount);\n\n // Set the net payout amount to 0 to signal the reversion.\n netPayoutAmount = 0;\n\n // Add undistributed amount back to project's balance.\n store.recordAddedBalanceFor(_projectId, _amount);\n\n emit PayoutReverted(_projectId, _split, _amount, reason, msg.sender);\n }\n } else {\n // Keep a reference to the beneficiary.\n address payable _beneficiary = _split.beneficiary != address(0)\n ? _split.beneficiary\n : payable(msg.sender);\n\n // If there's a full discount, this distribution is not eligible for a fee.\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\n netPayoutAmount = _amount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\n else {\n unchecked {\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\n }\n }\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(address(this), _beneficiary, netPayoutAmount);\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary, _projectId); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n @param _from The project ID the fee is being paid from.\n */\n function _processFee(\n uint256 _amount,\n address _beneficiary,\n uint256 _from\n ) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_from));\n\n // Trigger any inherited pre-transfer logic if funds will be transferred.\n if (address(_terminal) != address(this)) _beforeTransferTo(address(_terminal), _amount);\n\n try\n // Send the fee.\n _terminal.pay{value: _payableValue}(\n _FEE_BENEFICIARY_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n _projectMetadata\n )\n {} catch (bytes memory reason) {\n // Trigger any inhereted post-transfer cancelation logic if the pre-transfer logic was triggered.\n if (address(_terminal) != address(this)) _cancelTransferTo(address(_terminal), _amount);\n\n // Add fee amount back to project's balance.\n store.recordAddedBalanceFor(_from, _amount);\n\n emit FeeReverted(_from, _FEE_BENEFICIARY_PROJECT_ID, _amount, reason, msg.sender);\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\n {\n JBPayDelegateAllocation[] memory _delegateAllocations;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n _forwardedAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n // Get a reference to the number of delegates to allocate to.\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\n\n emit DelegateDidPay(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n unchecked {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\n IJBPaymentTerminal(address(0))\n ) return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge != IJBFeeGauge(address(0)))\n // If the guage reverts, keep the discount at 0.\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n // If the fee discount is greater than the max, we ignore the return value\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\n } catch {\n return 0;\n }\n\n return 0;\n }\n}\n" }, "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165Checker.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Library used to query support of an interface declared via {IERC165}.\n *\n * Note that these functions return the actual result of the query: they do not\n * `revert` if an interface is not supported. It is up to the caller to decide\n * what to do in these cases.\n */\nlibrary ERC165Checker {\n // As per the EIP-165 spec, no interface should ever match 0xffffffff\n bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;\n\n /**\n * @dev Returns true if `account` supports the {IERC165} interface,\n */\n function supportsERC165(address account) internal view returns (bool) {\n // Any contract that implements ERC165 must explicitly indicate support of\n // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid\n return\n _supportsERC165Interface(account, type(IERC165).interfaceId) &&\n !_supportsERC165Interface(account, _INTERFACE_ID_INVALID);\n }\n\n /**\n * @dev Returns true if `account` supports the interface defined by\n * `interfaceId`. Support for {IERC165} itself is queried automatically.\n *\n * See {IERC165-supportsInterface}.\n */\n function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {\n // query support of both ERC165 as per the spec and support of _interfaceId\n return supportsERC165(account) && _supportsERC165Interface(account, interfaceId);\n }\n\n /**\n * @dev Returns a boolean array where each value corresponds to the\n * interfaces passed in and whether they're supported or not. This allows\n * you to batch check interfaces for a contract where your expectation\n * is that some interfaces may not be supported.\n *\n * See {IERC165-supportsInterface}.\n *\n * _Available since v3.4._\n */\n function getSupportedInterfaces(address account, bytes4[] memory interfaceIds)\n internal\n view\n returns (bool[] memory)\n {\n // an array of booleans corresponding to interfaceIds and whether they're supported or not\n bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);\n\n // query support of ERC165 itself\n if (supportsERC165(account)) {\n // query support of each interface in interfaceIds\n for (uint256 i = 0; i < interfaceIds.length; i++) {\n interfaceIdsSupported[i] = _supportsERC165Interface(account, interfaceIds[i]);\n }\n }\n\n return interfaceIdsSupported;\n }\n\n /**\n * @dev Returns true if `account` supports all the interfaces defined in\n * `interfaceIds`. Support for {IERC165} itself is queried automatically.\n *\n * Batch-querying can lead to gas savings by skipping repeated checks for\n * {IERC165} support.\n *\n * See {IERC165-supportsInterface}.\n */\n function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {\n // query support of ERC165 itself\n if (!supportsERC165(account)) {\n return false;\n }\n\n // query support of each interface in _interfaceIds\n for (uint256 i = 0; i < interfaceIds.length; i++) {\n if (!_supportsERC165Interface(account, interfaceIds[i])) {\n return false;\n }\n }\n\n // all interfaces supported\n return true;\n }\n\n /**\n * @notice Query if a contract implements an interface, does not check ERC165 support\n * @param account The address of the contract to query for support of an interface\n * @param interfaceId The interface identifier, as specified in ERC-165\n * @return true if the contract at account indicates support of the interface with\n * identifier interfaceId, false otherwise\n * @dev Assumes that account contains a contract that supports ERC165, otherwise\n * the behavior of this method is undefined. This precondition can be checked\n * with {supportsERC165}.\n * Interface identification is specified in ERC-165.\n */\n function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) {\n bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);\n (bool success, bytes memory result) = account.staticcall{gas: 30000}(encodedParams);\n if (result.length < 32) return false;\n return success && abi.decode(result, (bool));\n }\n}\n" @@ -304,29 +304,29 @@ "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n function safeTransfer(\n IERC20 token,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(\n IERC20 token,\n address from,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n uint256 newAllowance = token.allowance(address(this), spender) + value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n uint256 newAllowance = oldAllowance - value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) {\n // Return data is optional\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" }, - "contracts/JBETHERC20SplitsPayer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBSplitsPayer.sol';\nimport './interfaces/IJBSplitsStore.sol';\nimport './libraries/JBConstants.sol';\nimport './JBETHERC20ProjectPayer.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\n\n @dev\n Adheres to -\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBETHERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBETHERC20SplitsPayer is JBETHERC20ProjectPayer, ReentrancyGuard, IJBSplitsPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The ID of project for which the default splits are stored. \n */\n uint256 public override defaultSplitsProjectId;\n\n /**\n @notice\n The domain within which the default splits are stored. \n */\n uint256 public override defaultSplitsDomain;\n\n /**\n @notice\n The group within which the default splits are stored. \n */\n uint256 public override defaultSplitsGroup;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBETHERC20ProjectPayer, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n )\n JBETHERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _preferAddToBalance,\n _splitsStore.directory(),\n _owner\n )\n {\n defaultSplitsProjectId = _defaultSplitsProjectId;\n defaultSplitsDomain = _defaultSplitsDomain;\n defaultSplitsGroup = _defaultSplitsGroup;\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default split group using the stored default properties.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override nonReentrant {\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n JBTokens.ETH,\n address(this).balance,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // If there is no leftover amount, nothing left to pay.\n if (_leftoverAmount == 0) return;\n\n // If there's a default project ID, try to pay it.\n if (defaultProjectId != 0)\n if (defaultPreferAddToBalance)\n // Pay the project by adding to its balance if prefered.\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.ETH,\n _leftoverAmount,\n 18, // decimals.\n defaultMemo,\n defaultMetadata\n );\n // Otherwise, issue a payment to the project.\n else\n _pay(\n defaultProjectId,\n JBTokens.ETH,\n _leftoverAmount,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n 0, // min returned tokens.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else\n Address.sendValue(\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(tx.origin),\n _leftoverAmount\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the splits in the splits store that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n @param _groupedSplits The split groups to set.\n */\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n JBGroupedSplits[] memory _groupedSplits\n ) external virtual override onlyOwner {\n // Set the splits in the store.\n splitsStore.set(_projectId, _domain, _groupedSplits);\n\n // Set the splits reference.\n setDefaultSplitsReference(_projectId, _domain, _group);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the location of the splits that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n */\n function setDefaultSplitsReference(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) public virtual override onlyOwner {\n // Set the default splits project ID if it's changing.\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\n\n // Set the default splits domain if it's changing.\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\n\n // Set the default splits group if it's changing.\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\n\n emit SetDefaultSplitsReference(_projectId, _domain, _group, msg.sender);\n }\n\n /** \n @notice \n Make a payment to the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Pay any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to pay it.\n if (_projectId != 0) {\n _pay(\n _projectId,\n _token,\n _leftoverAmount,\n _decimals,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? payable(_beneficiary) : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit Pay(\n _projectId,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event. \n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Distribute any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to add to its balance.\n if (_projectId != 0)\n // Add to the project's balance.\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\n\n // Otherwise, send a payment to the beneficiary.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit AddToBalance(\n _projectId,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splitsProjectId The ID of the project to which the splits belong.\n @param _splitsDomain The splits domain to which the group belongs.\n @param _splitsGroup The splits group to pay.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payToSplits(\n uint256 _splitsProjectId,\n uint256 _splitsDomain,\n uint256 _splitsGroup,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Pay the splits.\n leftoverAmount = _payTo(\n splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup),\n _token,\n _amount,\n _decimals,\n _defaultBeneficiary\n );\n emit DistributeToSplitGroup(_splitsProjectId, _splitsDomain, _splitsGroup, msg.sender);\n }\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splits The splits.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payTo(\n JBSplit[] memory _splits,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Set the leftover amount to the initial balance.\n leftoverAmount = _amount;\n\n // Settle between all splits.\n for (uint256 i; i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[i];\n\n // The amount to send towards the split.\n uint256 _splitAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n if (_splitAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n _token,\n _splitAmount,\n _decimals,\n defaultProjectId,\n 0,\n _split\n );\n\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\n if (_token != JBTokens.ETH)\n IERC20(_token).safeApprove(address(_split.allocator), _splitAmount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _splitAmount : 0;\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n if (_split.preferAddToBalance)\n _addToBalanceOf(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n 0,\n _split.preferClaimed,\n defaultMemo,\n defaultMetadata\n );\n } else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : payable(_defaultBeneficiary),\n _splitAmount\n );\n // Or, transfer the ERC20.\n else {\n IERC20(_token).safeTransfer(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n _splitAmount\n );\n }\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _splitAmount;\n }\n\n emit DistributeToSplit(_split, _splitAmount, _defaultBeneficiary, msg.sender);\n\n unchecked {\n ++i;\n }\n }\n }\n}\n" + "contracts/JBGasTokenERC20SplitsPayer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBSplitsPayer.sol';\nimport './interfaces/IJBSplitsStore.sol';\nimport './libraries/JBConstants.sol';\nimport './JBGasTokenERC20ProjectPayer.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\n\n @dev\n Adheres to -\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBGasTokenERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBGasTokenERC20SplitsPayer is JBGasTokenERC20ProjectPayer, ReentrancyGuard, IJBSplitsPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The ID of project for which the default splits are stored. \n */\n uint256 public override defaultSplitsProjectId;\n\n /**\n @notice\n The domain within which the default splits are stored. \n */\n uint256 public override defaultSplitsDomain;\n\n /**\n @notice\n The group within which the default splits are stored. \n */\n uint256 public override defaultSplitsGroup;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBGasTokenERC20ProjectPayer, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n )\n JBGasTokenERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _preferAddToBalance,\n _splitsStore.directory(),\n _owner\n )\n {\n defaultSplitsProjectId = _defaultSplitsProjectId;\n defaultSplitsDomain = _defaultSplitsDomain;\n defaultSplitsGroup = _defaultSplitsGroup;\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default split group using the stored default properties.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override nonReentrant {\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // If there is no leftover amount, nothing left to pay.\n if (_leftoverAmount == 0) return;\n\n // If there's a default project ID, try to pay it.\n if (defaultProjectId != 0)\n if (defaultPreferAddToBalance)\n // Pay the project by adding to its balance if prefered.\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n _leftoverAmount,\n 18, // decimals.\n defaultMemo,\n defaultMetadata\n );\n // Otherwise, issue a payment to the project.\n else\n _pay(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n _leftoverAmount,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n 0, // min returned tokens.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else\n Address.sendValue(\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(tx.origin),\n _leftoverAmount\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the splits in the splits store that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n @param _groupedSplits The split groups to set.\n */\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n JBGroupedSplits[] memory _groupedSplits\n ) external virtual override onlyOwner {\n // Set the splits in the store.\n splitsStore.set(_projectId, _domain, _groupedSplits);\n\n // Set the splits reference.\n setDefaultSplitsReference(_projectId, _domain, _group);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the location of the splits that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n */\n function setDefaultSplitsReference(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) public virtual override onlyOwner {\n // Set the default splits project ID if it's changing.\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\n\n // Set the default splits domain if it's changing.\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\n\n // Set the default splits group if it's changing.\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\n\n emit SetDefaultSplitsReference(_projectId, _domain, _group, msg.sender);\n }\n\n /** \n @notice \n Make a payment to the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Pay any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to pay it.\n if (_projectId != 0) {\n _pay(\n _projectId,\n _token,\n _leftoverAmount,\n _decimals,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? payable(_beneficiary) : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit Pay(\n _projectId,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event. \n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Distribute any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to add to its balance.\n if (_projectId != 0)\n // Add to the project's balance.\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\n\n // Otherwise, send a payment to the beneficiary.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit AddToBalance(\n _projectId,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splitsProjectId The ID of the project to which the splits belong.\n @param _splitsDomain The splits domain to which the group belongs.\n @param _splitsGroup The splits group to pay.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payToSplits(\n uint256 _splitsProjectId,\n uint256 _splitsDomain,\n uint256 _splitsGroup,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Pay the splits.\n leftoverAmount = _payTo(\n splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup),\n _token,\n _amount,\n _decimals,\n _defaultBeneficiary\n );\n emit DistributeToSplitGroup(_splitsProjectId, _splitsDomain, _splitsGroup, msg.sender);\n }\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splits The splits.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payTo(\n JBSplit[] memory _splits,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Set the leftover amount to the initial balance.\n leftoverAmount = _amount;\n\n // Settle between all splits.\n for (uint256 i; i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[i];\n\n // The amount to send towards the split.\n uint256 _splitAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n if (_splitAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n _token,\n _splitAmount,\n _decimals,\n defaultProjectId,\n 0,\n _split\n );\n\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN)\n IERC20(_token).safeApprove(address(_split.allocator), _splitAmount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _splitAmount : 0;\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n if (_split.preferAddToBalance)\n _addToBalanceOf(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n 0,\n _split.preferClaimed,\n defaultMemo,\n defaultMetadata\n );\n } else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : payable(_defaultBeneficiary),\n _splitAmount\n );\n // Or, transfer the ERC20.\n else {\n IERC20(_token).safeTransfer(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n _splitAmount\n );\n }\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _splitAmount;\n }\n\n emit DistributeToSplit(_split, _splitAmount, _defaultBeneficiary, msg.sender);\n\n unchecked {\n ++i;\n }\n }\n }\n}\n" }, "contracts/interfaces/IJBSplitsPayer.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './../structs/JBSplit.sol';\nimport './../structs/JBGroupedSplits.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBSplitsPayer is IERC165 {\n event SetDefaultSplitsReference(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n address caller\n );\n event Pay(\n uint256 indexed projectId,\n address beneficiary,\n address token,\n uint256 amount,\n uint256 decimals,\n uint256 leftoverAmount,\n uint256 minReturnedTokens,\n bool preferClaimedTokens,\n string memo,\n bytes metadata,\n address caller\n );\n\n event AddToBalance(\n uint256 indexed projectId,\n address beneficiary,\n address token,\n uint256 amount,\n uint256 decimals,\n uint256 leftoverAmount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DistributeToSplitGroup(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n address caller\n );\n\n event DistributeToSplit(\n JBSplit split,\n uint256 amount,\n address defaultBeneficiary,\n address caller\n );\n\n function defaultSplitsProjectId() external view returns (uint256);\n\n function defaultSplitsDomain() external view returns (uint256);\n\n function defaultSplitsGroup() external view returns (uint256);\n\n function splitsStore() external view returns (IJBSplitsStore);\n\n function setDefaultSplitsReference(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) external;\n\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n JBGroupedSplits[] memory _splitsGroup\n ) external;\n}\n" }, - "contracts/JBETHERC20ProjectPayer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport './interfaces/IJBProjectPayer.sol';\nimport './libraries/JBTokens.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ERC165: Introspection on interface adherance. \n*/\ncontract JBETHERC20ProjectPayer is Ownable, ERC165, IJBProjectPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // -------------------------- custom errors -------------------------- //\n //*********************************************************************//\n error INCORRECT_DECIMAL_AMOUNT();\n error NO_MSG_VALUE_ALLOWED();\n error TERMINAL_NOT_FOUND();\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice \n A contract storing directories of terminals and controllers for each project.\n */\n IJBDirectory public immutable override directory;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The ID of the project that should be used to forward this contract's received payments.\n */\n uint256 public override defaultProjectId;\n\n /** \n @notice \n The beneficiary that should be used in the payment made when this contract receives payments.\n */\n address payable public override defaultBeneficiary;\n\n /** \n @notice \n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\n */\n bool public override defaultPreferClaimedTokens;\n\n /** \n @notice \n The memo that should be used in the payment made when this contract receives payments.\n */\n string public override defaultMemo;\n\n /** \n @notice \n The metadata that should be used in the payment made when this contract receives payments.\n */\n bytes public override defaultMetadata;\n\n /**\n @notice \n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n bool public override defaultPreferAddToBalance;\n\n //*********************************************************************//\n // ------------------------- public views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) {\n defaultProjectId = _defaultProjectId;\n defaultBeneficiary = _defaultBeneficiary;\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\n defaultMemo = _defaultMemo;\n defaultMetadata = _defaultMetadata;\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n directory = _directory;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default project ID using the stored default properties.\n\n @dev\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override {\n if (defaultPreferAddToBalance)\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.ETH,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n defaultProjectId,\n JBTokens.ETH,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultBeneficiary == address(0) ? tx.origin : defaultBeneficiary,\n 0, // Can't determine expectation of returned tokens ahead of time.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\n\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _beneficiary The address that'll receive the project's tokens. \n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _memo The memo that'll be used. \n @param _metadata The metadata that'll be sent. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external virtual override onlyOwner {\n // Set the default project ID if it has changed.\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\n\n // Set the default beneficiary if it has changed.\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\n\n // Set the default claimed token preference if it has changed.\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\n defaultPreferClaimedTokens = _preferClaimedTokens;\n\n // Set the default memo if it has changed.\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\n defaultMemo = _memo;\n\n // Set the default metadata if it has changed.\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\n defaultMetadata = _metadata;\n\n // Set the add to balance preference if it has changed.\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n\n emit SetDefaultValues(\n _projectId,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata,\n _defaultPreferAddToBalance,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _pay(\n _projectId,\n _token,\n _amount,\n _decimals,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. \n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source and delegate, if provided.\n */\n function _pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.ETH) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\n\n // Send funds to the terminal.\n // If the token is ETH, send it in msg.value.\n _terminal.pay{value: _payableValue}(\n _projectId,\n _amount, // ignored if the token is JBTokens.ETH.\n _token,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.ETH) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\n\n // Add to balance so tokens don't get issued.\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\n }\n}\n" + "contracts/JBGasTokenERC20ProjectPayer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport './interfaces/IJBProjectPayer.sol';\nimport './libraries/JBTokens.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ERC165: Introspection on interface adherance. \n*/\ncontract JBGasTokenERC20ProjectPayer is Ownable, ERC165, IJBProjectPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // -------------------------- custom errors -------------------------- //\n //*********************************************************************//\n error INCORRECT_DECIMAL_AMOUNT();\n error NO_MSG_VALUE_ALLOWED();\n error TERMINAL_NOT_FOUND();\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice \n A contract storing directories of terminals and controllers for each project.\n */\n IJBDirectory public immutable override directory;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The ID of the project that should be used to forward this contract's received payments.\n */\n uint256 public override defaultProjectId;\n\n /** \n @notice \n The beneficiary that should be used in the payment made when this contract receives payments.\n */\n address payable public override defaultBeneficiary;\n\n /** \n @notice \n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\n */\n bool public override defaultPreferClaimedTokens;\n\n /** \n @notice \n The memo that should be used in the payment made when this contract receives payments.\n */\n string public override defaultMemo;\n\n /** \n @notice \n The metadata that should be used in the payment made when this contract receives payments.\n */\n bytes public override defaultMetadata;\n\n /**\n @notice \n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n bool public override defaultPreferAddToBalance;\n\n //*********************************************************************//\n // ------------------------- public views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) {\n defaultProjectId = _defaultProjectId;\n defaultBeneficiary = _defaultBeneficiary;\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\n defaultMemo = _defaultMemo;\n defaultMetadata = _defaultMetadata;\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n directory = _directory;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default project ID using the stored default properties.\n\n @dev\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override {\n if (defaultPreferAddToBalance)\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultBeneficiary == address(0) ? tx.origin : defaultBeneficiary,\n 0, // Can't determine expectation of returned tokens ahead of time.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\n\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _beneficiary The address that'll receive the project's tokens. \n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _memo The memo that'll be used. \n @param _metadata The metadata that'll be sent. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external virtual override onlyOwner {\n // Set the default project ID if it has changed.\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\n\n // Set the default beneficiary if it has changed.\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\n\n // Set the default claimed token preference if it has changed.\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\n defaultPreferClaimedTokens = _preferClaimedTokens;\n\n // Set the default memo if it has changed.\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\n defaultMemo = _memo;\n\n // Set the default metadata if it has changed.\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\n defaultMetadata = _metadata;\n\n // Set the add to balance preference if it has changed.\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n\n emit SetDefaultValues(\n _projectId,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata,\n _defaultPreferAddToBalance,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _pay(\n _projectId,\n _token,\n _amount,\n _decimals,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. \n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source and delegate, if provided.\n */\n function _pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send funds to the terminal.\n // If the token is ETH, send it in msg.value.\n _terminal.pay{value: _payableValue}(\n _projectId,\n _amount, // ignored if the token is JBTokens.GAS_TOKEN.\n _token,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Add to balance so tokens don't get issued.\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\n }\n}\n" }, "contracts/interfaces/IJBProjectPayer.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './IJBDirectory.sol';\n\ninterface IJBProjectPayer is IERC165 {\n event SetDefaultValues(\n uint256 indexed projectId,\n address indexed beneficiary,\n bool preferClaimedTokens,\n string memo,\n bytes metadata,\n bool preferAddToBalance,\n address caller\n );\n\n function directory() external view returns (IJBDirectory);\n\n function defaultProjectId() external view returns (uint256);\n\n function defaultBeneficiary() external view returns (address payable);\n\n function defaultPreferClaimedTokens() external view returns (bool);\n\n function defaultMemo() external view returns (string memory);\n\n function defaultMetadata() external view returns (bytes memory);\n\n function defaultPreferAddToBalance() external view returns (bool);\n\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external;\n\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) external payable;\n\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) external payable;\n\n receive() external payable;\n}\n" }, - "contracts/JBETHERC20SplitsPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './interfaces/IJBETHERC20SplitsPayerDeployer.sol';\nimport './structs/JBSplit.sol';\nimport './structs/JBGroupedSplits.sol';\nimport './JBETHERC20SplitsPayer.sol';\n\n/** \n @notice \n Deploys splits payer contracts.\n\n @dev\n Adheres to -\n IJBETHERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBETHERC20SplitsPayerDeployer is IJBETHERC20SplitsPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @dev\n This contract must have Operator permissions over the SET_SPLITS permission of the specified `_defaultSplitsProjectId`.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplits The splits to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBSplitsPayer splitsPayer) {\n // Use this contract's address as the domain.\n uint256 _domain = uint256(uint160(address(this)));\n\n // Create the random hash using data unique to this instance that'll be used as the storage domain.\n uint256 _group = uint256(keccak256(abi.encodePacked(msg.sender, block.number)));\n\n // Set the splits in the store.\n JBGroupedSplits[] memory _groupedSplits;\n _groupedSplits = new JBGroupedSplits[](1);\n _groupedSplits[0] = JBGroupedSplits(_group, _defaultSplits);\n _splitsStore.set(_defaultSplitsProjectId, _domain, _groupedSplits);\n\n return\n deploySplitsPayer(\n _defaultSplitsProjectId,\n _domain,\n _group,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n }\n\n //*********************************************************************//\n // ---------------------- public transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) public override returns (IJBSplitsPayer splitsPayer) {\n // Deploy the splits payer.\n splitsPayer = new JBETHERC20SplitsPayer(\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeploySplitsPayer(\n splitsPayer,\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner,\n msg.sender\n );\n }\n}\n" + "contracts/JBGasTokenERC20SplitsPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './interfaces/IJBGasTokenERC20SplitsPayerDeployer.sol';\nimport './structs/JBSplit.sol';\nimport './structs/JBGroupedSplits.sol';\nimport './JBGasTokenERC20SplitsPayer.sol';\n\n/** \n @notice \n Deploys splits payer contracts.\n\n @dev\n Adheres to -\n IJBGasTokenERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBGasTokenERC20SplitsPayerDeployer is IJBGasTokenERC20SplitsPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @dev\n This contract must have Operator permissions over the SET_SPLITS permission of the specified `_defaultSplitsProjectId`.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplits The splits to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBSplitsPayer splitsPayer) {\n // Use this contract's address as the domain.\n uint256 _domain = uint256(uint160(address(this)));\n\n // Create the random hash using data unique to this instance that'll be used as the storage domain.\n uint256 _group = uint256(keccak256(abi.encodePacked(msg.sender, block.number)));\n\n // Set the splits in the store.\n JBGroupedSplits[] memory _groupedSplits;\n _groupedSplits = new JBGroupedSplits[](1);\n _groupedSplits[0] = JBGroupedSplits(_group, _defaultSplits);\n _splitsStore.set(_defaultSplitsProjectId, _domain, _groupedSplits);\n\n return\n deploySplitsPayer(\n _defaultSplitsProjectId,\n _domain,\n _group,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n }\n\n //*********************************************************************//\n // ---------------------- public transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) public override returns (IJBSplitsPayer splitsPayer) {\n // Deploy the splits payer.\n splitsPayer = new JBGasTokenERC20SplitsPayer(\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeploySplitsPayer(\n splitsPayer,\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner,\n msg.sender\n );\n }\n}\n" }, - "contracts/interfaces/IJBETHERC20SplitsPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBSplitsPayer.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBETHERC20SplitsPayerDeployer {\n event DeploySplitsPayer(\n IJBSplitsPayer indexed splitsPayer,\n uint256 defaultSplitsProjectId,\n uint256 defaultSplitsDomain,\n uint256 defaultSplitsGroup,\n IJBSplitsStore splitsStore,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n address owner,\n address caller\n );\n\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string calldata _defaultMemo,\n bytes calldata _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n}\n" + "contracts/interfaces/IJBGasTokenERC20SplitsPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBSplitsPayer.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBGasTokenERC20SplitsPayerDeployer {\n event DeploySplitsPayer(\n IJBSplitsPayer indexed splitsPayer,\n uint256 defaultSplitsProjectId,\n uint256 defaultSplitsDomain,\n uint256 defaultSplitsGroup,\n IJBSplitsStore splitsStore,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n address owner,\n address caller\n );\n\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string calldata _defaultMemo,\n bytes calldata _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n}\n" }, - "contracts/JBETHERC20ProjectPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './interfaces/IJBETHERC20ProjectPayerDeployer.sol';\nimport './JBETHERC20ProjectPayer.sol';\n\n/** \n @notice \n Deploys project payer contracts.\n\n @dev\n Adheres to -\n IJBETHERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBETHERC20ProjectPayerDeployer is IJBETHERC20ProjectPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new project payer contract.\n\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the project payer contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the project payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the project payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the project payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the project payer.\n\n @return projectPayer The project payer contract.\n */\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external override returns (IJBProjectPayer projectPayer) {\n // Deploy the project payer.\n projectPayer = new JBETHERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner\n );\n\n emit DeployProjectPayer(\n projectPayer,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner,\n msg.sender\n );\n }\n}\n" + "contracts/JBGasTokenERC20ProjectPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './interfaces/IJBGasTokenERC20ProjectPayerDeployer.sol';\nimport './JBGasTokenERC20ProjectPayer.sol';\n\n/** \n @notice \n Deploys project payer contracts.\n\n @dev\n Adheres to -\n IJBGasTokenERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBGasTokenERC20ProjectPayerDeployer is IJBGasTokenERC20ProjectPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new project payer contract.\n\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the project payer contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the project payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the project payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the project payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the project payer.\n\n @return projectPayer The project payer contract.\n */\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external override returns (IJBProjectPayer projectPayer) {\n // Deploy the project payer.\n projectPayer = new JBGasTokenERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner\n );\n\n emit DeployProjectPayer(\n projectPayer,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner,\n msg.sender\n );\n }\n}\n" }, - "contracts/interfaces/IJBETHERC20ProjectPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBDirectory.sol';\nimport './IJBProjectPayer.sol';\n\ninterface IJBETHERC20ProjectPayerDeployer {\n event DeployProjectPayer(\n IJBProjectPayer indexed projectPayer,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n IJBDirectory directory,\n address owner,\n address caller\n );\n\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external returns (IJBProjectPayer projectPayer);\n}\n" + "contracts/interfaces/IJBGasTokenERC20ProjectPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBDirectory.sol';\nimport './IJBProjectPayer.sol';\n\ninterface IJBGasTokenERC20ProjectPayerDeployer {\n event DeployProjectPayer(\n IJBProjectPayer indexed projectPayer,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n IJBDirectory directory,\n address owner,\n address caller\n );\n\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external returns (IJBProjectPayer projectPayer);\n}\n" }, "contracts/JBDirectory.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport './abstract/JBOperatable.sol';\nimport './interfaces/IJBDirectory.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './libraries/JBOperations.sol';\n\n/**\n @notice\n Keeps a reference of which terminal contracts each project is currently accepting funds through, and which controller contract is managing each project's tokens and funding cycles.\n\n @dev\n Adheres to -\n IJBDirectory: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\ncontract JBDirectory is JBOperatable, Ownable, IJBDirectory {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error DUPLICATE_TERMINALS();\n error INVALID_PROJECT_ID_IN_DIRECTORY();\n error SET_CONTROLLER_NOT_ALLOWED();\n error SET_TERMINALS_NOT_ALLOWED();\n error TOKEN_NOT_ACCEPTED();\n\n //*********************************************************************//\n // --------------------- private stored properties ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n For each project ID, the terminals that are currently managing its funds.\n\n _projectId The ID of the project to get terminals of.\n */\n mapping(uint256 => IJBPaymentTerminal[]) private _terminalsOf;\n\n /**\n @notice\n The project's primary terminal for a token.\n\n _projectId The ID of the project to get the primary terminal of.\n _token The token to get the project's primary terminal of.\n */\n mapping(uint256 => mapping(address => IJBPaymentTerminal)) private _primaryTerminalOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n For each project ID, the controller that manages how terminals interact with tokens and funding cycles.\n\n _projectId The ID of the project to get the controller of.\n */\n mapping(uint256 => address) public override controllerOf;\n\n /**\n @notice\n Addresses that can set a project's first controller on their behalf. These addresses/contracts have been vetted and verified by this contract's owner.\n\n _address The address that is either allowed or not.\n */\n mapping(address => bool) public override isAllowedToSetFirstController;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n For each project ID, the terminals that are currently managing its funds.\n\n @param _projectId The ID of the project to get terminals of.\n\n @return An array of terminal addresses.\n */\n function terminalsOf(uint256 _projectId)\n external\n view\n override\n returns (IJBPaymentTerminal[] memory)\n {\n return _terminalsOf[_projectId];\n }\n\n /**\n @notice\n The primary terminal that is managing funds for a project for a specified token.\n\n @dev\n The zero address is returned if a terminal isn't found for the specified token.\n\n @param _projectId The ID of the project to get a terminal for.\n @param _token The token the terminal accepts.\n\n @return The primary terminal for the project for the specified token.\n */\n function primaryTerminalOf(uint256 _projectId, address _token)\n external\n view\n override\n returns (IJBPaymentTerminal)\n {\n // Keep a reference to the primary terminal for the provided project ID and token.\n IJBPaymentTerminal _primaryTerminal = _primaryTerminalOf[_projectId][_token];\n\n // If a primary terminal for the token was specifically set and it's one of the project's terminals, return it.\n if (\n _primaryTerminal != IJBPaymentTerminal(address(0)) &&\n isTerminalOf(_projectId, _primaryTerminal)\n ) return _primaryTerminal;\n\n // Keep a reference to the number of terminals the project has.\n uint256 _numberOfTerminals = _terminalsOf[_projectId].length;\n\n // Return the first terminal which accepts the specified token.\n for (uint256 _i; _i < _numberOfTerminals; ) {\n // Keep a reference to the terminal being iterated on.\n IJBPaymentTerminal _terminal = _terminalsOf[_projectId][_i];\n\n // If the terminal accepts the specified token, return it.\n if (_terminal.acceptsToken(_token, _projectId)) return _terminal;\n\n unchecked {\n ++_i;\n }\n }\n\n // Not found.\n return IJBPaymentTerminal(address(0));\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Whether or not a specified terminal is a terminal of the specified project.\n\n @param _projectId The ID of the project to check within.\n @param _terminal The address of the terminal to check for.\n\n @return A flag indicating whether or not the specified terminal is a terminal of the specified project.\n */\n function isTerminalOf(uint256 _projectId, IJBPaymentTerminal _terminal)\n public\n view\n override\n returns (bool)\n {\n // Keep a reference to the number of terminals the project has.\n uint256 _numberOfTerminals = _terminalsOf[_projectId].length;\n\n // Loop through and return true if the terminal is contained.\n for (uint256 _i; _i < _numberOfTerminals; ) {\n // If the terminal being iterated on matches the provided terminal, return true.\n if (_terminalsOf[_projectId][_i] == _terminal) return true;\n\n unchecked {\n ++_i;\n }\n }\n\n // Otherwise, return false.\n return false;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _owner The address that will own the contract.\n */\n constructor(\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBFundingCycleStore _fundingCycleStore,\n address _owner\n ) JBOperatable(_operatorStore) {\n projects = _projects;\n fundingCycleStore = _fundingCycleStore;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Update the controller that manages how terminals interact with the ecosystem.\n\n @dev\n A controller can be set if:\n - the message sender is the project owner or an operator having the correct authorization.\n - the message sender is the project's current controller.\n - or, an allowedlisted address is setting a controller for a project that doesn't already have a controller.\n\n @param _projectId The ID of the project to set a new controller for.\n @param _controller The new controller to set.\n */\n function setControllerOf(uint256 _projectId, address _controller)\n external\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.SET_CONTROLLER,\n (msg.sender == address(controllerOf[_projectId]) ||\n (isAllowedToSetFirstController[msg.sender] && controllerOf[_projectId] == address(0)))\n )\n {\n // The project must exist.\n if (projects.count() < _projectId) revert INVALID_PROJECT_ID_IN_DIRECTORY();\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Setting controller is allowed if called from the current controller, or if the project doesn't have a current controller, or if the project's funding cycle allows setting the controller. Revert otherwise.\n if (\n msg.sender != address(controllerOf[_projectId]) &&\n controllerOf[_projectId] != address(0) &&\n !_fundingCycle.global().allowSetController\n ) revert SET_CONTROLLER_NOT_ALLOWED();\n\n // Set the new controller.\n controllerOf[_projectId] = _controller;\n\n emit SetController(_projectId, _controller, msg.sender);\n }\n\n /** \n @notice \n Set a project's terminals.\n\n @dev\n Only a project owner, an operator, or its controller can set its terminals.\n\n @param _projectId The ID of the project having terminals set.\n @param _terminals The terminal to set.\n */\n function setTerminalsOf(uint256 _projectId, IJBPaymentTerminal[] calldata _terminals)\n external\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.SET_TERMINALS,\n msg.sender == address(controllerOf[_projectId])\n )\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Setting terminals must be allowed if not called from the current controller.\n if (\n msg.sender != address(controllerOf[_projectId]) && !_fundingCycle.global().allowSetTerminals\n ) revert SET_TERMINALS_NOT_ALLOWED();\n\n // Set the stored terminals for the project.\n _terminalsOf[_projectId] = _terminals;\n\n // Make sure duplicates were not added.\n if (_terminals.length > 1) {\n for (uint256 _i; _i < _terminals.length; ) {\n for (uint256 _j = _i + 1; _j < _terminals.length; ) {\n if (_terminals[_i] == _terminals[_j]) revert DUPLICATE_TERMINALS();\n\n unchecked {\n ++_j;\n }\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n emit SetTerminals(_projectId, _terminals, msg.sender);\n }\n\n /**\n @notice\n Project's can set which terminal should be their primary for a particular token.\n This is useful in case a project has several terminals connected for a particular token.\n\n @dev\n The terminal will be set as the primary terminal where ecosystem contracts should route tokens.\n\n @dev\n If setting a newly added terminal and the funding cycle doesn't allow new terminals, the caller must be the current controller.\n\n @param _projectId The ID of the project for which a primary token is being set.\n @param _token The token to set the primary terminal of.\n @param _terminal The terminal to make primary.\n */\n function setPrimaryTerminalOf(\n uint256 _projectId,\n address _token,\n IJBPaymentTerminal _terminal\n )\n external\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.SET_PRIMARY_TERMINAL)\n {\n // Can't set the primary terminal for a token if it doesn't accept the token.\n if (!_terminal.acceptsToken(_token, _projectId)) revert TOKEN_NOT_ACCEPTED();\n\n // Add the terminal to the project if it hasn't been already.\n _addTerminalIfNeeded(_projectId, _terminal);\n\n // Store the terminal as the primary for the particular token.\n _primaryTerminalOf[_projectId][_token] = _terminal;\n\n emit SetPrimaryTerminal(_projectId, _token, _terminal, msg.sender);\n }\n\n /** \n @notice\t\n Set a contract to the list of trusted addresses that can set a first controller for any project.\t\n\n @dev\n The owner can add addresses which are allowed to change projects' first controllers. \n These addresses are known and vetted controllers as well as contracts designed to launch new projects. \n A project can set its own controller without it being on the allow list.\n\n @dev\n If you would like an address/contract allowlisted, please reach out to the contract owner.\n\n @param _address The address to allow or revoke allowance from.\n @param _flag Whether allowance is being added or revoked.\n */\n function setIsAllowedToSetFirstController(address _address, bool _flag)\n external\n override\n onlyOwner\n {\n // Set the flag in the allowlist.\n isAllowedToSetFirstController[_address] = _flag;\n\n emit SetIsAllowedToSetFirstController(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Add a terminal to a project's list of terminals if it hasn't been already.\n\n @param _projectId The ID of the project having a terminal added.\n @param _terminal The terminal to add.\n */\n function _addTerminalIfNeeded(uint256 _projectId, IJBPaymentTerminal _terminal) private {\n // Check that the terminal has not already been added.\n if (isTerminalOf(_projectId, _terminal)) return;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Setting terminals must be allowed if not called from the current controller.\n if (\n msg.sender != address(controllerOf[_projectId]) && !_fundingCycle.global().allowSetTerminals\n ) revert SET_TERMINALS_NOT_ALLOWED();\n\n // Add the new terminal.\n _terminalsOf[_projectId].push(_terminal);\n\n emit AddTerminal(_projectId, _terminal, msg.sender);\n }\n}\n" @@ -350,7 +350,7 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './interfaces/IJBOperatorStore.sol';\n\n/** \n @notice\n Stores operator permissions for all addresses. Addresses can give permissions to any other address to take specific indexed actions on their behalf.\n\n @dev\n Adheres to -\n IJBOperatorStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBOperatorStore is IJBOperatorStore {\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error PERMISSION_INDEX_OUT_OF_BOUNDS();\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice\n The permissions that an operator has been given to operate on a specific domain.\n \n @dev\n An account can give an operator permissions that only pertain to a specific domain namespace.\n There is no domain with a value of 0 – accounts can use the 0 domain to give an operator\n permissions to all domains on their behalf.\n\n @dev\n Permissions are stored in a packed `uint256`. Each 256 bits represents the on/off state of a permission. Applications can specify the significance of each index.\n\n _operator The address of the operator.\n _account The address of the account being operated.\n _domain The domain within which the permissions apply. Applications can use the domain namespace as they wish.\n */\n mapping(address => mapping(address => mapping(uint256 => uint256))) public override permissionsOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Whether or not an operator has the permission to take a certain action pertaining to the specified domain.\n\n @param _operator The operator to check.\n @param _account The account that has given out permissions to the operator.\n @param _domain The domain that the operator has been given permissions to operate.\n @param _permissionIndex The permission index to check for.\n\n @return A flag indicating whether the operator has the specified permission.\n */\n function hasPermission(\n address _operator,\n address _account,\n uint256 _domain,\n uint256 _permissionIndex\n ) external view override returns (bool) {\n if (_permissionIndex > 255) revert PERMISSION_INDEX_OUT_OF_BOUNDS();\n\n return (((permissionsOf[_operator][_account][_domain] >> _permissionIndex) & 1) == 1);\n }\n\n /** \n @notice \n Whether or not an operator has the permission to take certain actions pertaining to the specified domain.\n\n @param _operator The operator to check.\n @param _account The account that has given out permissions to the operator.\n @param _domain The domain that the operator has been given permissions to operate.\n @param _permissionIndexes An array of permission indexes to check for.\n\n @return A flag indicating whether the operator has all specified permissions.\n */\n function hasPermissions(\n address _operator,\n address _account,\n uint256 _domain,\n uint256[] calldata _permissionIndexes\n ) external view override returns (bool) {\n for (uint256 _i; _i < _permissionIndexes.length; ) {\n uint256 _permissionIndex = _permissionIndexes[_i];\n\n if (_permissionIndex > 255) revert PERMISSION_INDEX_OUT_OF_BOUNDS();\n\n if (((permissionsOf[_operator][_account][_domain] >> _permissionIndex) & 1) == 0)\n return false;\n\n unchecked {\n ++_i;\n }\n }\n return true;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Sets permissions for an operators.\n\n @dev\n Only an address can set its own operators.\n\n @param _operatorData The data that specifies the params for the operator being set.\n */\n function setOperator(JBOperatorData calldata _operatorData) external override {\n // Pack the indexes into a uint256.\n uint256 _packed = _packedPermissions(_operatorData.permissionIndexes);\n\n // Store the new value.\n permissionsOf[_operatorData.operator][msg.sender][_operatorData.domain] = _packed;\n\n emit SetOperator(\n _operatorData.operator,\n msg.sender,\n _operatorData.domain,\n _operatorData.permissionIndexes,\n _packed\n );\n }\n\n /**\n @notice\n Sets permissions for many operators.\n\n @dev\n Only an address can set its own operators.\n\n @param _operatorData The data that specify the params for each operator being set.\n */\n function setOperators(JBOperatorData[] calldata _operatorData) external override {\n for (uint256 _i; _i < _operatorData.length; ) {\n // Pack the indexes into a uint256.\n uint256 _packed = _packedPermissions(_operatorData[_i].permissionIndexes);\n\n // Store the new value.\n permissionsOf[_operatorData[_i].operator][msg.sender][_operatorData[_i].domain] = _packed;\n\n emit SetOperator(\n _operatorData[_i].operator,\n msg.sender,\n _operatorData[_i].domain,\n _operatorData[_i].permissionIndexes,\n _packed\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Converts an array of permission indexes to a packed `uint256`.\n\n @param _indexes The indexes of the permissions to pack.\n\n @return packed The packed value.\n */\n function _packedPermissions(uint256[] calldata _indexes) private pure returns (uint256 packed) {\n for (uint256 _i; _i < _indexes.length; ) {\n uint256 _index = _indexes[_i];\n\n if (_index > 255) revert PERMISSION_INDEX_OUT_OF_BOUNDS();\n\n // Turn the bit at the index on.\n packed |= 1 << _index;\n\n unchecked {\n ++_i;\n }\n }\n }\n}\n" }, "contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBPayDelegateAllocation.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal is\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n IJBPayoutRedemptionPaymentTerminal\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n @dev\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.ETH)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.ETH, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance.\n */\n function _balance() internal view virtual returns (uint256);\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.ETH) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual {\n _from; // Prevents unused var compiler and natspec complaints.\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\n {\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\n\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _forwardedAmount,\n _beneficiary,\n _memo,\n _metadata\n );\n\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\n\n emit DelegateDidRedeem(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n }\n\n // Take the fee.\n _fee = _feeEligibleDistributionAmount != 0\n ? _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n )\n : 0;\n\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\n if (_leftoverDistributionAmount != 0) {\n // Subtract the fee from the net leftover amount.\n netLeftoverDistributionAmount =\n _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n\n // Transfer the amount to the project owner.\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n // The total percentage available to split\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = _split.percent == leftoverPercentage\n ? leftoverAmount\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\n\n // Decrement the leftover percentage.\n leftoverPercentage -= _split.percent;\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount;\n\n if (_payoutAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\n isFeelessAddress[address(_split.allocator)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n _netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n // If this terminal's token is ETH, send it in msg.value.\n _split.allocator.allocate{value: token == JBTokens.ETH ? _netPayoutAmount : 0}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // Save gas if this contract is being used as the terminal.\n if (_terminal == this) {\n // This distribution does not incur a fee.\n _netPayoutAmount = _payoutAmount;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\n else\n _pay(\n _netPayoutAmount,\n address(this),\n _split.projectId,\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n } else {\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_terminal)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _netPayoutAmount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _terminal.addToBalanceOf{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n '',\n _projectMetadata\n );\n else\n _terminal.pay{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n }\n } else {\n // Keep a reference to the beneficiary.\n address payable _beneficiary = _split.beneficiary != address(0)\n ? _split.beneficiary\n : payable(msg.sender);\n\n // If there's a full discount, this distribution is not eligible for a fee.\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(address(this), _beneficiary, _netPayoutAmount);\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n */\n function _processFee(uint256 _amount, address _beneficiary) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\n\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\n if (_terminal == this)\n _pay(\n _amount,\n address(this),\n _FEE_BENEFICIARY_PROJECT_ID,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the local pay call.\n else {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _amount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _amount : 0;\n\n // Send the payment.\n _terminal.pay{value: _payableValue}(\n _FEE_BENEFICIARY_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the external pay call of the correct terminal.\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\n {\n JBPayDelegateAllocation[] memory _delegateAllocations;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n _forwardedAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n // Get a reference to the number of delegates to allocate to.\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\n\n emit DelegateDidPay(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n unchecked {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\n IJBPaymentTerminal(address(0))\n ) return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge != IJBFeeGauge(address(0)))\n // If the guage reverts, keep the discount at 0.\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n // If the fee discount is greater than the max, we ignore the return value\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\n } catch {\n return 0;\n }\n\n return 0;\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBPayDelegateAllocation.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal is\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n IJBPayoutRedemptionPaymentTerminal\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n @dev\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.GAS_CURRENCY)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.GAS_CURRENCY, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance.\n */\n function _balance() internal view virtual returns (uint256);\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.GAS_TOKEN) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual {\n _from; // Prevents unused var compiler and natspec complaints.\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\n {\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\n\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _forwardedAmount,\n _beneficiary,\n _memo,\n _metadata\n );\n\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\n\n emit DelegateDidRedeem(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n }\n\n // Take the fee.\n _fee = _feeEligibleDistributionAmount != 0\n ? _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n )\n : 0;\n\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\n if (_leftoverDistributionAmount != 0) {\n // Subtract the fee from the net leftover amount.\n netLeftoverDistributionAmount =\n _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n\n // Transfer the amount to the project owner.\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n // The total percentage available to split\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = _split.percent == leftoverPercentage\n ? leftoverAmount\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\n\n // Decrement the leftover percentage.\n leftoverPercentage -= _split.percent;\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount;\n\n if (_payoutAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\n isFeelessAddress[address(_split.allocator)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n _netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n // If this terminal's token is ETH, send it in msg.value.\n _split.allocator.allocate{value: token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // Save gas if this contract is being used as the terminal.\n if (_terminal == this) {\n // This distribution does not incur a fee.\n _netPayoutAmount = _payoutAmount;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\n else\n _pay(\n _netPayoutAmount,\n address(this),\n _split.projectId,\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n } else {\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_terminal)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _terminal.addToBalanceOf{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n '',\n _projectMetadata\n );\n else\n _terminal.pay{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n }\n } else {\n // Keep a reference to the beneficiary.\n address payable _beneficiary = _split.beneficiary != address(0)\n ? _split.beneficiary\n : payable(msg.sender);\n\n // If there's a full discount, this distribution is not eligible for a fee.\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(address(this), _beneficiary, _netPayoutAmount);\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n */\n function _processFee(uint256 _amount, address _beneficiary) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\n\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\n if (_terminal == this)\n _pay(\n _amount,\n address(this),\n _FEE_BENEFICIARY_PROJECT_ID,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the local pay call.\n else {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _amount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send the payment.\n _terminal.pay{value: _payableValue}(\n _FEE_BENEFICIARY_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the external pay call of the correct terminal.\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\n {\n JBPayDelegateAllocation[] memory _delegateAllocations;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n _forwardedAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n // Get a reference to the number of delegates to allocate to.\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\n\n emit DelegateDidPay(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n unchecked {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\n IJBPaymentTerminal(address(0))\n ) return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge != IJBFeeGauge(address(0)))\n // If the guage reverts, keep the discount at 0.\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n // If the fee discount is greater than the max, we ignore the return value\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\n } catch {\n return 0;\n }\n\n return 0;\n }\n}\n" }, "contracts/interfaces/IJBPayoutRedemptionPaymentTerminal.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './../structs/JBFee.sol';\nimport './IJBAllowanceTerminal.sol';\nimport './IJBDirectory.sol';\nimport './IJBFeeGauge.sol';\nimport './IJBPayDelegate.sol';\nimport './IJBPaymentTerminal.sol';\nimport './IJBPayoutTerminal.sol';\nimport './IJBPrices.sol';\nimport './IJBProjects.sol';\nimport './IJBRedemptionDelegate.sol';\nimport './IJBRedemptionTerminal.sol';\nimport './IJBSingleTokenPaymentTerminalStore.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBPayoutRedemptionPaymentTerminal is\n IJBPaymentTerminal,\n IJBPayoutTerminal,\n IJBAllowanceTerminal,\n IJBRedemptionTerminal\n{\n event AddToBalance(\n uint256 indexed projectId,\n uint256 amount,\n uint256 refundedFees,\n string memo,\n bytes metadata,\n address caller\n );\n\n event Migrate(\n uint256 indexed projectId,\n IJBPaymentTerminal indexed to,\n uint256 amount,\n address caller\n );\n\n event DistributePayouts(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address beneficiary,\n uint256 amount,\n uint256 distributedAmount,\n uint256 fee,\n uint256 beneficiaryDistributionAmount,\n string memo,\n address caller\n );\n\n event UseAllowance(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address beneficiary,\n uint256 amount,\n uint256 distributedAmount,\n uint256 netDistributedamount,\n string memo,\n address caller\n );\n\n event HoldFee(\n uint256 indexed projectId,\n uint256 indexed amount,\n uint256 indexed fee,\n uint256 feeDiscount,\n address beneficiary,\n address caller\n );\n\n event ProcessFee(\n uint256 indexed projectId,\n uint256 indexed amount,\n bool indexed wasHeld,\n address beneficiary,\n address caller\n );\n\n event RefundHeldFees(\n uint256 indexed projectId,\n uint256 indexed amount,\n uint256 indexed refundedFees,\n uint256 leftoverAmount,\n address caller\n );\n\n event Pay(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address payer,\n address beneficiary,\n uint256 amount,\n uint256 beneficiaryTokenCount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DelegateDidPay(\n IJBPayDelegate indexed delegate,\n JBDidPayData data,\n uint256 delegatedAmount,\n address caller\n );\n\n event RedeemTokens(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address holder,\n address beneficiary,\n uint256 tokenCount,\n uint256 reclaimedAmount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DelegateDidRedeem(\n IJBRedemptionDelegate indexed delegate,\n JBDidRedeemData data,\n uint256 delegatedAmount,\n address caller\n );\n\n event DistributeToPayoutSplit(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n JBSplit split,\n uint256 amount,\n address caller\n );\n\n event SetFee(uint256 fee, address caller);\n\n event SetFeeGauge(IJBFeeGauge indexed feeGauge, address caller);\n\n event SetFeelessAddress(address indexed addrs, bool indexed flag, address caller);\n\n function projects() external view returns (IJBProjects);\n\n function splitsStore() external view returns (IJBSplitsStore);\n\n function directory() external view returns (IJBDirectory);\n\n function prices() external view returns (IJBPrices);\n\n function store() external view returns (IJBSingleTokenPaymentTerminalStore);\n\n function baseWeightCurrency() external view returns (uint256);\n\n function payoutSplitsGroup() external view returns (uint256);\n\n function heldFeesOf(uint256 _projectId) external view returns (JBFee[] memory);\n\n function fee() external view returns (uint256);\n\n function feeGauge() external view returns (IJBFeeGauge);\n\n function isFeelessAddress(address _contract) external view returns (bool);\n\n function migrate(uint256 _projectId, IJBPaymentTerminal _to) external returns (uint256 balance);\n\n function processFees(uint256 _projectId) external;\n\n function setFee(uint256 _fee) external;\n\n function setFeeGauge(IJBFeeGauge _feeGauge) external;\n\n function setFeelessAddress(address _contract, bool _flag) external;\n}\n" @@ -362,7 +362,7 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IJBPayoutTerminal {\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) external returns (uint256 netLeftoverDistributionAmount);\n}\n" }, "contracts/JBETHPaymentTerminal.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\nimport './libraries/JBSplitsGroups.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return address(this).balance;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n JBTokens.ETH,\n 18, // 18 decimals.\n JBCurrencies.ETH,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\nimport './libraries/JBSplitsGroups.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return address(this).balance;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n JBTokens.GAS_TOKEN,\n 18, // 18 decimals.\n JBCurrencies.GAS_CURRENCY,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n}\n" }, "contracts/JBERC20PaymentTerminal.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\n\n/** \n @notice \n Manages the inflows and outflows of an ERC-20 token.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\ncontract JBERC20PaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return IERC20(token).balanceOf(address(this));\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n IERC20Metadata _token,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n address(_token),\n _token.decimals(),\n _currency,\n _baseWeightCurrency,\n _payoutSplitsGroup,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from == address(this)\n ? IERC20(token).safeTransfer(_to, _amount)\n : IERC20(token).safeTransferFrom(_from, _to, _amount);\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal override {\n IERC20(token).safeApprove(_to, _amount);\n }\n}\n" diff --git a/deployments/mainnet/solcInputs/7f5ae5369c2a685c882e67f75315b841.json b/deployments/mainnet/solcInputs/7f5ae5369c2a685c882e67f75315b841.json index 8819afbdf..331538fd8 100644 --- a/deployments/mainnet/solcInputs/7f5ae5369c2a685c882e67f75315b841.json +++ b/deployments/mainnet/solcInputs/7f5ae5369c2a685c882e67f75315b841.json @@ -146,13 +146,13 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport './abstract/JBOperatable.sol';\nimport './interfaces/IJBDirectory.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './libraries/JBOperations.sol';\n\n/**\n @notice\n Keeps a reference of which terminal contracts each project is currently accepting funds through, and which controller contract is managing each project's tokens and funding cycles.\n\n @dev\n Adheres to -\n IJBDirectory: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\ncontract JBDirectory is JBOperatable, Ownable, IJBDirectory {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error DUPLICATE_TERMINALS();\n error INVALID_PROJECT_ID_IN_DIRECTORY();\n error SET_CONTROLLER_NOT_ALLOWED();\n error SET_TERMINALS_NOT_ALLOWED();\n error TOKEN_NOT_ACCEPTED();\n\n //*********************************************************************//\n // --------------------- private stored properties ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n For each project ID, the terminals that are currently managing its funds.\n\n _projectId The ID of the project to get terminals of.\n */\n mapping(uint256 => IJBPaymentTerminal[]) private _terminalsOf;\n\n /**\n @notice\n The project's primary terminal for a token.\n\n _projectId The ID of the project to get the primary terminal of.\n _token The token to get the project's primary terminal of.\n */\n mapping(uint256 => mapping(address => IJBPaymentTerminal)) private _primaryTerminalOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n For each project ID, the controller that manages how terminals interact with tokens and funding cycles.\n\n _projectId The ID of the project to get the controller of.\n */\n mapping(uint256 => address) public override controllerOf;\n\n /**\n @notice\n Addresses that can set a project's first controller on their behalf. These addresses/contracts have been vetted and verified by this contract's owner.\n\n _address The address that is either allowed or not.\n */\n mapping(address => bool) public override isAllowedToSetFirstController;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n For each project ID, the terminals that are currently managing its funds.\n\n @param _projectId The ID of the project to get terminals of.\n\n @return An array of terminal addresses.\n */\n function terminalsOf(uint256 _projectId)\n external\n view\n override\n returns (IJBPaymentTerminal[] memory)\n {\n return _terminalsOf[_projectId];\n }\n\n /**\n @notice\n The primary terminal that is managing funds for a project for a specified token.\n\n @dev\n The zero address is returned if a terminal isn't found for the specified token.\n\n @param _projectId The ID of the project to get a terminal for.\n @param _token The token the terminal accepts.\n\n @return The primary terminal for the project for the specified token.\n */\n function primaryTerminalOf(uint256 _projectId, address _token)\n external\n view\n override\n returns (IJBPaymentTerminal)\n {\n // Keep a reference to the primary terminal for the provided project ID and token.\n IJBPaymentTerminal _primaryTerminal = _primaryTerminalOf[_projectId][_token];\n\n // If a primary terminal for the token was specifically set and it's one of the project's terminals, return it.\n if (\n _primaryTerminal != IJBPaymentTerminal(address(0)) &&\n isTerminalOf(_projectId, _primaryTerminal)\n ) return _primaryTerminal;\n\n // Keep a reference to the number of terminals the project has.\n uint256 _numberOfTerminals = _terminalsOf[_projectId].length;\n\n // Return the first terminal which accepts the specified token.\n for (uint256 _i; _i < _numberOfTerminals; ) {\n // Keep a reference to the terminal being iterated on.\n IJBPaymentTerminal _terminal = _terminalsOf[_projectId][_i];\n\n // If the terminal accepts the specified token, return it.\n if (_terminal.acceptsToken(_token, _projectId)) return _terminal;\n\n unchecked {\n ++_i;\n }\n }\n\n // Not found.\n return IJBPaymentTerminal(address(0));\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Whether or not a specified terminal is a terminal of the specified project.\n\n @param _projectId The ID of the project to check within.\n @param _terminal The address of the terminal to check for.\n\n @return A flag indicating whether or not the specified terminal is a terminal of the specified project.\n */\n function isTerminalOf(uint256 _projectId, IJBPaymentTerminal _terminal)\n public\n view\n override\n returns (bool)\n {\n // Keep a reference to the number of terminals the project has.\n uint256 _numberOfTerminals = _terminalsOf[_projectId].length;\n\n // Loop through and return true if the terminal is contained.\n for (uint256 _i; _i < _numberOfTerminals; ) {\n // If the terminal being iterated on matches the provided terminal, return true.\n if (_terminalsOf[_projectId][_i] == _terminal) return true;\n\n unchecked {\n ++_i;\n }\n }\n\n // Otherwise, return false.\n return false;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _owner The address that will own the contract.\n */\n constructor(\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBFundingCycleStore _fundingCycleStore,\n address _owner\n ) JBOperatable(_operatorStore) {\n projects = _projects;\n fundingCycleStore = _fundingCycleStore;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Update the controller that manages how terminals interact with the ecosystem.\n\n @dev\n A controller can be set if:\n - the message sender is the project owner or an operator having the correct authorization.\n - the message sender is the project's current controller.\n - or, an allowedlisted address is setting a controller for a project that doesn't already have a controller.\n\n @param _projectId The ID of the project to set a new controller for.\n @param _controller The new controller to set.\n */\n function setControllerOf(uint256 _projectId, address _controller)\n external\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.SET_CONTROLLER,\n (msg.sender == address(controllerOf[_projectId]) ||\n (isAllowedToSetFirstController[msg.sender] && controllerOf[_projectId] == address(0)))\n )\n {\n // The project must exist.\n if (projects.count() < _projectId) revert INVALID_PROJECT_ID_IN_DIRECTORY();\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Setting controller is allowed if called from the current controller, or if the project doesn't have a current controller, or if the project's funding cycle allows setting the controller. Revert otherwise.\n if (\n msg.sender != address(controllerOf[_projectId]) &&\n controllerOf[_projectId] != address(0) &&\n !_fundingCycle.global().allowSetController\n ) revert SET_CONTROLLER_NOT_ALLOWED();\n\n // Set the new controller.\n controllerOf[_projectId] = _controller;\n\n emit SetController(_projectId, _controller, msg.sender);\n }\n\n /** \n @notice \n Set a project's terminals.\n\n @dev\n Only a project owner, an operator, or its controller can set its terminals.\n\n @param _projectId The ID of the project having terminals set.\n @param _terminals The terminal to set.\n */\n function setTerminalsOf(uint256 _projectId, IJBPaymentTerminal[] calldata _terminals)\n external\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.SET_TERMINALS,\n msg.sender == address(controllerOf[_projectId])\n )\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Setting terminals must be allowed if not called from the current controller.\n if (\n msg.sender != address(controllerOf[_projectId]) && !_fundingCycle.global().allowSetTerminals\n ) revert SET_TERMINALS_NOT_ALLOWED();\n\n // Set the stored terminals for the project.\n _terminalsOf[_projectId] = _terminals;\n\n // Make sure duplicates were not added.\n if (_terminals.length > 1) {\n for (uint256 _i; _i < _terminals.length; ) {\n for (uint256 _j = _i + 1; _j < _terminals.length; ) {\n if (_terminals[_i] == _terminals[_j]) revert DUPLICATE_TERMINALS();\n\n unchecked {\n ++_j;\n }\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n emit SetTerminals(_projectId, _terminals, msg.sender);\n }\n\n /**\n @notice\n Project's can set which terminal should be their primary for a particular token.\n This is useful in case a project has several terminals connected for a particular token.\n\n @dev\n The terminal will be set as the primary terminal where ecosystem contracts should route tokens.\n\n @dev\n If setting a newly added terminal and the funding cycle doesn't allow new terminals, the caller must be the current controller.\n\n @param _projectId The ID of the project for which a primary token is being set.\n @param _token The token to set the primary terminal of.\n @param _terminal The terminal to make primary.\n */\n function setPrimaryTerminalOf(\n uint256 _projectId,\n address _token,\n IJBPaymentTerminal _terminal\n )\n external\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.SET_PRIMARY_TERMINAL)\n {\n // Can't set the primary terminal for a token if it doesn't accept the token.\n if (!_terminal.acceptsToken(_token, _projectId)) revert TOKEN_NOT_ACCEPTED();\n\n // Add the terminal to the project if it hasn't been already.\n _addTerminalIfNeeded(_projectId, _terminal);\n\n // Store the terminal as the primary for the particular token.\n _primaryTerminalOf[_projectId][_token] = _terminal;\n\n emit SetPrimaryTerminal(_projectId, _token, _terminal, msg.sender);\n }\n\n /** \n @notice\t\n Set a contract to the list of trusted addresses that can set a first controller for any project.\t\n\n @dev\n The owner can add addresses which are allowed to change projects' first controllers. \n These addresses are known and vetted controllers as well as contracts designed to launch new projects. \n A project can set its own controller without it being on the allow list.\n\n @dev\n If you would like an address/contract allowlisted, please reach out to the contract owner.\n\n @param _address The address to allow or revoke allowance from.\n @param _flag Whether allowance is being added or revoked.\n */\n function setIsAllowedToSetFirstController(address _address, bool _flag)\n external\n override\n onlyOwner\n {\n // Set the flag in the allowlist.\n isAllowedToSetFirstController[_address] = _flag;\n\n emit SetIsAllowedToSetFirstController(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Add a terminal to a project's list of terminals if it hasn't been already.\n\n @param _projectId The ID of the project having a terminal added.\n @param _terminal The terminal to add.\n */\n function _addTerminalIfNeeded(uint256 _projectId, IJBPaymentTerminal _terminal) private {\n // Check that the terminal has not already been added.\n if (isTerminalOf(_projectId, _terminal)) return;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Setting terminals must be allowed if not called from the current controller.\n if (\n msg.sender != address(controllerOf[_projectId]) && !_fundingCycle.global().allowSetTerminals\n ) revert SET_TERMINALS_NOT_ALLOWED();\n\n // Add the new terminal.\n _terminalsOf[_projectId].push(_terminal);\n\n emit AddTerminal(_projectId, _terminal, msg.sender);\n }\n}\n" }, "contracts/JBETHPaymentTerminal.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\nimport './libraries/JBSplitsGroups.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return address(this).balance;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n JBTokens.ETH,\n 18, // 18 decimals.\n JBCurrencies.ETH,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\nimport './libraries/JBSplitsGroups.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return address(this).balance;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n JBTokens.GAS_TOKEN,\n 18, // 18 decimals.\n JBCurrencies.GAS_CURRENCY,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n}\n" }, "contracts/JBERC20PaymentTerminal.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\n\n/** \n @notice \n Manages the inflows and outflows of an ERC-20 token.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\ncontract JBERC20PaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return IERC20(token).balanceOf(address(this));\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n IERC20Metadata _token,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n address(_token),\n _token.decimals(),\n _currency,\n _baseWeightCurrency,\n _payoutSplitsGroup,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from == address(this)\n ? IERC20(token).safeTransfer(_to, _amount)\n : IERC20(token).safeTransferFrom(_from, _to, _amount);\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal override {\n IERC20(token).safeApprove(_to, _amount);\n }\n}\n" }, "contracts/JBSingleTokenPaymentTerminalStore.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController.sol';\nimport './interfaces/IJBFundingCycleDataSource.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './structs/JBPayDelegateAllocation.sol';\nimport './structs/JBPayParamsData.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBSingleTokenPaymentTerminalStore is ReentrancyGuard, IJBSingleTokenPaymentTerminalStore {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n JBPayDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .payParams(_data);\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\n {\n // Keep a reference to the amount that should be added to the project's balance.\n uint256 _balanceDiff = _amount.value;\n\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\n if (delegateAllocations.length != 0) {\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0) {\n // Can't delegate more than was paid.\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\n\n // Decrement the total amount being added to the balance.\n _balanceDiff = _balanceDiff - _delegatedAmount;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Add the correct balance difference to the token balance of the project.\n if (_balanceDiff != 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _balanceDiff;\n }\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\n _projectId,\n fundingCycle.reservedRate()\n );\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow != 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\n {\n // Get a reference to the ballot state.\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\n\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n _state == JBBallotState.Active\n ? fundingCycle.ballotRedemptionRate()\n : fundingCycle.redemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\n fundingCycle.dataSource()\n ).redeemParams(_data);\n }\n } else {\n memo = _memo;\n }\n }\n\n // Keep a reference to the amount that should be subtracted from the project's balance.\n uint256 _balanceDiff = reclaimAmount;\n\n if (delegateAllocations.length != 0) {\n // Validate all delegated amounts.\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0)\n // Increment the total amount being subtracted from the balance.\n _balanceDiff = _balanceDiff + _delegatedAmount;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (_balanceDiff != 0) {\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n _balanceDiff;\n }\n }\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n unchecked {\n return\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i; _i < _terminals.length; ) {\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n unchecked {\n ++_i;\n }\n }\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.ETH\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.ETH, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController.sol';\nimport './interfaces/IJBFundingCycleDataSource.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './structs/JBPayDelegateAllocation.sol';\nimport './structs/JBPayParamsData.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBSingleTokenPaymentTerminalStore is ReentrancyGuard, IJBSingleTokenPaymentTerminalStore {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n JBPayDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .payParams(_data);\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\n {\n // Keep a reference to the amount that should be added to the project's balance.\n uint256 _balanceDiff = _amount.value;\n\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\n if (delegateAllocations.length != 0) {\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0) {\n // Can't delegate more than was paid.\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\n\n // Decrement the total amount being added to the balance.\n _balanceDiff = _balanceDiff - _delegatedAmount;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Add the correct balance difference to the token balance of the project.\n if (_balanceDiff != 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _balanceDiff;\n }\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\n _projectId,\n fundingCycle.reservedRate()\n );\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow != 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\n {\n // Get a reference to the ballot state.\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\n\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n _state == JBBallotState.Active\n ? fundingCycle.ballotRedemptionRate()\n : fundingCycle.redemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\n fundingCycle.dataSource()\n ).redeemParams(_data);\n }\n } else {\n memo = _memo;\n }\n }\n\n // Keep a reference to the amount that should be subtracted from the project's balance.\n uint256 _balanceDiff = reclaimAmount;\n\n if (delegateAllocations.length != 0) {\n // Validate all delegated amounts.\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0)\n // Increment the total amount being subtracted from the balance.\n _balanceDiff = _balanceDiff + _delegatedAmount;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (_balanceDiff != 0) {\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n _balanceDiff;\n }\n }\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n unchecked {\n return\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i; _i < _terminals.length; ) {\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n unchecked {\n ++_i;\n }\n }\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.GAS_CURRENCY\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.GAS_CURRENCY, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" }, "contracts/JBFundingCycleStore.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './abstract/JBControllerUtility.sol';\nimport './libraries/JBConstants.sol';\n\n/** \n @notice \n Manages funding cycle configurations and scheduling.\n\n @dev\n Adheres to -\n IJBFundingCycleStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBControllerUtility: Includes convenience functionality for checking if the message sender is the current controller of the project whose data is being manipulated.\n*/\ncontract JBFundingCycleStore is JBControllerUtility, IJBFundingCycleStore {\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_BALLOT();\n error INVALID_DISCOUNT_RATE();\n error INVALID_DURATION();\n error INVALID_TIMEFRAME();\n error INVALID_WEIGHT();\n error NO_SAME_BLOCK_RECONFIGURATION();\n\n //*********************************************************************//\n // --------------------- private stored properties ------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Stores the user defined properties of each funding cycle, packed into one storage slot.\n\n _projectId The ID of the project to get properties of.\n _configuration The funding cycle configuration to get properties of.\n */\n mapping(uint256 => mapping(uint256 => uint256)) private _packedUserPropertiesOf;\n\n /** \n @notice\n Stores the properties added by the mechanism to manage and schedule each funding cycle, packed into one storage slot.\n \n _projectId The ID of the project to get instrinsic properties of.\n _configuration The funding cycle configuration to get properties of.\n */\n mapping(uint256 => mapping(uint256 => uint256)) private _packedIntrinsicPropertiesOf;\n\n /** \n @notice\n Stores the metadata for each funding cycle configuration, packed into one storage slot.\n\n _projectId The ID of the project to get metadata of.\n _configuration The funding cycle configuration to get metadata of.\n */\n mapping(uint256 => mapping(uint256 => uint256)) private _metadataOf;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The latest funding cycle configuration for each project.\n\n _projectId The ID of the project to get the latest funding cycle configuration of.\n */\n mapping(uint256 => uint256) public override latestConfigurationOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice \n Get the funding cycle with the given configuration for the specified project.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n @param _configuration The configuration of the funding cycle to get.\n\n @return fundingCycle The funding cycle.\n */\n function get(uint256 _projectId, uint256 _configuration)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle)\n {\n return _getStructFor(_projectId, _configuration);\n }\n\n /**\n @notice \n The latest funding cycle to be configured for the specified project, and its current ballot state.\n\n @param _projectId The ID of the project to get the latest configured funding cycle of.\n\n @return fundingCycle The project's queued funding cycle.\n @return ballotState The state of the ballot for the reconfiguration.\n */\n function latestConfiguredOf(uint256 _projectId)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle, JBBallotState ballotState)\n {\n // Get a reference to the latest funding cycle configuration.\n uint256 _fundingCycleConfiguration = latestConfigurationOf[_projectId];\n\n // Resolve the funding cycle for the latest configuration.\n fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n // Resolve the ballot state.\n ballotState = _ballotStateOf(\n _projectId,\n fundingCycle.configuration,\n fundingCycle.start,\n fundingCycle.basedOn\n );\n }\n\n /**\n @notice \n The funding cycle that's next up for the specified project.\n\n @dev\n If a queued funding cycle of the project is not found, returns an empty funding cycle with all properties set to 0.\n\n @param _projectId The ID of the project to get the queued funding cycle of.\n\n @return fundingCycle The project's queued funding cycle.\n */\n function queuedOf(uint256 _projectId)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle)\n {\n // If the project does not have a funding cycle, return an empty struct.\n if (latestConfigurationOf[_projectId] == 0) return _getStructFor(0, 0);\n\n // Get a reference to the configuration of the standby funding cycle.\n uint256 _standbyFundingCycleConfiguration = _standbyOf(_projectId);\n\n // If it exists, return its funding cycle if it is approved.\n if (_standbyFundingCycleConfiguration > 0) {\n fundingCycle = _getStructFor(_projectId, _standbyFundingCycleConfiguration);\n\n if (_isApproved(_projectId, fundingCycle)) return fundingCycle;\n\n // Resolve the funding cycle for the latest configured funding cycle.\n fundingCycle = _getStructFor(_projectId, fundingCycle.basedOn);\n } else {\n // Resolve the funding cycle for the latest configured funding cycle.\n fundingCycle = _getStructFor(_projectId, latestConfigurationOf[_projectId]);\n\n // If the latest funding cycle starts in the future, it must start in the distant future\n // since its not in standby. In this case base the queued cycles on the base cycle.\n if (fundingCycle.start > block.timestamp)\n fundingCycle = _getStructFor(_projectId, fundingCycle.basedOn);\n }\n\n // There's no queued if the current has a duration of 0.\n if (fundingCycle.duration == 0) return _getStructFor(0, 0);\n\n // Check to see if this funding cycle's ballot is approved.\n // If so, return a funding cycle based on it.\n if (_isApproved(_projectId, fundingCycle)) return _mockFundingCycleBasedOn(fundingCycle, false);\n\n // Get the funding cycle of its base funding cycle, which carries the last approved configuration.\n fundingCycle = _getStructFor(_projectId, fundingCycle.basedOn);\n\n // There's no queued if the base, which must still be the current, has a duration of 0.\n if (fundingCycle.duration == 0) return _getStructFor(0, 0);\n\n // Return a mock of the next up funding cycle.\n return _mockFundingCycleBasedOn(fundingCycle, false);\n }\n\n /**\n @notice \n The funding cycle that is currently active for the specified project.\n\n @dev\n If a current funding cycle of the project is not found, returns an empty funding cycle with all properties set to 0.\n\n @param _projectId The ID of the project to get the current funding cycle of.\n\n @return fundingCycle The project's current funding cycle.\n */\n function currentOf(uint256 _projectId)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle)\n {\n // If the project does not have a funding cycle, return an empty struct.\n if (latestConfigurationOf[_projectId] == 0) return _getStructFor(0, 0);\n\n // Get a reference to the configuration of the eligible funding cycle.\n uint256 _fundingCycleConfiguration = _eligibleOf(_projectId);\n\n // Keep a reference to the eligible funding cycle.\n JBFundingCycle memory _fundingCycle;\n\n // If an eligible funding cycle exists...\n if (_fundingCycleConfiguration > 0) {\n // Resolve the funding cycle for the eligible configuration.\n _fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n // Check to see if this funding cycle's ballot is approved.\n // If so, return it.\n if (_isApproved(_projectId, _fundingCycle)) return _fundingCycle;\n\n // If it hasn't been approved, set the funding cycle configuration to be the configuration of the funding cycle that it's based on,\n // which carries the last approved configuration.\n _fundingCycleConfiguration = _fundingCycle.basedOn;\n } else {\n // No upcoming funding cycle found that is eligible to become active,\n // so use the last configuration.\n _fundingCycleConfiguration = latestConfigurationOf[_projectId];\n\n // Get the funding cycle for the latest ID.\n _fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n // If it's not approved or if it hasn't yet started, get a reference to the funding cycle that the latest is based on, which has the latest approved configuration.\n if (!_isApproved(_projectId, _fundingCycle) || block.timestamp < _fundingCycle.start)\n _fundingCycleConfiguration = _fundingCycle.basedOn;\n }\n\n // If there is not funding cycle to base the current one on, there can't be a current one.\n if (_fundingCycleConfiguration == 0) return _getStructFor(0, 0);\n\n // The funding cycle to base a current one on.\n _fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n // If the base has no duration, it's still the current one.\n if (_fundingCycle.duration == 0) return _fundingCycle;\n\n // Return a mock of the current funding cycle.\n return _mockFundingCycleBasedOn(_fundingCycle, true);\n }\n\n /** \n @notice \n The current ballot state of the project.\n\n @param _projectId The ID of the project to check the ballot state of.\n\n @return The project's current ballot's state.\n */\n function currentBallotStateOf(uint256 _projectId) external view override returns (JBBallotState) {\n // Get a reference to the latest funding cycle configuration.\n uint256 _fundingCycleConfiguration = latestConfigurationOf[_projectId];\n\n // Resolve the funding cycle for the latest configuration.\n JBFundingCycle memory _fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n return\n _ballotStateOf(\n _projectId,\n _fundingCycle.configuration,\n _fundingCycle.start,\n _fundingCycle.basedOn\n );\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _directory A contract storing directories of terminals and controllers for each project.\n */\n // solhint-disable-next-line no-empty-blocks\n constructor(IJBDirectory _directory) JBControllerUtility(_directory) {}\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice \n Configures the next eligible funding cycle for the specified project.\n\n @dev\n Only a project's current controller can configure its funding cycles.\n\n @param _projectId The ID of the project being configured.\n @param _data The funding cycle configuration data.\n @param _metadata Arbitrary extra data to associate with this funding cycle configuration that's not used within.\n @param _mustStartAtOrAfter The time before which the initialized funding cycle cannot start.\n\n @return The funding cycle that the configuration will take effect during.\n */\n function configureFor(\n uint256 _projectId,\n JBFundingCycleData calldata _data,\n uint256 _metadata,\n uint256 _mustStartAtOrAfter\n ) external override onlyController(_projectId) returns (JBFundingCycle memory) {\n // Duration must fit in a uint32.\n if (_data.duration > type(uint32).max) revert INVALID_DURATION();\n\n // Discount rate must be less than or equal to 100%.\n if (_data.discountRate > JBConstants.MAX_DISCOUNT_RATE) revert INVALID_DISCOUNT_RATE();\n\n // Weight must fit into a uint88.\n if (_data.weight > type(uint88).max) revert INVALID_WEIGHT();\n\n // If the start date is in the past, set it to be the current timestamp.\n if (_mustStartAtOrAfter < block.timestamp) _mustStartAtOrAfter = block.timestamp;\n\n // Make sure the min start date fits in a uint56, and that the start date of an upcoming cycle also starts within the max.\n if (_mustStartAtOrAfter + _data.duration > type(uint56).max) revert INVALID_TIMEFRAME();\n\n // Ballot should be a valid contract, supporting the correct interface\n if (_data.ballot != IJBFundingCycleBallot(address(0))) {\n address _ballot = address(_data.ballot);\n\n // No contract at the address ?\n if (_ballot.code.length == 0) revert INVALID_BALLOT();\n\n // Make sure the ballot supports the expected interface.\n try _data.ballot.supportsInterface(type(IJBFundingCycleBallot).interfaceId) returns (\n bool _supports\n ) {\n if (!_supports) revert INVALID_BALLOT(); // Contract exists at the address but with the wrong interface\n } catch {\n revert INVALID_BALLOT(); // No ERC165 support\n }\n }\n\n // The configuration timestamp is now.\n uint256 _configuration = block.timestamp;\n\n // Set up a reconfiguration by configuring intrinsic properties.\n _configureIntrinsicPropertiesFor(_projectId, _configuration, _data.weight, _mustStartAtOrAfter);\n\n // Efficiently stores a funding cycles provided user defined properties.\n // If all user config properties are zero, no need to store anything as the default value will have the same outcome.\n if (\n _data.ballot != IJBFundingCycleBallot(address(0)) ||\n _data.duration > 0 ||\n _data.discountRate > 0\n ) {\n // ballot in bits 0-159 bytes.\n uint256 packed = uint160(address(_data.ballot));\n\n // duration in bits 160-191 bytes.\n packed |= _data.duration << 160;\n\n // discountRate in bits 192-223 bytes.\n packed |= _data.discountRate << 192;\n\n // Set in storage.\n _packedUserPropertiesOf[_projectId][_configuration] = packed;\n }\n\n // Set the metadata if needed.\n if (_metadata > 0) _metadataOf[_projectId][_configuration] = _metadata;\n\n emit Configure(_configuration, _projectId, _data, _metadata, _mustStartAtOrAfter, msg.sender);\n\n // Return the funding cycle for the new configuration.\n return _getStructFor(_projectId, _configuration);\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice \n Updates the configurable funding cycle for this project if it exists, otherwise creates one.\n\n @param _projectId The ID of the project to find a configurable funding cycle for.\n @param _configuration The time at which the funding cycle was configured.\n @param _weight The weight to store in the configured funding cycle.\n @param _mustStartAtOrAfter The time before which the initialized funding cycle can't start.\n */\n function _configureIntrinsicPropertiesFor(\n uint256 _projectId,\n uint256 _configuration,\n uint256 _weight,\n uint256 _mustStartAtOrAfter\n ) private {\n // If there's not yet a funding cycle for the project, initialize one.\n if (latestConfigurationOf[_projectId] == 0)\n // Use an empty funding cycle as the base.\n return\n _initFor(_projectId, _getStructFor(0, 0), _configuration, _mustStartAtOrAfter, _weight);\n\n // Get the active funding cycle's configuration.\n uint256 _currentConfiguration = _eligibleOf(_projectId);\n\n // If an eligible funding cycle does not exist, get a reference to the latest funding cycle configuration for the project.\n if (_currentConfiguration == 0)\n // Get the latest funding cycle's configuration.\n _currentConfiguration = latestConfigurationOf[_projectId];\n\n // Get a reference to the funding cycle.\n JBFundingCycle memory _baseFundingCycle = _getStructFor(_projectId, _currentConfiguration);\n\n if (!_isApproved(_projectId, _baseFundingCycle) || block.timestamp < _baseFundingCycle.start)\n // If it hasn't been approved or hasn't yet started, set the ID to be the funding cycle it's based on,\n // which carries the latest approved configuration.\n _baseFundingCycle = _getStructFor(_projectId, _baseFundingCycle.basedOn);\n\n // The configuration can't be the same as the base configuration.\n if (_baseFundingCycle.configuration == _configuration) revert NO_SAME_BLOCK_RECONFIGURATION();\n\n // The time after the ballot of the provided funding cycle has expired.\n // If the provided funding cycle has no ballot, return the current timestamp.\n uint256 _timestampAfterBallot = _baseFundingCycle.ballot == IJBFundingCycleBallot(address(0))\n ? 0\n : _configuration + _baseFundingCycle.ballot.duration();\n\n _initFor(\n _projectId,\n _baseFundingCycle,\n _configuration,\n // Can only start after the ballot.\n _timestampAfterBallot > _mustStartAtOrAfter ? _timestampAfterBallot : _mustStartAtOrAfter,\n _weight\n );\n }\n\n /**\n @notice \n Initializes a funding cycle with the specified properties.\n\n @param _projectId The ID of the project to which the funding cycle being initialized belongs.\n @param _baseFundingCycle The funding cycle to base the initialized one on.\n @param _configuration The configuration of the funding cycle being initialized.\n @param _mustStartAtOrAfter The time before which the initialized funding cycle cannot start.\n @param _weight The weight to give the newly initialized funding cycle.\n */\n function _initFor(\n uint256 _projectId,\n JBFundingCycle memory _baseFundingCycle,\n uint256 _configuration,\n uint256 _mustStartAtOrAfter,\n uint256 _weight\n ) private {\n // If there is no base, initialize a first cycle.\n if (_baseFundingCycle.number == 0) {\n // The first number is 1.\n uint256 _number = 1;\n\n // Set fresh intrinsic properties.\n _packAndStoreIntrinsicPropertiesOf(\n _configuration,\n _projectId,\n _number,\n _weight,\n _baseFundingCycle.configuration,\n _mustStartAtOrAfter\n );\n } else {\n // Derive the correct next start time from the base.\n uint256 _start = _deriveStartFrom(_baseFundingCycle, _mustStartAtOrAfter);\n\n // A weight of 1 is treated as a weight of 0.\n // This is to allow a weight of 0 (default) to represent inheriting the discounted weight of the previous funding cycle.\n _weight = _weight > 0\n ? (_weight == 1 ? 0 : _weight)\n : _deriveWeightFrom(_baseFundingCycle, _start);\n\n // Derive the correct number.\n uint256 _number = _deriveNumberFrom(_baseFundingCycle, _start);\n\n // Update the intrinsic properties.\n _packAndStoreIntrinsicPropertiesOf(\n _configuration,\n _projectId,\n _number,\n _weight,\n _baseFundingCycle.configuration,\n _start\n );\n }\n\n // Set the project's latest funding cycle configuration.\n latestConfigurationOf[_projectId] = _configuration;\n\n emit Init(_configuration, _projectId, _baseFundingCycle.configuration);\n }\n\n /**\n @notice \n Efficiently stores a funding cycle's provided intrinsic properties.\n\n @param _configuration The configuration of the funding cycle to pack and store.\n @param _projectId The ID of the project to which the funding cycle belongs.\n @param _number The number of the funding cycle.\n @param _weight The weight of the funding cycle.\n @param _basedOn The configuration of the base funding cycle.\n @param _start The start time of this funding cycle.\n */\n function _packAndStoreIntrinsicPropertiesOf(\n uint256 _configuration,\n uint256 _projectId,\n uint256 _number,\n uint256 _weight,\n uint256 _basedOn,\n uint256 _start\n ) private {\n // weight in bits 0-87.\n uint256 packed = _weight;\n\n // basedOn in bits 88-143.\n packed |= _basedOn << 88;\n\n // start in bits 144-199.\n packed |= _start << 144;\n\n // number in bits 200-255.\n packed |= _number << 200;\n\n // Store the packed value.\n _packedIntrinsicPropertiesOf[_projectId][_configuration] = packed;\n }\n\n /**\n @notice \n The project's stored funding cycle that hasn't yet started and should be used next, if one exists.\n\n @dev\n A value of 0 is returned if no funding cycle was found.\n\n @dev\n Assumes the project has a latest configuration.\n \n @param _projectId The ID of a project to look through for a standby cycle.\n\n @return configuration The configuration of the standby funding cycle if one exists, or 0 if one doesn't exist.\n */\n function _standbyOf(uint256 _projectId) private view returns (uint256 configuration) {\n // Get a reference to the project's latest funding cycle.\n configuration = latestConfigurationOf[_projectId];\n\n // Get the necessary properties for the latest funding cycle.\n JBFundingCycle memory _fundingCycle = _getStructFor(_projectId, configuration);\n\n // There is no upcoming funding cycle if the latest funding cycle has already started.\n if (block.timestamp >= _fundingCycle.start) return 0;\n\n // If this is the first funding cycle, it is queued.\n if (_fundingCycle.number == 1) return configuration;\n\n // Get the necessary properties for the base funding cycle.\n JBFundingCycle memory _baseFundingCycle = _getStructFor(_projectId, _fundingCycle.basedOn);\n\n // If the latest configuration doesn't start until after another base cycle, return 0.\n if (\n _baseFundingCycle.duration > 0 &&\n block.timestamp < _fundingCycle.start - _baseFundingCycle.duration\n ) return 0;\n }\n\n /**\n @notice \n The project's stored funding cycle that has started and hasn't yet expired.\n \n @dev\n A value of 0 is returned if no funding cycle was found.\n\n @dev\n Assumes the project has a latest configuration.\n\n @param _projectId The ID of the project to look through.\n\n @return configuration The configuration of an eligible funding cycle if one exists, or 0 if one doesn't exist.\n */\n function _eligibleOf(uint256 _projectId) private view returns (uint256 configuration) {\n // Get a reference to the project's latest funding cycle.\n configuration = latestConfigurationOf[_projectId];\n\n // Get the latest funding cycle.\n JBFundingCycle memory _fundingCycle = _getStructFor(_projectId, configuration);\n\n // If the latest is expired, return an empty funding cycle.\n // A duration of 0 cannot be expired.\n if (\n _fundingCycle.duration > 0 && block.timestamp >= _fundingCycle.start + _fundingCycle.duration\n ) return 0;\n\n // Return the funding cycle's configuration if it has started.\n if (block.timestamp >= _fundingCycle.start) return _fundingCycle.configuration;\n\n // Get a reference to the cycle's base configuration.\n JBFundingCycle memory _baseFundingCycle = _getStructFor(_projectId, _fundingCycle.basedOn);\n\n // If the base cycle isn't eligible, the project has no eligible cycle.\n // A duration of 0 is always eligible.\n if (\n _baseFundingCycle.duration > 0 &&\n block.timestamp >= _baseFundingCycle.start + _baseFundingCycle.duration\n ) return 0;\n\n // Return the configuration that the latest funding cycle is based on.\n configuration = _fundingCycle.basedOn;\n }\n\n /** \n @notice \n A view of the funding cycle that would be created based on the provided one if the project doesn't make a reconfiguration.\n\n @dev\n Returns an empty funding cycle if there can't be a mock funding cycle based on the provided one.\n\n @dev\n Assumes a funding cycle with a duration of 0 will never be asked to be the base of a mock.\n\n @param _baseFundingCycle The funding cycle that the resulting funding cycle should follow.\n @param _allowMidCycle A flag indicating if the mocked funding cycle is allowed to already be mid cycle.\n\n @return A mock of what the next funding cycle will be.\n */\n function _mockFundingCycleBasedOn(JBFundingCycle memory _baseFundingCycle, bool _allowMidCycle)\n private\n view\n returns (JBFundingCycle memory)\n {\n // Get the distance of the current time to the start of the next possible funding cycle.\n // If the returned mock cycle must not yet have started, the start time of the mock must be in the future.\n uint256 _mustStartAtOrAfter = !_allowMidCycle\n ? block.timestamp + 1\n : block.timestamp - _baseFundingCycle.duration + 1;\n\n // Derive what the start time should be.\n uint256 _start = _deriveStartFrom(_baseFundingCycle, _mustStartAtOrAfter);\n\n // Derive what the number should be.\n uint256 _number = _deriveNumberFrom(_baseFundingCycle, _start);\n\n return\n JBFundingCycle(\n _number,\n _baseFundingCycle.configuration,\n _baseFundingCycle.basedOn,\n _start,\n _baseFundingCycle.duration,\n _deriveWeightFrom(_baseFundingCycle, _start),\n _baseFundingCycle.discountRate,\n _baseFundingCycle.ballot,\n _baseFundingCycle.metadata\n );\n }\n\n /** \n @notice \n The date that is the nearest multiple of the specified funding cycle's duration from its end.\n\n @param _baseFundingCycle The funding cycle to base the calculation on.\n @param _mustStartAtOrAfter A date that the derived start must be on or come after.\n\n @return start The next start time.\n */\n function _deriveStartFrom(JBFundingCycle memory _baseFundingCycle, uint256 _mustStartAtOrAfter)\n private\n pure\n returns (uint256 start)\n {\n // A subsequent cycle to one with a duration of 0 should start as soon as possible.\n if (_baseFundingCycle.duration == 0) return _mustStartAtOrAfter;\n\n // The time when the funding cycle immediately after the specified funding cycle starts.\n uint256 _nextImmediateStart = _baseFundingCycle.start + _baseFundingCycle.duration;\n\n // If the next immediate start is now or in the future, return it.\n if (_nextImmediateStart >= _mustStartAtOrAfter) return _nextImmediateStart;\n\n // The amount of seconds since the `_mustStartAtOrAfter` time which results in a start time that might satisfy the specified constraints.\n uint256 _timeFromImmediateStartMultiple = (_mustStartAtOrAfter - _nextImmediateStart) %\n _baseFundingCycle.duration;\n\n // A reference to the first possible start timestamp.\n start = _mustStartAtOrAfter - _timeFromImmediateStartMultiple;\n\n // Add increments of duration as necessary to satisfy the threshold.\n while (_mustStartAtOrAfter > start) start = start + _baseFundingCycle.duration;\n }\n\n /** \n @notice \n The accumulated weight change since the specified funding cycle.\n\n @param _baseFundingCycle The funding cycle to base the calculation on.\n @param _start The start time of the funding cycle to derive a number for.\n\n @return weight The derived weight, as a fixed point number with 18 decimals.\n */\n function _deriveWeightFrom(JBFundingCycle memory _baseFundingCycle, uint256 _start)\n private\n pure\n returns (uint256 weight)\n {\n // A subsequent cycle to one with a duration of 0 should have the next possible weight.\n if (_baseFundingCycle.duration == 0)\n return\n PRBMath.mulDiv(\n _baseFundingCycle.weight,\n JBConstants.MAX_DISCOUNT_RATE - _baseFundingCycle.discountRate,\n JBConstants.MAX_DISCOUNT_RATE\n );\n\n // The weight should be based off the base funding cycle's weight.\n weight = _baseFundingCycle.weight;\n\n // If the discount is 0, the weight doesn't change.\n if (_baseFundingCycle.discountRate == 0) return weight;\n\n // The difference between the start of the base funding cycle and the proposed start.\n uint256 _startDistance = _start - _baseFundingCycle.start;\n\n // Apply the base funding cycle's discount rate for each cycle that has passed.\n uint256 _discountMultiple;\n unchecked {\n _discountMultiple = _startDistance / _baseFundingCycle.duration; // Non-null duration is excluded above\n }\n\n for (uint256 _i; _i < _discountMultiple; ) {\n // The number of times to apply the discount rate.\n // Base the new weight on the specified funding cycle's weight.\n weight = PRBMath.mulDiv(\n weight,\n JBConstants.MAX_DISCOUNT_RATE - _baseFundingCycle.discountRate,\n JBConstants.MAX_DISCOUNT_RATE\n );\n\n // The calculation doesn't need to continue if the weight is 0.\n if (weight == 0) break;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /** \n @notice \n The number of the next funding cycle given the specified funding cycle.\n\n @param _baseFundingCycle The funding cycle to base the calculation on.\n @param _start The start time of the funding cycle to derive a number for.\n\n @return The funding cycle number.\n */\n function _deriveNumberFrom(JBFundingCycle memory _baseFundingCycle, uint256 _start)\n private\n pure\n returns (uint256)\n {\n // A subsequent cycle to one with a duration of 0 should be the next number.\n if (_baseFundingCycle.duration == 0) return _baseFundingCycle.number + 1;\n\n // The difference between the start of the base funding cycle and the proposed start.\n uint256 _startDistance = _start - _baseFundingCycle.start;\n\n // Find the number of base cycles that fit in the start distance.\n return _baseFundingCycle.number + (_startDistance / _baseFundingCycle.duration);\n }\n\n /** \n @notice \n Checks to see if the provided funding cycle is approved according to the correct ballot.\n\n @param _projectId The ID of the project to which the funding cycle belongs. \n @param _fundingCycle The funding cycle to get an approval flag for.\n\n @return The approval flag.\n */\n function _isApproved(uint256 _projectId, JBFundingCycle memory _fundingCycle)\n private\n view\n returns (bool)\n {\n return\n _ballotStateOf(\n _projectId,\n _fundingCycle.configuration,\n _fundingCycle.start,\n _fundingCycle.basedOn\n ) == JBBallotState.Approved;\n }\n\n /**\n @notice \n A project's latest funding cycle configuration approval status.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n @param _configuration The funding cycle configuration to get the ballot state of.\n @param _start The start time of the funding cycle configuration to get the ballot state of.\n @param _ballotFundingCycleConfiguration The configuration of the funding cycle which is configured with the ballot that should be used.\n\n @return The ballot state of the project.\n */\n function _ballotStateOf(\n uint256 _projectId,\n uint256 _configuration,\n uint256 _start,\n uint256 _ballotFundingCycleConfiguration\n ) private view returns (JBBallotState) {\n // If there is no ballot funding cycle, implicitly approve.\n if (_ballotFundingCycleConfiguration == 0) return JBBallotState.Approved;\n\n // Get the ballot funding cycle.\n JBFundingCycle memory _ballotFundingCycle = _getStructFor(\n _projectId,\n _ballotFundingCycleConfiguration\n );\n\n // If there is no ballot, the ID is auto approved.\n if (_ballotFundingCycle.ballot == IJBFundingCycleBallot(address(0)))\n return JBBallotState.Approved;\n\n // Return the ballot's state\n return _ballotFundingCycle.ballot.stateOf(_projectId, _configuration, _start);\n }\n\n /**\n @notice \n Unpack a funding cycle's packed stored values into an easy-to-work-with funding cycle struct.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n @param _configuration The funding cycle configuration to get the full struct for.\n\n @return fundingCycle A funding cycle struct.\n */\n function _getStructFor(uint256 _projectId, uint256 _configuration)\n private\n view\n returns (JBFundingCycle memory fundingCycle)\n {\n // Return an empty funding cycle if the configuration specified is 0.\n if (_configuration == 0) return fundingCycle;\n\n fundingCycle.configuration = _configuration;\n\n uint256 _packedIntrinsicProperties = _packedIntrinsicPropertiesOf[_projectId][_configuration];\n\n // weight in bits 0-87 bits.\n fundingCycle.weight = uint256(uint88(_packedIntrinsicProperties));\n // basedOn in bits 88-143 bits.\n fundingCycle.basedOn = uint256(uint56(_packedIntrinsicProperties >> 88));\n // start in bits 144-199 bits.\n fundingCycle.start = uint256(uint56(_packedIntrinsicProperties >> 144));\n // number in bits 200-255 bits.\n fundingCycle.number = uint256(uint56(_packedIntrinsicProperties >> 200));\n\n uint256 _packedUserProperties = _packedUserPropertiesOf[_projectId][_configuration];\n\n // ballot in bits 0-159 bits.\n fundingCycle.ballot = IJBFundingCycleBallot(address(uint160(_packedUserProperties)));\n // duration in bits 160-191 bits.\n fundingCycle.duration = uint256(uint32(_packedUserProperties >> 160));\n // discountRate in bits 192-223 bits.\n fundingCycle.discountRate = uint256(uint32(_packedUserProperties >> 192));\n\n fundingCycle.metadata = _metadataOf[_projectId][_configuration];\n }\n}\n" @@ -194,7 +194,7 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './../interfaces/IJBSplitAllocator.sol';\n\n/** \n @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.\n @member preferAddToBalance A flag indicating if a distribution to a project should prefer triggering it's addToBalance function instead of its pay function.\n @member percent The percent of the whole group that this split occupies. This number is out of `JBConstants.SPLITS_TOTAL_PERCENT`.\n @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.\n @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.\n @member lockedUntil Specifies if the split should be unchangeable until the specified time, with the exception of extending the locked period.\n @member allocator If an allocator is specified, funds will be sent to the allocator contract along with all properties of this split.\n*/\nstruct JBSplit {\n bool preferClaimed;\n bool preferAddToBalance;\n uint256 percent;\n uint256 projectId;\n address payable beneficiary;\n uint256 lockedUntil;\n IJBSplitAllocator allocator;\n}\n" }, "contracts/system_tests/helpers/AccessJBLib.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.6;\n\nimport '../../libraries/JBCurrencies.sol';\nimport '../../libraries/JBConstants.sol';\nimport '../../libraries/JBTokens.sol';\n\ncontract AccessJBLib {\n function ETH() external pure returns (uint256) {\n return JBCurrencies.ETH;\n }\n\n function USD() external pure returns (uint256) {\n return JBCurrencies.USD;\n }\n\n function ETHToken() external pure returns (address) {\n return JBTokens.ETH;\n }\n\n function MAX_FEE() external pure returns (uint256) {\n return JBConstants.MAX_FEE;\n }\n\n function MAX_RESERVED_RATE() external pure returns (uint256) {\n return JBConstants.MAX_RESERVED_RATE;\n }\n\n function MAX_REDEMPTION_RATE() external pure returns (uint256) {\n return JBConstants.MAX_REDEMPTION_RATE;\n }\n\n function MAX_DISCOUNT_RATE() external pure returns (uint256) {\n return JBConstants.MAX_DISCOUNT_RATE;\n }\n\n function SPLITS_TOTAL_PERCENT() external pure returns (uint256) {\n return JBConstants.SPLITS_TOTAL_PERCENT;\n }\n\n function MAX_FEE_DISCOUNT() external pure returns (uint256) {\n return JBConstants.MAX_FEE_DISCOUNT;\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.6;\n\nimport '../../libraries/JBCurrencies.sol';\nimport '../../libraries/JBConstants.sol';\nimport '../../libraries/JBTokens.sol';\n\ncontract AccessJBLib {\n function ETH() external pure returns (uint256) {\n return JBCurrencies.GAS_CURRENCY;\n }\n\n function USD() external pure returns (uint256) {\n return JBCurrencies.USD;\n }\n\n function ETHToken() external pure returns (address) {\n return JBTokens.GAS_TOKEN;\n }\n\n function MAX_FEE() external pure returns (uint256) {\n return JBConstants.MAX_FEE;\n }\n\n function MAX_RESERVED_RATE() external pure returns (uint256) {\n return JBConstants.MAX_RESERVED_RATE;\n }\n\n function MAX_REDEMPTION_RATE() external pure returns (uint256) {\n return JBConstants.MAX_REDEMPTION_RATE;\n }\n\n function MAX_DISCOUNT_RATE() external pure returns (uint256) {\n return JBConstants.MAX_DISCOUNT_RATE;\n }\n\n function SPLITS_TOTAL_PERCENT() external pure returns (uint256) {\n return JBConstants.SPLITS_TOTAL_PERCENT;\n }\n\n function MAX_FEE_DISCOUNT() external pure returns (uint256) {\n return JBConstants.MAX_FEE_DISCOUNT;\n }\n}\n" }, "@paulrberg/contracts/math/PRBMath.sol": { "content": "// SPDX-License-Identifier: Unlicense\npragma solidity >=0.8.4;\n\nimport \"prb-math/contracts/PRBMath.sol\";\n" @@ -227,7 +227,7 @@ "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" }, "contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBPayDelegateAllocation.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal is\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n IJBPayoutRedemptionPaymentTerminal\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n @dev\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.ETH)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.ETH, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance.\n */\n function _balance() internal view virtual returns (uint256);\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.ETH) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual {\n _from; // Prevents unused var compiler and natspec complaints.\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\n {\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\n\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _forwardedAmount,\n _beneficiary,\n _memo,\n _metadata\n );\n\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\n\n emit DelegateDidRedeem(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n }\n\n // Take the fee.\n _fee = _feeEligibleDistributionAmount != 0\n ? _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n )\n : 0;\n\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\n if (_leftoverDistributionAmount != 0) {\n // Subtract the fee from the net leftover amount.\n netLeftoverDistributionAmount =\n _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n\n // Transfer the amount to the project owner.\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n // The total percentage available to split\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = _split.percent == leftoverPercentage\n ? leftoverAmount\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\n\n // Decrement the leftover percentage.\n leftoverPercentage -= _split.percent;\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount;\n\n if (_payoutAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\n isFeelessAddress[address(_split.allocator)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n _netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n // If this terminal's token is ETH, send it in msg.value.\n _split.allocator.allocate{value: token == JBTokens.ETH ? _netPayoutAmount : 0}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // Save gas if this contract is being used as the terminal.\n if (_terminal == this) {\n // This distribution does not incur a fee.\n _netPayoutAmount = _payoutAmount;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\n else\n _pay(\n _netPayoutAmount,\n address(this),\n _split.projectId,\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n } else {\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_terminal)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _netPayoutAmount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _terminal.addToBalanceOf{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n '',\n _projectMetadata\n );\n else\n _terminal.pay{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n }\n } else {\n // Keep a reference to the beneficiary.\n address payable _beneficiary = _split.beneficiary != address(0)\n ? _split.beneficiary\n : payable(msg.sender);\n\n // If there's a full discount, this distribution is not eligible for a fee.\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(address(this), _beneficiary, _netPayoutAmount);\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n */\n function _processFee(uint256 _amount, address _beneficiary) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\n\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\n if (_terminal == this)\n _pay(\n _amount,\n address(this),\n _FEE_BENEFICIARY_PROJECT_ID,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the local pay call.\n else {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _amount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _amount : 0;\n\n // Send the payment.\n _terminal.pay{value: _payableValue}(\n _FEE_BENEFICIARY_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the external pay call of the correct terminal.\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\n {\n JBPayDelegateAllocation[] memory _delegateAllocations;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n _forwardedAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n // Get a reference to the number of delegates to allocate to.\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\n\n emit DelegateDidPay(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n unchecked {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\n IJBPaymentTerminal(address(0))\n ) return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge != IJBFeeGauge(address(0)))\n // If the guage reverts, keep the discount at 0.\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n // If the fee discount is greater than the max, we ignore the return value\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\n } catch {\n return 0;\n }\n\n return 0;\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBPayDelegateAllocation.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal is\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n IJBPayoutRedemptionPaymentTerminal\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n @dev\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.GAS_CURRENCY)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.GAS_CURRENCY, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance.\n */\n function _balance() internal view virtual returns (uint256);\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.GAS_TOKEN) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual {\n _from; // Prevents unused var compiler and natspec complaints.\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\n {\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\n\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _forwardedAmount,\n _beneficiary,\n _memo,\n _metadata\n );\n\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\n\n emit DelegateDidRedeem(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n }\n\n // Take the fee.\n _fee = _feeEligibleDistributionAmount != 0\n ? _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n )\n : 0;\n\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\n if (_leftoverDistributionAmount != 0) {\n // Subtract the fee from the net leftover amount.\n netLeftoverDistributionAmount =\n _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n\n // Transfer the amount to the project owner.\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n // The total percentage available to split\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = _split.percent == leftoverPercentage\n ? leftoverAmount\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\n\n // Decrement the leftover percentage.\n leftoverPercentage -= _split.percent;\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount;\n\n if (_payoutAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\n isFeelessAddress[address(_split.allocator)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n _netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n // If this terminal's token is ETH, send it in msg.value.\n _split.allocator.allocate{value: token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // Save gas if this contract is being used as the terminal.\n if (_terminal == this) {\n // This distribution does not incur a fee.\n _netPayoutAmount = _payoutAmount;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\n else\n _pay(\n _netPayoutAmount,\n address(this),\n _split.projectId,\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n } else {\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_terminal)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _terminal.addToBalanceOf{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n '',\n _projectMetadata\n );\n else\n _terminal.pay{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n }\n } else {\n // Keep a reference to the beneficiary.\n address payable _beneficiary = _split.beneficiary != address(0)\n ? _split.beneficiary\n : payable(msg.sender);\n\n // If there's a full discount, this distribution is not eligible for a fee.\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(address(this), _beneficiary, _netPayoutAmount);\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n */\n function _processFee(uint256 _amount, address _beneficiary) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\n\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\n if (_terminal == this)\n _pay(\n _amount,\n address(this),\n _FEE_BENEFICIARY_PROJECT_ID,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the local pay call.\n else {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _amount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send the payment.\n _terminal.pay{value: _payableValue}(\n _FEE_BENEFICIARY_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the external pay call of the correct terminal.\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\n {\n JBPayDelegateAllocation[] memory _delegateAllocations;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n _forwardedAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n // Get a reference to the number of delegates to allocate to.\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\n\n emit DelegateDidPay(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n unchecked {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\n IJBPaymentTerminal(address(0))\n ) return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge != IJBFeeGauge(address(0)))\n // If the guage reverts, keep the discount at 0.\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n // If the fee discount is greater than the max, we ignore the return value\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\n } catch {\n return 0;\n }\n\n return 0;\n }\n}\n" }, "contracts/interfaces/IJBPayoutRedemptionPaymentTerminal.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './../structs/JBFee.sol';\nimport './IJBAllowanceTerminal.sol';\nimport './IJBDirectory.sol';\nimport './IJBFeeGauge.sol';\nimport './IJBPayDelegate.sol';\nimport './IJBPaymentTerminal.sol';\nimport './IJBPayoutTerminal.sol';\nimport './IJBPrices.sol';\nimport './IJBProjects.sol';\nimport './IJBRedemptionDelegate.sol';\nimport './IJBRedemptionTerminal.sol';\nimport './IJBSingleTokenPaymentTerminalStore.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBPayoutRedemptionPaymentTerminal is\n IJBPaymentTerminal,\n IJBPayoutTerminal,\n IJBAllowanceTerminal,\n IJBRedemptionTerminal\n{\n event AddToBalance(\n uint256 indexed projectId,\n uint256 amount,\n uint256 refundedFees,\n string memo,\n bytes metadata,\n address caller\n );\n\n event Migrate(\n uint256 indexed projectId,\n IJBPaymentTerminal indexed to,\n uint256 amount,\n address caller\n );\n\n event DistributePayouts(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address beneficiary,\n uint256 amount,\n uint256 distributedAmount,\n uint256 fee,\n uint256 beneficiaryDistributionAmount,\n string memo,\n address caller\n );\n\n event UseAllowance(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address beneficiary,\n uint256 amount,\n uint256 distributedAmount,\n uint256 netDistributedamount,\n string memo,\n address caller\n );\n\n event HoldFee(\n uint256 indexed projectId,\n uint256 indexed amount,\n uint256 indexed fee,\n uint256 feeDiscount,\n address beneficiary,\n address caller\n );\n\n event ProcessFee(\n uint256 indexed projectId,\n uint256 indexed amount,\n bool indexed wasHeld,\n address beneficiary,\n address caller\n );\n\n event RefundHeldFees(\n uint256 indexed projectId,\n uint256 indexed amount,\n uint256 indexed refundedFees,\n uint256 leftoverAmount,\n address caller\n );\n\n event Pay(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address payer,\n address beneficiary,\n uint256 amount,\n uint256 beneficiaryTokenCount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DelegateDidPay(\n IJBPayDelegate indexed delegate,\n JBDidPayData data,\n uint256 delegatedAmount,\n address caller\n );\n\n event RedeemTokens(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address holder,\n address beneficiary,\n uint256 tokenCount,\n uint256 reclaimedAmount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DelegateDidRedeem(\n IJBRedemptionDelegate indexed delegate,\n JBDidRedeemData data,\n uint256 delegatedAmount,\n address caller\n );\n\n event DistributeToPayoutSplit(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n JBSplit split,\n uint256 amount,\n address caller\n );\n\n event SetFee(uint256 fee, address caller);\n\n event SetFeeGauge(IJBFeeGauge indexed feeGauge, address caller);\n\n event SetFeelessAddress(address indexed addrs, bool indexed flag, address caller);\n\n function projects() external view returns (IJBProjects);\n\n function splitsStore() external view returns (IJBSplitsStore);\n\n function directory() external view returns (IJBDirectory);\n\n function prices() external view returns (IJBPrices);\n\n function store() external view returns (IJBSingleTokenPaymentTerminalStore);\n\n function baseWeightCurrency() external view returns (uint256);\n\n function payoutSplitsGroup() external view returns (uint256);\n\n function heldFeesOf(uint256 _projectId) external view returns (JBFee[] memory);\n\n function fee() external view returns (uint256);\n\n function feeGauge() external view returns (IJBFeeGauge);\n\n function isFeelessAddress(address _contract) external view returns (bool);\n\n function migrate(uint256 _projectId, IJBPaymentTerminal _to) external returns (uint256 balance);\n\n function processFees(uint256 _projectId) external;\n\n function setFee(uint256 _fee) external;\n\n function setFeeGauge(IJBFeeGauge _feeGauge) external;\n\n function setFeelessAddress(address _contract, bool _flag) external;\n}\n" @@ -337,20 +337,20 @@ "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface AggregatorV3Interface {\n\n function decimals()\n external\n view\n returns (\n uint8\n );\n\n function description()\n external\n view\n returns (\n string memory\n );\n\n function version()\n external\n view\n returns (\n uint256\n );\n\n // getRoundData and latestRoundData should both raise \"No data present\"\n // if they do not have data to report, instead of returning unset values\n // which could be misinterpreted as actual reported values.\n function getRoundData(\n uint80 _roundId\n )\n external\n view\n returns (\n uint80 roundId,\n int256 answer,\n uint256 startedAt,\n uint256 updatedAt,\n uint80 answeredInRound\n );\n\n function latestRoundData()\n external\n view\n returns (\n uint80 roundId,\n int256 answer,\n uint256 startedAt,\n uint256 updatedAt,\n uint80 answeredInRound\n );\n\n}\n" }, - "contracts/JBETHERC20SplitsPayer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBSplitsPayer.sol';\nimport './interfaces/IJBSplitsStore.sol';\nimport './libraries/JBConstants.sol';\nimport './JBETHERC20ProjectPayer.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\n\n @dev\n Adheres to -\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBETHERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBETHERC20SplitsPayer is JBETHERC20ProjectPayer, ReentrancyGuard, IJBSplitsPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The ID of project for which the default splits are stored. \n */\n uint256 public override defaultSplitsProjectId;\n\n /**\n @notice\n The domain within which the default splits are stored. \n */\n uint256 public override defaultSplitsDomain;\n\n /**\n @notice\n The group within which the default splits are stored. \n */\n uint256 public override defaultSplitsGroup;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBETHERC20ProjectPayer, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n )\n JBETHERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _preferAddToBalance,\n _splitsStore.directory(),\n _owner\n )\n {\n defaultSplitsProjectId = _defaultSplitsProjectId;\n defaultSplitsDomain = _defaultSplitsDomain;\n defaultSplitsGroup = _defaultSplitsGroup;\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default split group using the stored default properties.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override nonReentrant {\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n JBTokens.ETH,\n address(this).balance,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // If there is no leftover amount, nothing left to pay.\n if (_leftoverAmount == 0) return;\n\n // If there's a default project ID, try to pay it.\n if (defaultProjectId != 0)\n if (defaultPreferAddToBalance)\n // Pay the project by adding to its balance if prefered.\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.ETH,\n _leftoverAmount,\n 18, // decimals.\n defaultMemo,\n defaultMetadata\n );\n // Otherwise, issue a payment to the project.\n else\n _pay(\n defaultProjectId,\n JBTokens.ETH,\n _leftoverAmount,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n 0, // min returned tokens.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else\n Address.sendValue(\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(tx.origin),\n _leftoverAmount\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the splits in the splits store that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n @param _groupedSplits The split groups to set.\n */\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n JBGroupedSplits[] memory _groupedSplits\n ) external virtual override onlyOwner {\n // Set the splits in the store.\n splitsStore.set(_projectId, _domain, _groupedSplits);\n\n // Set the splits reference.\n setDefaultSplitsReference(_projectId, _domain, _group);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the location of the splits that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n */\n function setDefaultSplitsReference(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) public virtual override onlyOwner {\n // Set the default splits project ID if it's changing.\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\n\n // Set the default splits domain if it's changing.\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\n\n // Set the default splits group if it's changing.\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\n\n emit SetDefaultSplitsReference(_projectId, _domain, _group, msg.sender);\n }\n\n /** \n @notice \n Make a payment to the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Pay any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to pay it.\n if (_projectId != 0) {\n _pay(\n _projectId,\n _token,\n _leftoverAmount,\n _decimals,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? payable(_beneficiary) : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit Pay(\n _projectId,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event. \n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Distribute any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to add to its balance.\n if (_projectId != 0)\n // Add to the project's balance.\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\n\n // Otherwise, send a payment to the beneficiary.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit AddToBalance(\n _projectId,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splitsProjectId The ID of the project to which the splits belong.\n @param _splitsDomain The splits domain to which the group belongs.\n @param _splitsGroup The splits group to pay.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payToSplits(\n uint256 _splitsProjectId,\n uint256 _splitsDomain,\n uint256 _splitsGroup,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Pay the splits.\n leftoverAmount = _payTo(\n splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup),\n _token,\n _amount,\n _decimals,\n _defaultBeneficiary\n );\n emit DistributeToSplitGroup(_splitsProjectId, _splitsDomain, _splitsGroup, msg.sender);\n }\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splits The splits.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payTo(\n JBSplit[] memory _splits,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Set the leftover amount to the initial balance.\n leftoverAmount = _amount;\n\n // Settle between all splits.\n for (uint256 i; i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[i];\n\n // The amount to send towards the split.\n uint256 _splitAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n if (_splitAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n _token,\n _splitAmount,\n _decimals,\n defaultProjectId,\n 0,\n _split\n );\n\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\n if (_token != JBTokens.ETH)\n IERC20(_token).safeApprove(address(_split.allocator), _splitAmount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _splitAmount : 0;\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n if (_split.preferAddToBalance)\n _addToBalanceOf(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n 0,\n _split.preferClaimed,\n defaultMemo,\n defaultMetadata\n );\n } else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : payable(_defaultBeneficiary),\n _splitAmount\n );\n // Or, transfer the ERC20.\n else {\n IERC20(_token).safeTransfer(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n _splitAmount\n );\n }\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _splitAmount;\n }\n\n emit DistributeToSplit(_split, _splitAmount, _defaultBeneficiary, msg.sender);\n\n unchecked {\n ++i;\n }\n }\n }\n}\n" + "contracts/JBGasTokenERC20SplitsPayer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBSplitsPayer.sol';\nimport './interfaces/IJBSplitsStore.sol';\nimport './libraries/JBConstants.sol';\nimport './JBGasTokenERC20ProjectPayer.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\n\n @dev\n Adheres to -\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBGasTokenERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBGasTokenERC20SplitsPayer is JBGasTokenERC20ProjectPayer, ReentrancyGuard, IJBSplitsPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The ID of project for which the default splits are stored. \n */\n uint256 public override defaultSplitsProjectId;\n\n /**\n @notice\n The domain within which the default splits are stored. \n */\n uint256 public override defaultSplitsDomain;\n\n /**\n @notice\n The group within which the default splits are stored. \n */\n uint256 public override defaultSplitsGroup;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBGasTokenERC20ProjectPayer, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n )\n JBGasTokenERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _preferAddToBalance,\n _splitsStore.directory(),\n _owner\n )\n {\n defaultSplitsProjectId = _defaultSplitsProjectId;\n defaultSplitsDomain = _defaultSplitsDomain;\n defaultSplitsGroup = _defaultSplitsGroup;\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default split group using the stored default properties.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override nonReentrant {\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // If there is no leftover amount, nothing left to pay.\n if (_leftoverAmount == 0) return;\n\n // If there's a default project ID, try to pay it.\n if (defaultProjectId != 0)\n if (defaultPreferAddToBalance)\n // Pay the project by adding to its balance if prefered.\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n _leftoverAmount,\n 18, // decimals.\n defaultMemo,\n defaultMetadata\n );\n // Otherwise, issue a payment to the project.\n else\n _pay(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n _leftoverAmount,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n 0, // min returned tokens.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else\n Address.sendValue(\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(tx.origin),\n _leftoverAmount\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the splits in the splits store that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n @param _groupedSplits The split groups to set.\n */\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n JBGroupedSplits[] memory _groupedSplits\n ) external virtual override onlyOwner {\n // Set the splits in the store.\n splitsStore.set(_projectId, _domain, _groupedSplits);\n\n // Set the splits reference.\n setDefaultSplitsReference(_projectId, _domain, _group);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the location of the splits that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n */\n function setDefaultSplitsReference(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) public virtual override onlyOwner {\n // Set the default splits project ID if it's changing.\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\n\n // Set the default splits domain if it's changing.\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\n\n // Set the default splits group if it's changing.\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\n\n emit SetDefaultSplitsReference(_projectId, _domain, _group, msg.sender);\n }\n\n /** \n @notice \n Make a payment to the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Pay any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to pay it.\n if (_projectId != 0) {\n _pay(\n _projectId,\n _token,\n _leftoverAmount,\n _decimals,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? payable(_beneficiary) : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit Pay(\n _projectId,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event. \n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Distribute any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to add to its balance.\n if (_projectId != 0)\n // Add to the project's balance.\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\n\n // Otherwise, send a payment to the beneficiary.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit AddToBalance(\n _projectId,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splitsProjectId The ID of the project to which the splits belong.\n @param _splitsDomain The splits domain to which the group belongs.\n @param _splitsGroup The splits group to pay.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payToSplits(\n uint256 _splitsProjectId,\n uint256 _splitsDomain,\n uint256 _splitsGroup,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Pay the splits.\n leftoverAmount = _payTo(\n splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup),\n _token,\n _amount,\n _decimals,\n _defaultBeneficiary\n );\n emit DistributeToSplitGroup(_splitsProjectId, _splitsDomain, _splitsGroup, msg.sender);\n }\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splits The splits.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payTo(\n JBSplit[] memory _splits,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Set the leftover amount to the initial balance.\n leftoverAmount = _amount;\n\n // Settle between all splits.\n for (uint256 i; i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[i];\n\n // The amount to send towards the split.\n uint256 _splitAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n if (_splitAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n _token,\n _splitAmount,\n _decimals,\n defaultProjectId,\n 0,\n _split\n );\n\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN)\n IERC20(_token).safeApprove(address(_split.allocator), _splitAmount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _splitAmount : 0;\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n if (_split.preferAddToBalance)\n _addToBalanceOf(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n 0,\n _split.preferClaimed,\n defaultMemo,\n defaultMetadata\n );\n } else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : payable(_defaultBeneficiary),\n _splitAmount\n );\n // Or, transfer the ERC20.\n else {\n IERC20(_token).safeTransfer(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n _splitAmount\n );\n }\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _splitAmount;\n }\n\n emit DistributeToSplit(_split, _splitAmount, _defaultBeneficiary, msg.sender);\n\n unchecked {\n ++i;\n }\n }\n }\n}\n" }, "contracts/interfaces/IJBSplitsPayer.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './../structs/JBSplit.sol';\nimport './../structs/JBGroupedSplits.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBSplitsPayer is IERC165 {\n event SetDefaultSplitsReference(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n address caller\n );\n event Pay(\n uint256 indexed projectId,\n address beneficiary,\n address token,\n uint256 amount,\n uint256 decimals,\n uint256 leftoverAmount,\n uint256 minReturnedTokens,\n bool preferClaimedTokens,\n string memo,\n bytes metadata,\n address caller\n );\n\n event AddToBalance(\n uint256 indexed projectId,\n address beneficiary,\n address token,\n uint256 amount,\n uint256 decimals,\n uint256 leftoverAmount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DistributeToSplitGroup(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n address caller\n );\n\n event DistributeToSplit(\n JBSplit split,\n uint256 amount,\n address defaultBeneficiary,\n address caller\n );\n\n function defaultSplitsProjectId() external view returns (uint256);\n\n function defaultSplitsDomain() external view returns (uint256);\n\n function defaultSplitsGroup() external view returns (uint256);\n\n function splitsStore() external view returns (IJBSplitsStore);\n\n function setDefaultSplitsReference(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) external;\n\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n JBGroupedSplits[] memory _splitsGroup\n ) external;\n}\n" }, - "contracts/JBETHERC20ProjectPayer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport './interfaces/IJBProjectPayer.sol';\nimport './libraries/JBTokens.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ERC165: Introspection on interface adherance. \n*/\ncontract JBETHERC20ProjectPayer is Ownable, ERC165, IJBProjectPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // -------------------------- custom errors -------------------------- //\n //*********************************************************************//\n error INCORRECT_DECIMAL_AMOUNT();\n error NO_MSG_VALUE_ALLOWED();\n error TERMINAL_NOT_FOUND();\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice \n A contract storing directories of terminals and controllers for each project.\n */\n IJBDirectory public immutable override directory;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The ID of the project that should be used to forward this contract's received payments.\n */\n uint256 public override defaultProjectId;\n\n /** \n @notice \n The beneficiary that should be used in the payment made when this contract receives payments.\n */\n address payable public override defaultBeneficiary;\n\n /** \n @notice \n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\n */\n bool public override defaultPreferClaimedTokens;\n\n /** \n @notice \n The memo that should be used in the payment made when this contract receives payments.\n */\n string public override defaultMemo;\n\n /** \n @notice \n The metadata that should be used in the payment made when this contract receives payments.\n */\n bytes public override defaultMetadata;\n\n /**\n @notice \n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n bool public override defaultPreferAddToBalance;\n\n //*********************************************************************//\n // ------------------------- public views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) {\n defaultProjectId = _defaultProjectId;\n defaultBeneficiary = _defaultBeneficiary;\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\n defaultMemo = _defaultMemo;\n defaultMetadata = _defaultMetadata;\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n directory = _directory;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default project ID using the stored default properties.\n\n @dev\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override {\n if (defaultPreferAddToBalance)\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.ETH,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n defaultProjectId,\n JBTokens.ETH,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultBeneficiary == address(0) ? tx.origin : defaultBeneficiary,\n 0, // Can't determine expectation of returned tokens ahead of time.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\n\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _beneficiary The address that'll receive the project's tokens. \n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _memo The memo that'll be used. \n @param _metadata The metadata that'll be sent. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external virtual override onlyOwner {\n // Set the default project ID if it has changed.\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\n\n // Set the default beneficiary if it has changed.\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\n\n // Set the default claimed token preference if it has changed.\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\n defaultPreferClaimedTokens = _preferClaimedTokens;\n\n // Set the default memo if it has changed.\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\n defaultMemo = _memo;\n\n // Set the default metadata if it has changed.\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\n defaultMetadata = _metadata;\n\n // Set the add to balance preference if it has changed.\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n\n emit SetDefaultValues(\n _projectId,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata,\n _defaultPreferAddToBalance,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _pay(\n _projectId,\n _token,\n _amount,\n _decimals,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. \n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source and delegate, if provided.\n */\n function _pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.ETH) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\n\n // Send funds to the terminal.\n // If the token is ETH, send it in msg.value.\n _terminal.pay{value: _payableValue}(\n _projectId,\n _amount, // ignored if the token is JBTokens.ETH.\n _token,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.ETH) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\n\n // Add to balance so tokens don't get issued.\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\n }\n}\n" + "contracts/JBGasTokenERC20ProjectPayer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport './interfaces/IJBProjectPayer.sol';\nimport './libraries/JBTokens.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ERC165: Introspection on interface adherance. \n*/\ncontract JBGasTokenERC20ProjectPayer is Ownable, ERC165, IJBProjectPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // -------------------------- custom errors -------------------------- //\n //*********************************************************************//\n error INCORRECT_DECIMAL_AMOUNT();\n error NO_MSG_VALUE_ALLOWED();\n error TERMINAL_NOT_FOUND();\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice \n A contract storing directories of terminals and controllers for each project.\n */\n IJBDirectory public immutable override directory;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The ID of the project that should be used to forward this contract's received payments.\n */\n uint256 public override defaultProjectId;\n\n /** \n @notice \n The beneficiary that should be used in the payment made when this contract receives payments.\n */\n address payable public override defaultBeneficiary;\n\n /** \n @notice \n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\n */\n bool public override defaultPreferClaimedTokens;\n\n /** \n @notice \n The memo that should be used in the payment made when this contract receives payments.\n */\n string public override defaultMemo;\n\n /** \n @notice \n The metadata that should be used in the payment made when this contract receives payments.\n */\n bytes public override defaultMetadata;\n\n /**\n @notice \n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n bool public override defaultPreferAddToBalance;\n\n //*********************************************************************//\n // ------------------------- public views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) {\n defaultProjectId = _defaultProjectId;\n defaultBeneficiary = _defaultBeneficiary;\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\n defaultMemo = _defaultMemo;\n defaultMetadata = _defaultMetadata;\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n directory = _directory;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default project ID using the stored default properties.\n\n @dev\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override {\n if (defaultPreferAddToBalance)\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultBeneficiary == address(0) ? tx.origin : defaultBeneficiary,\n 0, // Can't determine expectation of returned tokens ahead of time.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\n\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _beneficiary The address that'll receive the project's tokens. \n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _memo The memo that'll be used. \n @param _metadata The metadata that'll be sent. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external virtual override onlyOwner {\n // Set the default project ID if it has changed.\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\n\n // Set the default beneficiary if it has changed.\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\n\n // Set the default claimed token preference if it has changed.\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\n defaultPreferClaimedTokens = _preferClaimedTokens;\n\n // Set the default memo if it has changed.\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\n defaultMemo = _memo;\n\n // Set the default metadata if it has changed.\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\n defaultMetadata = _metadata;\n\n // Set the add to balance preference if it has changed.\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n\n emit SetDefaultValues(\n _projectId,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata,\n _defaultPreferAddToBalance,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _pay(\n _projectId,\n _token,\n _amount,\n _decimals,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. \n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source and delegate, if provided.\n */\n function _pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send funds to the terminal.\n // If the token is ETH, send it in msg.value.\n _terminal.pay{value: _payableValue}(\n _projectId,\n _amount, // ignored if the token is JBTokens.GAS_TOKEN.\n _token,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Add to balance so tokens don't get issued.\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\n }\n}\n" }, "contracts/interfaces/IJBProjectPayer.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './IJBDirectory.sol';\n\ninterface IJBProjectPayer is IERC165 {\n event SetDefaultValues(\n uint256 indexed projectId,\n address indexed beneficiary,\n bool preferClaimedTokens,\n string memo,\n bytes metadata,\n bool preferAddToBalance,\n address caller\n );\n\n function directory() external view returns (IJBDirectory);\n\n function defaultProjectId() external view returns (uint256);\n\n function defaultBeneficiary() external view returns (address payable);\n\n function defaultPreferClaimedTokens() external view returns (bool);\n\n function defaultMemo() external view returns (string memory);\n\n function defaultMetadata() external view returns (bytes memory);\n\n function defaultPreferAddToBalance() external view returns (bool);\n\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external;\n\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) external payable;\n\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) external payable;\n\n receive() external payable;\n}\n" }, "contracts/system_tests/TestEIP165.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.6;\n\nimport './helpers/TestBaseWorkflow.sol';\nimport '../JBReconfigurationBufferBallot.sol';\nimport '../JBETHERC20SplitsPayer.sol';\n\ncontract TestEIP165 is TestBaseWorkflow {\n bytes4 constant notSupportedInterface = 0xffffffff;\n\n uint256 constant projectId = 2;\n uint256 constant splitsProjectID = 3;\n address payable constant splitsBeneficiary = payable(address(420));\n uint256 constant splitsDomain = 1;\n uint256 constant splitsGroup = 1;\n bool constant splitsPreferClaimedTokens = false;\n string constant splitsMemo = '';\n bytes constant splitsMetadata = '';\n bool constant splitsPreferAddToBalance = true;\n address constant splitsOwner = address(420);\n\n function testJBController() public {\n JBController controller = jbController();\n\n // Should support these interfaces\n assertTrue(controller.supportsInterface(type(IERC165).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBController).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBMigratable).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!controller.supportsInterface(notSupportedInterface));\n }\n\n function testJBERC20PaymentTerminal() public {\n JBERC20PaymentTerminal terminal = new JBERC20PaymentTerminal(\n jbToken(),\n jbLibraries().USD(), // currency\n jbLibraries().ETH(), // base weight currency\n 1, // JBSplitsGroupe\n jbOperatorStore(),\n jbProjects(),\n jbDirectory(),\n jbSplitsStore(),\n jbPrices(),\n jbPaymentTerminalStore(),\n multisig()\n );\n\n // Should support these interfaces\n assertTrue(terminal.supportsInterface(type(IERC165).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBRedemptionTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBSingleTokenPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!terminal.supportsInterface(notSupportedInterface));\n }\n\n function testJBETHPaymentTerminal() public {\n JBETHPaymentTerminal terminal = jbETHPaymentTerminal();\n\n // Should support these interfaces\n assertTrue(terminal.supportsInterface(type(IERC165).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBRedemptionTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBSingleTokenPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!terminal.supportsInterface(notSupportedInterface));\n }\n\n function testJBProjects() public {\n JBProjects projects = jbProjects();\n\n // Should support these interfaces\n assertTrue(projects.supportsInterface(type(IERC165).interfaceId));\n assertTrue(projects.supportsInterface(type(IERC721).interfaceId));\n assertTrue(projects.supportsInterface(type(IERC721Metadata).interfaceId));\n assertTrue(projects.supportsInterface(type(IJBProjects).interfaceId));\n assertTrue(projects.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!projects.supportsInterface(notSupportedInterface));\n }\n\n function testJBReconfigurationBufferBallot() public {\n JBReconfigurationBufferBallot ballot = new JBReconfigurationBufferBallot(3000);\n\n // Should support these interfaces\n assertTrue(ballot.supportsInterface(type(IERC165).interfaceId));\n // TODO: Add interface\n //assertTrue(ballot.supportsInterface(type(IJBReconfigurationBufferBallot).interfaceId));\n assertTrue(ballot.supportsInterface(type(IJBFundingCycleBallot).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!ballot.supportsInterface(notSupportedInterface));\n }\n\n function testJBETHERC20SplitsPayer() public {\n JBETHERC20SplitsPayer splitsPayer = new JBETHERC20SplitsPayer(\n splitsProjectID,\n splitsDomain,\n splitsGroup,\n jbSplitsStore(),\n projectId,\n splitsBeneficiary,\n splitsPreferClaimedTokens,\n splitsMemo,\n splitsMetadata,\n splitsPreferAddToBalance,\n splitsOwner\n );\n\n // Should support these interfaces\n assertTrue(splitsPayer.supportsInterface(type(IERC165).interfaceId));\n assertTrue(splitsPayer.supportsInterface(type(IJBSplitsPayer).interfaceId));\n assertTrue(splitsPayer.supportsInterface(type(IJBProjectPayer).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!splitsPayer.supportsInterface(notSupportedInterface));\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.6;\n\nimport './helpers/TestBaseWorkflow.sol';\nimport '../JBReconfigurationBufferBallot.sol';\nimport '../JBGasTokenERC20SplitsPayer.sol';\n\ncontract TestEIP165 is TestBaseWorkflow {\n bytes4 constant notSupportedInterface = 0xffffffff;\n\n uint256 constant projectId = 2;\n uint256 constant splitsProjectID = 3;\n address payable constant splitsBeneficiary = payable(address(420));\n uint256 constant splitsDomain = 1;\n uint256 constant splitsGroup = 1;\n bool constant splitsPreferClaimedTokens = false;\n string constant splitsMemo = '';\n bytes constant splitsMetadata = '';\n bool constant splitsPreferAddToBalance = true;\n address constant splitsOwner = address(420);\n\n function testJBController() public {\n JBController controller = jbController();\n\n // Should support these interfaces\n assertTrue(controller.supportsInterface(type(IERC165).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBController).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBMigratable).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!controller.supportsInterface(notSupportedInterface));\n }\n\n function testJBERC20PaymentTerminal() public {\n JBERC20PaymentTerminal terminal = new JBERC20PaymentTerminal(\n jbToken(),\n jbLibraries().USD(), // currency\n jbLibraries().ETH(), // base weight currency\n 1, // JBSplitsGroupe\n jbOperatorStore(),\n jbProjects(),\n jbDirectory(),\n jbSplitsStore(),\n jbPrices(),\n jbPaymentTerminalStore(),\n multisig()\n );\n\n // Should support these interfaces\n assertTrue(terminal.supportsInterface(type(IERC165).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBRedemptionTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBSingleTokenPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!terminal.supportsInterface(notSupportedInterface));\n }\n\n function testJBETHPaymentTerminal() public {\n JBETHPaymentTerminal terminal = jbETHPaymentTerminal();\n\n // Should support these interfaces\n assertTrue(terminal.supportsInterface(type(IERC165).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBRedemptionTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBSingleTokenPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!terminal.supportsInterface(notSupportedInterface));\n }\n\n function testJBProjects() public {\n JBProjects projects = jbProjects();\n\n // Should support these interfaces\n assertTrue(projects.supportsInterface(type(IERC165).interfaceId));\n assertTrue(projects.supportsInterface(type(IERC721).interfaceId));\n assertTrue(projects.supportsInterface(type(IERC721Metadata).interfaceId));\n assertTrue(projects.supportsInterface(type(IJBProjects).interfaceId));\n assertTrue(projects.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!projects.supportsInterface(notSupportedInterface));\n }\n\n function testJBReconfigurationBufferBallot() public {\n JBReconfigurationBufferBallot ballot = new JBReconfigurationBufferBallot(3000);\n\n // Should support these interfaces\n assertTrue(ballot.supportsInterface(type(IERC165).interfaceId));\n // TODO: Add interface\n //assertTrue(ballot.supportsInterface(type(IJBReconfigurationBufferBallot).interfaceId));\n assertTrue(ballot.supportsInterface(type(IJBFundingCycleBallot).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!ballot.supportsInterface(notSupportedInterface));\n }\n\n function testJBGasTokenERC20SplitsPayer() public {\n JBGasTokenERC20SplitsPayer splitsPayer = new JBGasTokenERC20SplitsPayer(\n splitsProjectID,\n splitsDomain,\n splitsGroup,\n jbSplitsStore(),\n projectId,\n splitsBeneficiary,\n splitsPreferClaimedTokens,\n splitsMemo,\n splitsMetadata,\n splitsPreferAddToBalance,\n splitsOwner\n );\n\n // Should support these interfaces\n assertTrue(splitsPayer.supportsInterface(type(IERC165).interfaceId));\n assertTrue(splitsPayer.supportsInterface(type(IJBSplitsPayer).interfaceId));\n assertTrue(splitsPayer.supportsInterface(type(IJBProjectPayer).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!splitsPayer.supportsInterface(notSupportedInterface));\n }\n}\n" }, "contracts/JBReconfigurationBufferBallot.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport './interfaces/IJBFundingCycleBallot.sol';\nimport './structs/JBFundingCycle.sol';\n\n/** \n @notice \n Manages approving funding cycle reconfigurations automatically after a buffer period.\n\n @dev\n Adheres to -\n IJBFundingCycleBallot: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ERC165: Introspection on interface adherance. \n*/\ncontract JBReconfigurationBufferBallot is ERC165, IJBFundingCycleBallot {\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice \n The number of seconds that must pass for a funding cycle reconfiguration to become either `Approved` or `Failed`.\n */\n uint256 public immutable override duration;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice \n The approval state of a particular funding cycle.\n\n @param _projectId The ID of the project to which the funding cycle being checked belongs.\n @param _configured The configuration of the funding cycle to check the state of.\n @param _start The start timestamp of the funding cycle to check the state of.\n\n @return The state of the provided ballot. \n */\n function stateOf(\n uint256 _projectId,\n uint256 _configured,\n uint256 _start\n ) public view override returns (JBBallotState) {\n _projectId; // Prevents unused var compiler and natspec complaints.\n\n // If the provided configured timestamp is after the start timestamp, the ballot is Failed.\n if (_configured > _start) return JBBallotState.Failed;\n\n unchecked {\n // If there was sufficient time between configuration and the start of the cycle, it is approved. Otherwise, it is failed.\n return (_start - _configured < duration) ? JBBallotState.Failed : JBBallotState.Approved;\n }\n }\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBFundingCycleBallot).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _duration The number of seconds to wait until a reconfiguration can be either `Approved` or `Failed`.\n */\n constructor(uint256 _duration) {\n duration = _duration;\n }\n}\n" @@ -358,20 +358,20 @@ "contracts/system_tests/TestReconfigure.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.6;\n\nimport './helpers/TestBaseWorkflow.sol';\n\nimport '../JBReconfigurationBufferBallot.sol';\n\nuint256 constant WEIGHT = 1000 * 10**18;\n\ncontract TestReconfigureProject is TestBaseWorkflow {\n JBController controller;\n JBProjectMetadata _projectMetadata;\n JBFundingCycleData _data;\n JBFundingCycleData _dataReconfiguration;\n JBFundingCycleData _dataWithoutBallot;\n JBFundingCycleMetadata _metadata;\n JBReconfigurationBufferBallot _ballot;\n JBGroupedSplits[] _groupedSplits; // Default empty\n JBFundAccessConstraints[] _fundAccessConstraints; // Default empty\n IJBPaymentTerminal[] _terminals; // Default empty\n\n uint256 BALLOT_DURATION = 3 days;\n\n function setUp() public override {\n super.setUp();\n\n controller = jbController();\n\n _projectMetadata = JBProjectMetadata({content: 'myIPFSHash', domain: 1});\n\n _ballot = new JBReconfigurationBufferBallot(BALLOT_DURATION);\n\n _data = JBFundingCycleData({\n duration: 6 days,\n weight: 10000 * 10**18,\n discountRate: 0,\n ballot: _ballot\n });\n\n _dataWithoutBallot = JBFundingCycleData({\n duration: 6 days,\n weight: 1000 * 10**18,\n discountRate: 0,\n ballot: JBReconfigurationBufferBallot(address(0))\n });\n\n _dataReconfiguration = JBFundingCycleData({\n duration: 6 days,\n weight: 69 * 10**18,\n discountRate: 0,\n ballot: JBReconfigurationBufferBallot(address(0))\n });\n\n _metadata = JBFundingCycleMetadata({\n global: JBGlobalFundingCycleMetadata({\n allowSetTerminals: false,\n allowSetController: false,\n pauseTransfers: false\n }),\n reservedRate: 5000,\n redemptionRate: 5000,\n ballotRedemptionRate: 0,\n pausePay: false,\n pauseDistributions: false,\n pauseRedeem: false,\n pauseBurn: false,\n allowMinting: true,\n allowTerminalMigration: false,\n allowControllerMigration: false,\n holdFees: false,\n preferClaimedTokenOverride: false,\n useTotalOverflowForRedemptions: false,\n useDataSourceForPay: false,\n useDataSourceForRedeem: false,\n dataSource: address(0),\n metadata: 0\n });\n\n _terminals = [jbETHPaymentTerminal()];\n }\n\n function testReconfigureProject() public {\n uint256 projectId = controller.launchProjectFor(\n multisig(),\n _projectMetadata,\n _data,\n _metadata,\n 0, // Start asap\n _groupedSplits,\n _fundAccessConstraints,\n _terminals,\n ''\n );\n\n JBFundingCycle memory fundingCycle = jbFundingCycleStore().currentOf(projectId);\n\n assertEq(fundingCycle.number, 1); // ok\n assertEq(fundingCycle.weight, _data.weight);\n\n uint256 currentConfiguration = fundingCycle.configuration;\n\n evm.warp(block.timestamp + 1); // Avoid overwriting if same timestamp\n\n evm.prank(multisig());\n controller.reconfigureFundingCyclesOf(\n projectId,\n _data, // 3days ballot\n _metadata,\n 0, // Start asap\n _groupedSplits,\n _fundAccessConstraints,\n ''\n );\n\n // Shouldn't have changed\n fundingCycle = jbFundingCycleStore().currentOf(projectId);\n assertEq(fundingCycle.number, 1);\n assertEq(fundingCycle.configuration, currentConfiguration);\n assertEq(fundingCycle.weight, _data.weight);\n\n // should be new funding cycle\n evm.warp(fundingCycle.start + fundingCycle.duration);\n\n JBFundingCycle memory newFundingCycle = jbFundingCycleStore().currentOf(projectId);\n assertEq(newFundingCycle.number, 2);\n assertEq(newFundingCycle.weight, _data.weight);\n }\n\n function testMultipleReconfigurationOnRolledOver() public {\n uint256 weightFirstReconfiguration = 1234 * 10**18;\n uint256 weightSecondReconfiguration = 6969 * 10**18;\n\n uint256 projectId = controller.launchProjectFor(\n multisig(),\n _projectMetadata,\n _data,\n _metadata,\n 0, // Start asap\n _groupedSplits,\n _fundAccessConstraints,\n _terminals,\n ''\n );\n\n JBFundingCycle memory fundingCycle = jbFundingCycleStore().currentOf(projectId);\n\n // Initial funding cycle data\n assertEq(fundingCycle.number, 1);\n assertEq(fundingCycle.weight, _data.weight);\n\n uint256 currentConfiguration = fundingCycle.configuration;\n\n // Jump to FC+1, rolled over\n evm.warp(block.timestamp + fundingCycle.duration);\n\n // First reconfiguration\n evm.prank(multisig());\n controller.reconfigureFundingCyclesOf(\n projectId,\n JBFundingCycleData({\n duration: 6 days,\n weight: weightFirstReconfiguration,\n discountRate: 0,\n ballot: _ballot\n }), // 3days ballot\n _metadata,\n 0, // Start asap\n _groupedSplits,\n _fundAccessConstraints,\n ''\n );\n\n evm.warp(block.timestamp + 1); // Avoid overwrite\n\n // Second reconfiguration (different configuration)\n evm.prank(multisig());\n controller.reconfigureFundingCyclesOf(\n projectId,\n JBFundingCycleData({\n duration: 6 days,\n weight: weightSecondReconfiguration,\n discountRate: 0,\n ballot: _ballot\n }), // 3days ballot\n _metadata,\n 0, // Start asap\n _groupedSplits,\n _fundAccessConstraints,\n ''\n );\n uint256 secondReconfiguration = block.timestamp;\n\n // Shouldn't have changed, still in FC#2, rolled over from FC#1\n fundingCycle = jbFundingCycleStore().currentOf(projectId);\n assertEq(fundingCycle.number, 2);\n assertEq(fundingCycle.configuration, currentConfiguration);\n assertEq(fundingCycle.weight, _data.weight);\n\n // Jump to after the ballot passed, but before the next FC\n evm.warp(fundingCycle.start + fundingCycle.duration - 1);\n\n // Queued should be the second reconfiguration\n JBFundingCycle memory queuedFundingCycle = jbFundingCycleStore().queuedOf(projectId);\n assertEq(queuedFundingCycle.number, 3);\n assertEq(queuedFundingCycle.configuration, secondReconfiguration);\n assertEq(queuedFundingCycle.weight, weightSecondReconfiguration);\n\n evm.warp(fundingCycle.start + fundingCycle.duration);\n\n // Second reconfiguration should be now the current one\n JBFundingCycle memory newFundingCycle = jbFundingCycleStore().currentOf(projectId);\n assertEq(newFundingCycle.number, 3);\n assertEq(newFundingCycle.configuration, secondReconfiguration);\n assertEq(newFundingCycle.weight, weightSecondReconfiguration);\n }\n\n function testMultipleReconfigure(uint8 FUZZED_BALLOT_DURATION) public {\n _ballot = new JBReconfigurationBufferBallot(FUZZED_BALLOT_DURATION);\n\n _data = JBFundingCycleData({\n duration: 6 days,\n weight: 10000 ether,\n discountRate: 0,\n ballot: _ballot\n });\n\n uint256 projectId = controller.launchProjectFor(\n multisig(),\n _projectMetadata,\n _data, // duration 6 days, weight=10k, ballot 3days\n _metadata,\n 0, // Start asap\n _groupedSplits,\n _fundAccessConstraints,\n _terminals,\n ''\n );\n\n JBFundingCycle memory initialFundingCycle = jbFundingCycleStore().currentOf(projectId);\n JBFundingCycle memory currentFundingCycle = initialFundingCycle;\n JBFundingCycle memory queuedFundingCycle = jbFundingCycleStore().queuedOf(projectId);\n\n evm.warp(currentFundingCycle.start + 1); // Avoid overwriting current fc while reconfiguring\n\n for (uint256 i = 0; i < 4; i++) {\n currentFundingCycle = jbFundingCycleStore().currentOf(projectId);\n\n if (FUZZED_BALLOT_DURATION + i * 1 days < currentFundingCycle.duration)\n assertEq(currentFundingCycle.weight, initialFundingCycle.weight - i);\n\n _data = JBFundingCycleData({\n duration: 6 days,\n weight: initialFundingCycle.weight - (i + 1), // i+1 -> next funding cycle\n discountRate: 0,\n ballot: _ballot\n });\n\n evm.prank(multisig());\n controller.reconfigureFundingCyclesOf(\n projectId,\n _data,\n _metadata,\n 0,\n _groupedSplits,\n _fundAccessConstraints,\n ''\n );\n\n currentFundingCycle = jbFundingCycleStore().currentOf(projectId);\n queuedFundingCycle = jbFundingCycleStore().queuedOf(projectId);\n\n // Queued is the funding cycle currently under ballot\n assertEq(queuedFundingCycle.weight, _data.weight);\n assertEq(queuedFundingCycle.number, currentFundingCycle.number + 1);\n\n // Is the full ballot duration included in the funding cycle?\n if (\n FUZZED_BALLOT_DURATION == 0 ||\n currentFundingCycle.duration % (FUZZED_BALLOT_DURATION + i * 1 days) <\n currentFundingCycle.duration\n ) {\n assertEq(currentFundingCycle.weight, initialFundingCycle.weight - i);\n\n uint256 _previousFundingCycleNumber = currentFundingCycle.number;\n\n // we shift forward the start of the ballot into the fc, one day at a time, from fc to fc\n evm.warp(currentFundingCycle.start + currentFundingCycle.duration + i * 1 days);\n\n // Ballot was Approved and we've changed fc, current is the reconfiguration\n currentFundingCycle = jbFundingCycleStore().currentOf(projectId);\n assertEq(currentFundingCycle.weight, _data.weight);\n assertEq(currentFundingCycle.number, _previousFundingCycleNumber + 1);\n\n // Queued is the reconfiguration rolled-over\n queuedFundingCycle = jbFundingCycleStore().queuedOf(projectId);\n assertEq(queuedFundingCycle.weight, _data.weight);\n assertEq(queuedFundingCycle.number, currentFundingCycle.number + 1);\n }\n // the ballot is accross two funding cycles\n else {\n // Warp to begining of next FC: should be the previous fc config rolled over (ballot is in Failed state)\n evm.warp(currentFundingCycle.start + currentFundingCycle.duration);\n assertEq(currentFundingCycle.weight, initialFundingCycle.weight - i);\n uint256 cycleNumber = currentFundingCycle.number;\n\n // Warp to after the end of the ballot, within the same fc: should be the new fc (ballot is in Approved state)\n evm.warp(currentFundingCycle.start + currentFundingCycle.duration + FUZZED_BALLOT_DURATION);\n currentFundingCycle = jbFundingCycleStore().currentOf(projectId);\n assertEq(currentFundingCycle.weight, _data.weight);\n assertEq(currentFundingCycle.number, cycleNumber + 1);\n }\n }\n }\n\n function testReconfigureProjectFuzzRates(\n uint96 RESERVED_RATE,\n uint96 REDEMPTION_RATE,\n uint96 BALANCE\n ) public {\n evm.assume(payable(msg.sender).balance / 2 >= BALANCE);\n evm.assume(100 < BALANCE);\n\n address _beneficiary = address(69420);\n uint256 projectId = controller.launchProjectFor(\n multisig(),\n _projectMetadata,\n _dataWithoutBallot,\n _metadata,\n 0, // _mustStartAtOrAfter\n _groupedSplits,\n _fundAccessConstraints,\n _terminals,\n ''\n );\n\n JBFundingCycle memory fundingCycle = jbFundingCycleStore().currentOf(projectId);\n assertEq(fundingCycle.number, 1);\n\n evm.warp(block.timestamp + 1);\n\n jbETHPaymentTerminal().pay{value: BALANCE}(\n projectId,\n BALANCE,\n address(0),\n _beneficiary,\n 0,\n false,\n 'Forge test',\n new bytes(0)\n );\n\n uint256 _userTokenBalance = PRBMath.mulDiv(BALANCE, (WEIGHT / 10**18), 2); // initial FC rate is 50%\n if (BALANCE != 0)\n assertEq(jbTokenStore().balanceOf(_beneficiary, projectId), _userTokenBalance);\n\n evm.prank(multisig());\n if (RESERVED_RATE > 10000) evm.expectRevert(abi.encodeWithSignature('INVALID_RESERVED_RATE()'));\n else if (REDEMPTION_RATE > 10000)\n evm.expectRevert(abi.encodeWithSignature('INVALID_REDEMPTION_RATE()'));\n\n controller.reconfigureFundingCyclesOf(\n projectId,\n _dataWithoutBallot,\n JBFundingCycleMetadata({\n global: JBGlobalFundingCycleMetadata({\n allowSetTerminals: false,\n allowSetController: false,\n pauseTransfers: false\n }),\n reservedRate: RESERVED_RATE,\n redemptionRate: REDEMPTION_RATE,\n ballotRedemptionRate: 0,\n pausePay: false,\n pauseDistributions: false,\n pauseRedeem: false,\n pauseBurn: false,\n allowMinting: true,\n allowTerminalMigration: false,\n allowControllerMigration: false,\n holdFees: false,\n preferClaimedTokenOverride: false,\n useTotalOverflowForRedemptions: false,\n useDataSourceForPay: false,\n useDataSourceForRedeem: false,\n dataSource: address(0),\n metadata: 0\n }),\n 0,\n _groupedSplits,\n _fundAccessConstraints,\n ''\n );\n\n if (RESERVED_RATE > 10000 || REDEMPTION_RATE > 10000) {\n REDEMPTION_RATE = 5000; // If reconfigure has reverted, keep previous rates\n RESERVED_RATE = 5000;\n }\n\n evm.warp(block.timestamp + fundingCycle.duration);\n\n fundingCycle = jbFundingCycleStore().currentOf(projectId);\n assertEq(fundingCycle.number, 2);\n\n jbETHPaymentTerminal().pay{value: BALANCE}(\n projectId,\n BALANCE,\n address(0),\n _beneficiary,\n 0,\n false,\n 'Forge test',\n new bytes(0)\n );\n\n uint256 _newUserTokenBalance = RESERVED_RATE == 0 // New fc, rate is RESERVED_RATE\n ? PRBMath.mulDiv(BALANCE, WEIGHT, 10**18)\n : PRBMath.mulDiv(PRBMath.mulDiv(BALANCE, WEIGHT, 10**18), 10000 - RESERVED_RATE, 10000);\n\n if (BALANCE != 0)\n assertEq(\n jbTokenStore().balanceOf(_beneficiary, projectId),\n _userTokenBalance + _newUserTokenBalance\n );\n\n uint256 tokenBalance = jbTokenStore().balanceOf(_beneficiary, projectId);\n uint256 totalSupply = jbController().totalOutstandingTokensOf(projectId, RESERVED_RATE);\n uint256 overflow = jbETHPaymentTerminal().currentEthOverflowOf(projectId);\n\n evm.startPrank(_beneficiary);\n jbETHPaymentTerminal().redeemTokensOf(\n _beneficiary,\n projectId,\n tokenBalance,\n address(0), //token (unused)\n 0,\n payable(_beneficiary),\n '',\n new bytes(0)\n );\n evm.stopPrank();\n\n if (BALANCE != 0 && REDEMPTION_RATE != 0)\n assertEq(\n _beneficiary.balance,\n PRBMath.mulDiv(\n PRBMath.mulDiv(overflow, tokenBalance, totalSupply),\n REDEMPTION_RATE + PRBMath.mulDiv(tokenBalance, 10000 - REDEMPTION_RATE, totalSupply),\n 10000\n )\n );\n }\n\n function testLaunchProjectWrongBallot() public {\n uint256 projectId = controller.launchProjectFor(\n multisig(),\n _projectMetadata,\n _data,\n _metadata,\n 0, // Start asap\n _groupedSplits,\n _fundAccessConstraints,\n _terminals,\n ''\n );\n\n JBFundingCycleData memory _dataNew = JBFundingCycleData({\n duration: 6 days,\n weight: 12345 * 10**18,\n discountRate: 0,\n ballot: IJBFundingCycleBallot(address(6969)) // Wrong ballot address\n });\n\n evm.warp(block.timestamp + 1); // Avoid overwriting if same timestamp\n\n evm.prank(multisig());\n evm.expectRevert(abi.encodeWithSignature('INVALID_BALLOT()'));\n controller.reconfigureFundingCyclesOf(\n projectId,\n _dataNew, // wrong ballot\n _metadata,\n 0, // Start asap\n _groupedSplits,\n _fundAccessConstraints,\n ''\n );\n }\n\n function testReconfigureShortDurationProject() public {\n _data = JBFundingCycleData({\n duration: 5 minutes,\n weight: 10000 * 10**18,\n discountRate: 0,\n ballot: _ballot\n });\n\n _dataReconfiguration = JBFundingCycleData({\n duration: 6 days,\n weight: 69 * 10**18,\n discountRate: 0,\n ballot: IJBFundingCycleBallot(address(0))\n });\n\n uint256 projectId = controller.launchProjectFor(\n multisig(),\n _projectMetadata,\n _data,\n _metadata,\n 0, // Start asap\n _groupedSplits,\n _fundAccessConstraints,\n _terminals,\n ''\n );\n\n JBFundingCycle memory fundingCycle = jbFundingCycleStore().currentOf(projectId);\n\n assertEq(fundingCycle.number, 1); // ok\n assertEq(fundingCycle.weight, _data.weight);\n\n uint256 currentConfiguration = fundingCycle.configuration;\n\n evm.warp(block.timestamp + 1); // Avoid overwriting if same timestamp\n\n evm.prank(multisig());\n controller.reconfigureFundingCyclesOf(\n projectId,\n _dataReconfiguration,\n _metadata,\n 0, // Start asap\n _groupedSplits,\n _fundAccessConstraints,\n ''\n );\n\n // Shouldn't have changed (same cycle, with a ballot)\n fundingCycle = jbFundingCycleStore().currentOf(projectId);\n assertEq(fundingCycle.number, 1);\n assertEq(fundingCycle.configuration, currentConfiguration);\n assertEq(fundingCycle.weight, _data.weight);\n\n // shouldn't have changed (new cycle but ballot is still active)\n evm.warp(fundingCycle.start + fundingCycle.duration);\n\n JBFundingCycle memory newFundingCycle = jbFundingCycleStore().currentOf(projectId);\n assertEq(newFundingCycle.number, 2);\n assertEq(newFundingCycle.weight, _data.weight);\n\n // should now be the reconfiguration (ballot duration is over)\n evm.warp(fundingCycle.start + fundingCycle.duration + 3 days);\n\n newFundingCycle = jbFundingCycleStore().currentOf(projectId);\n assertEq(newFundingCycle.number, fundingCycle.number + (3 days / 5 minutes) + 1);\n assertEq(newFundingCycle.weight, _dataReconfiguration.weight);\n }\n\n function testReconfigureWithoutBallot() public {\n _data = JBFundingCycleData({\n duration: 5 minutes,\n weight: 10000 * 10**18,\n discountRate: 0,\n ballot: IJBFundingCycleBallot(address(0))\n });\n\n _dataReconfiguration = JBFundingCycleData({\n duration: 6 days,\n weight: 69 * 10**18,\n discountRate: 0,\n ballot: IJBFundingCycleBallot(address(0))\n });\n\n uint256 projectId = controller.launchProjectFor(\n multisig(),\n _projectMetadata,\n _data,\n _metadata,\n 0, // Start asap\n _groupedSplits,\n _fundAccessConstraints,\n _terminals,\n ''\n );\n\n JBFundingCycle memory fundingCycle = jbFundingCycleStore().currentOf(projectId);\n\n assertEq(fundingCycle.number, 1);\n assertEq(fundingCycle.weight, _data.weight);\n\n evm.warp(block.timestamp + 10); // Avoid overwriting if same timestamp\n\n evm.prank(multisig());\n controller.reconfigureFundingCyclesOf(\n projectId,\n _dataReconfiguration,\n _metadata,\n 0, // Start asap\n _groupedSplits,\n _fundAccessConstraints,\n ''\n );\n // Should not have changed\n fundingCycle = jbFundingCycleStore().currentOf(projectId);\n assertEq(fundingCycle.number, 1);\n assertEq(fundingCycle.weight, _data.weight);\n\n // Should have changed after the current funding cycle is over\n evm.warp(fundingCycle.start + fundingCycle.duration);\n fundingCycle = jbFundingCycleStore().currentOf(projectId);\n assertEq(fundingCycle.number, 2);\n assertEq(fundingCycle.weight, _dataReconfiguration.weight);\n }\n}\n" }, - "contracts/JBETHERC20ProjectPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './interfaces/IJBETHERC20ProjectPayerDeployer.sol';\nimport './JBETHERC20ProjectPayer.sol';\n\n/** \n @notice \n Deploys project payer contracts.\n\n @dev\n Adheres to -\n IJBETHERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBETHERC20ProjectPayerDeployer is IJBETHERC20ProjectPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new project payer contract.\n\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the project payer contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the project payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the project payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the project payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the project payer.\n\n @return projectPayer The project payer contract.\n */\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external override returns (IJBProjectPayer projectPayer) {\n // Deploy the project payer.\n projectPayer = new JBETHERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner\n );\n\n emit DeployProjectPayer(\n projectPayer,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner,\n msg.sender\n );\n }\n}\n" + "contracts/JBGasTokenERC20ProjectPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './interfaces/IJBGasTokenERC20ProjectPayerDeployer.sol';\nimport './JBGasTokenERC20ProjectPayer.sol';\n\n/** \n @notice \n Deploys project payer contracts.\n\n @dev\n Adheres to -\n IJBGasTokenERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBGasTokenERC20ProjectPayerDeployer is IJBGasTokenERC20ProjectPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new project payer contract.\n\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the project payer contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the project payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the project payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the project payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the project payer.\n\n @return projectPayer The project payer contract.\n */\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external override returns (IJBProjectPayer projectPayer) {\n // Deploy the project payer.\n projectPayer = new JBGasTokenERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner\n );\n\n emit DeployProjectPayer(\n projectPayer,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner,\n msg.sender\n );\n }\n}\n" }, - "contracts/interfaces/IJBETHERC20ProjectPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBDirectory.sol';\nimport './IJBProjectPayer.sol';\n\ninterface IJBETHERC20ProjectPayerDeployer {\n event DeployProjectPayer(\n IJBProjectPayer indexed projectPayer,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n IJBDirectory directory,\n address owner,\n address caller\n );\n\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external returns (IJBProjectPayer projectPayer);\n}\n" + "contracts/interfaces/IJBGasTokenERC20ProjectPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBDirectory.sol';\nimport './IJBProjectPayer.sol';\n\ninterface IJBGasTokenERC20ProjectPayerDeployer {\n event DeployProjectPayer(\n IJBProjectPayer indexed projectPayer,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n IJBDirectory directory,\n address owner,\n address caller\n );\n\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external returns (IJBProjectPayer projectPayer);\n}\n" }, "contracts/interfaces/IJBTerminalUtility.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBDirectory.sol';\n\ninterface IJBPaymentTerminalUtility {\n function directory() external view returns (IJBDirectory);\n}\n" }, - "contracts/JBETHERC20SplitsPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './interfaces/IJBETHERC20SplitsPayerDeployer.sol';\nimport './structs/JBSplit.sol';\nimport './structs/JBGroupedSplits.sol';\nimport './JBETHERC20SplitsPayer.sol';\n\n/** \n @notice \n Deploys splits payer contracts.\n\n @dev\n Adheres to -\n IJBETHERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBETHERC20SplitsPayerDeployer is IJBETHERC20SplitsPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @dev\n This contract must have Operator permissions over the SET_SPLITS permission of the specified `_defaultSplitsProjectId`.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplits The splits to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBSplitsPayer splitsPayer) {\n // Use this contract's address as the domain.\n uint256 _domain = uint256(uint160(address(this)));\n\n // Create the random hash using data unique to this instance that'll be used as the storage domain.\n uint256 _group = uint256(keccak256(abi.encodePacked(msg.sender, block.number)));\n\n // Set the splits in the store.\n JBGroupedSplits[] memory _groupedSplits;\n _groupedSplits = new JBGroupedSplits[](1);\n _groupedSplits[0] = JBGroupedSplits(_group, _defaultSplits);\n _splitsStore.set(_defaultSplitsProjectId, _domain, _groupedSplits);\n\n return\n deploySplitsPayer(\n _defaultSplitsProjectId,\n _domain,\n _group,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n }\n\n //*********************************************************************//\n // ---------------------- public transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) public override returns (IJBSplitsPayer splitsPayer) {\n // Deploy the splits payer.\n splitsPayer = new JBETHERC20SplitsPayer(\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeploySplitsPayer(\n splitsPayer,\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner,\n msg.sender\n );\n }\n}\n" + "contracts/JBGasTokenERC20SplitsPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './interfaces/IJBGasTokenERC20SplitsPayerDeployer.sol';\nimport './structs/JBSplit.sol';\nimport './structs/JBGroupedSplits.sol';\nimport './JBGasTokenERC20SplitsPayer.sol';\n\n/** \n @notice \n Deploys splits payer contracts.\n\n @dev\n Adheres to -\n IJBGasTokenERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBGasTokenERC20SplitsPayerDeployer is IJBGasTokenERC20SplitsPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @dev\n This contract must have Operator permissions over the SET_SPLITS permission of the specified `_defaultSplitsProjectId`.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplits The splits to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBSplitsPayer splitsPayer) {\n // Use this contract's address as the domain.\n uint256 _domain = uint256(uint160(address(this)));\n\n // Create the random hash using data unique to this instance that'll be used as the storage domain.\n uint256 _group = uint256(keccak256(abi.encodePacked(msg.sender, block.number)));\n\n // Set the splits in the store.\n JBGroupedSplits[] memory _groupedSplits;\n _groupedSplits = new JBGroupedSplits[](1);\n _groupedSplits[0] = JBGroupedSplits(_group, _defaultSplits);\n _splitsStore.set(_defaultSplitsProjectId, _domain, _groupedSplits);\n\n return\n deploySplitsPayer(\n _defaultSplitsProjectId,\n _domain,\n _group,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n }\n\n //*********************************************************************//\n // ---------------------- public transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) public override returns (IJBSplitsPayer splitsPayer) {\n // Deploy the splits payer.\n splitsPayer = new JBGasTokenERC20SplitsPayer(\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeploySplitsPayer(\n splitsPayer,\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner,\n msg.sender\n );\n }\n}\n" }, - "contracts/interfaces/IJBETHERC20SplitsPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBSplitsPayer.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBETHERC20SplitsPayerDeployer {\n event DeploySplitsPayer(\n IJBSplitsPayer indexed splitsPayer,\n uint256 defaultSplitsProjectId,\n uint256 defaultSplitsDomain,\n uint256 defaultSplitsGroup,\n IJBSplitsStore splitsStore,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n address owner,\n address caller\n );\n\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string calldata _defaultMemo,\n bytes calldata _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n}\n" + "contracts/interfaces/IJBGasTokenERC20SplitsPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBSplitsPayer.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBGasTokenERC20SplitsPayerDeployer {\n event DeploySplitsPayer(\n IJBSplitsPayer indexed splitsPayer,\n uint256 defaultSplitsProjectId,\n uint256 defaultSplitsDomain,\n uint256 defaultSplitsGroup,\n IJBSplitsStore splitsStore,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n address owner,\n address caller\n );\n\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string calldata _defaultMemo,\n bytes calldata _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n}\n" }, "contracts/system_tests/TestDistributeHeldFee.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.6;\n\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport '@paulrberg/contracts/math/PRBMathUD60x18.sol';\n\nimport './helpers/TestBaseWorkflow.sol';\n\ncontract TestDistributeHeldFee is TestBaseWorkflow {\n JBController private _controller;\n JBETHPaymentTerminal private _terminal;\n JBTokenStore private _tokenStore;\n\n JBProjectMetadata private _projectMetadata;\n JBFundingCycleData private _data;\n JBFundingCycleMetadata private _metadata;\n JBGroupedSplits[] private _groupedSplits; // Default empty\n JBFundAccessConstraints[] private _fundAccessConstraints; // Default empty\n IJBPaymentTerminal[] private _terminals; // Default empty\n\n uint256 private _projectId;\n address private _projectOwner;\n uint256 private _weight = 1000 * 10**18;\n uint256 private _targetInWei = 10 * 10**18;\n\n function setUp() public override {\n super.setUp();\n\n _controller = jbController();\n _terminal = jbETHPaymentTerminal();\n _tokenStore = jbTokenStore();\n\n _projectMetadata = JBProjectMetadata({content: 'myIPFSHash', domain: 1});\n\n _data = JBFundingCycleData({\n duration: 14,\n weight: _weight,\n discountRate: 450000000,\n ballot: IJBFundingCycleBallot(address(0))\n });\n\n _metadata = JBFundingCycleMetadata({\n global: JBGlobalFundingCycleMetadata({\n allowSetTerminals: false,\n allowSetController: false,\n pauseTransfers: false\n }),\n reservedRate: 0,\n redemptionRate: 10000, //100%\n ballotRedemptionRate: 0,\n pausePay: false,\n pauseDistributions: false,\n pauseRedeem: false,\n pauseBurn: false,\n allowMinting: false,\n allowTerminalMigration: false,\n allowControllerMigration: false,\n holdFees: true,\n preferClaimedTokenOverride: false,\n useTotalOverflowForRedemptions: false,\n useDataSourceForPay: false,\n useDataSourceForRedeem: false,\n dataSource: address(0),\n metadata: 0\n });\n\n _terminals.push(_terminal);\n\n _fundAccessConstraints.push(\n JBFundAccessConstraints({\n terminal: _terminal,\n token: jbLibraries().ETHToken(),\n distributionLimit: _targetInWei, // 10 ETH target\n overflowAllowance: 5 ether,\n distributionLimitCurrency: 1, // Currency = ETH\n overflowAllowanceCurrency: 1\n })\n );\n\n _projectOwner = multisig();\n\n _projectId = _controller.launchProjectFor(\n _projectOwner,\n _projectMetadata,\n _data,\n _metadata,\n block.timestamp,\n _groupedSplits,\n _fundAccessConstraints,\n _terminals,\n ''\n );\n }\n\n function testHeldFeeReimburse(\n uint256 payAmountInWei,\n uint16 fee,\n uint256 feeDiscount\n ) external {\n // Assuming we don't revert when distributing too much\n evm.assume(payAmountInWei <= _targetInWei);\n // Avoid rounding error\n evm.assume(payAmountInWei > 1);\n evm.assume(feeDiscount <= jbLibraries().MAX_FEE());\n evm.assume(fee <= 50_000_000); // fee cap\n address _userWallet = address(1234);\n\n evm.prank(multisig());\n _terminal.setFee(fee);\n\n IJBFeeGauge feeGauge = IJBFeeGauge(address(69696969));\n evm.etch(address(feeGauge), new bytes(0x1));\n evm.mockCall(\n address(feeGauge),\n abi.encodeWithSignature('currentDiscountFor(uint256)', _projectId),\n abi.encode(feeDiscount)\n );\n evm.prank(multisig());\n _terminal.setFeeGauge(feeGauge);\n\n uint256 discountedFee = fee - PRBMath.mulDiv(fee, feeDiscount, jbLibraries().MAX_FEE());\n\n // -- pay --\n _terminal.pay{value: payAmountInWei}(\n _projectId,\n payAmountInWei,\n address(0),\n /* _beneficiary */\n _userWallet,\n /* _minReturnedTokens */\n 0,\n /* _preferClaimedTokens */\n false,\n /* _memo */\n 'Take my money!',\n /* _delegateMetadata */\n new bytes(0)\n );\n\n // verify: beneficiary should have a balance of JBTokens\n uint256 _userTokenBalance = PRBMathUD60x18.mul(payAmountInWei, _weight);\n assertEq(_tokenStore.balanceOf(_userWallet, _projectId), _userTokenBalance);\n\n // verify: ETH balance in terminal should be up to date\n uint256 _terminalBalanceInWei = payAmountInWei;\n assertEq(jbPaymentTerminalStore().balanceOf(_terminal, _projectId), _terminalBalanceInWei);\n\n // -- distribute --\n _terminal.distributePayoutsOf(\n _projectId,\n payAmountInWei,\n jbLibraries().ETH(),\n address(0), //token (unused)\n /*min out*/\n 0,\n /*LFG*/\n 'lfg'\n );\n\n // verify: should have held the fee\n if (fee > 0) {\n assertEq(_terminal.heldFeesOf(_projectId)[0].fee, _terminal.fee());\n assertEq(_terminal.heldFeesOf(_projectId)[0].feeDiscount, feeDiscount);\n assertEq(_terminal.heldFeesOf(_projectId)[0].amount, payAmountInWei);\n }\n\n // -- add to balance --\n // Will get the fee reimbursed:\n uint256 heldFee = payAmountInWei -\n PRBMath.mulDiv(\n payAmountInWei,\n jbLibraries().MAX_FEE(),\n discountedFee + jbLibraries().MAX_FEE()\n ); // no discount\n uint256 balanceBefore = jbPaymentTerminalStore().balanceOf(_terminal, _projectId);\n _terminal.addToBalanceOf{value: payAmountInWei}(\n _projectId,\n payAmountInWei,\n address(0),\n 'thanks for all the fish',\n /* _delegateMetadata */\n new bytes(0)\n );\n\n // verify: project should get the fee back (plus the addToBalance amount)\n assertEq(\n jbPaymentTerminalStore().balanceOf(_terminal, _projectId),\n balanceBefore + heldFee + payAmountInWei\n );\n }\n\n function testFeeGetsHeldSpecialCase() public {\n uint256 feeDiscount = 0;\n uint256 fee = 50_000_000;\n uint256 payAmountInWei = 1000000000; // The same value as 100% in the split (makes it easy to leave `1` left over)\n\n JBSplit[] memory _jbSplits = new JBSplit[](1);\n _jbSplits[0] = JBSplit(\n false,\n false,\n 1000000000 - 1, // We make it so there is exactly `1` left over (note: change the subtraction to be anything else than 1 for this test to pass)\n 0,\n payable(address(5)),\n 0,\n IJBSplitAllocator(address(0))\n );\n\n JBGroupedSplits[] memory _groupedSplitsLocal = new JBGroupedSplits[](1);\n\n _groupedSplitsLocal[0] = JBGroupedSplits(_terminal.payoutSplitsGroup(), _jbSplits);\n\n _projectId = _controller.launchProjectFor(\n _projectOwner,\n _projectMetadata,\n _data,\n _metadata,\n block.timestamp,\n _groupedSplitsLocal,\n _fundAccessConstraints,\n _terminals,\n ''\n );\n\n address _userWallet = address(1234);\n evm.deal(_userWallet, payAmountInWei);\n evm.prank(multisig());\n _terminal.setFee(fee);\n\n IJBFeeGauge feeGauge = IJBFeeGauge(address(69696969));\n evm.etch(address(feeGauge), new bytes(0x1));\n evm.mockCall(\n address(feeGauge),\n abi.encodeWithSignature('currentDiscountFor(uint256)', _projectId),\n abi.encode(feeDiscount)\n );\n evm.prank(multisig());\n _terminal.setFeeGauge(feeGauge);\n\n // -- pay --\n _terminal.pay{value: payAmountInWei}(\n _projectId,\n payAmountInWei,\n address(0),\n /* _beneficiary */\n _userWallet,\n /* _minReturnedTokens */\n 0,\n /* _preferClaimedTokens */\n false,\n /* _memo */\n 'Take my money!',\n /* _delegateMetadata */\n new bytes(0)\n );\n\n // verify: ETH balance in terminal should be up to date\n uint256 _terminalBalanceInWei = payAmountInWei;\n assertEq(jbPaymentTerminalStore().balanceOf(_terminal, _projectId), _terminalBalanceInWei);\n\n // -- distribute --\n _terminal.distributePayoutsOf(\n _projectId,\n payAmountInWei,\n jbLibraries().ETH(),\n address(0), //token (unused)\n /*min out*/\n 0,\n /*LFG*/\n 'lfg'\n );\n\n // Verify that a fee was held\n assertEq(_terminal.heldFeesOf(_projectId).length, 1);\n\n // verify: should have held the fee\n assertEq(_terminal.heldFeesOf(_projectId)[0].fee, _terminal.fee());\n assertEq(_terminal.heldFeesOf(_projectId)[0].feeDiscount, feeDiscount);\n assertEq(_terminal.heldFeesOf(_projectId)[0].amount, payAmountInWei);\n }\n}\n" @@ -383,7 +383,7 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.6;\n\nimport './helpers/TestBaseWorkflow.sol';\n\ncontract TestERC20Terminal is TestBaseWorkflow {\n JBController controller;\n JBProjectMetadata _projectMetadata;\n JBFundingCycleData _data;\n JBFundingCycleMetadata _metadata;\n JBGroupedSplits[] _groupedSplits;\n JBFundAccessConstraints[] _fundAccessConstraints;\n IJBPaymentTerminal[] _terminals;\n JBTokenStore _tokenStore;\n address _projectOwner;\n\n uint256 WEIGHT = 1000 * 10**18;\n\n function setUp() public override {\n super.setUp();\n\n _projectOwner = multisig();\n\n _tokenStore = jbTokenStore();\n\n controller = jbController();\n\n _projectMetadata = JBProjectMetadata({content: 'myIPFSHash', domain: 1});\n\n _data = JBFundingCycleData({\n duration: 14,\n weight: WEIGHT,\n discountRate: 450000000,\n ballot: IJBFundingCycleBallot(address(0))\n });\n\n _metadata = JBFundingCycleMetadata({\n global: JBGlobalFundingCycleMetadata({\n allowSetTerminals: false,\n allowSetController: false,\n pauseTransfers: false\n }),\n reservedRate: 5000, //50%\n redemptionRate: 5000, //50%\n ballotRedemptionRate: 0,\n pausePay: false,\n pauseDistributions: false,\n pauseRedeem: false,\n pauseBurn: false,\n allowMinting: false,\n allowTerminalMigration: false,\n allowControllerMigration: false,\n holdFees: false,\n preferClaimedTokenOverride: false,\n useTotalOverflowForRedemptions: false,\n useDataSourceForPay: false,\n useDataSourceForRedeem: false,\n dataSource: address(0),\n metadata: 0\n });\n\n _terminals.push(jbERC20PaymentTerminal());\n }\n\n function testAllowanceERC20() public {\n JBERC20PaymentTerminal terminal = jbERC20PaymentTerminal();\n\n _fundAccessConstraints.push(\n JBFundAccessConstraints({\n terminal: terminal,\n token: address(jbToken()),\n distributionLimit: 10 * 10**18,\n overflowAllowance: 5 * 10**18,\n distributionLimitCurrency: jbLibraries().ETH(),\n overflowAllowanceCurrency: jbLibraries().ETH()\n })\n );\n\n uint256 projectId = controller.launchProjectFor(\n _projectOwner,\n _projectMetadata,\n _data,\n _metadata,\n block.timestamp,\n _groupedSplits,\n _fundAccessConstraints,\n _terminals,\n ''\n );\n\n address caller = msg.sender;\n evm.label(caller, 'caller');\n evm.prank(_projectOwner);\n jbToken().transfer(caller, 20 * 10**18);\n\n evm.prank(caller); // back to regular msg.sender (bug?)\n jbToken().approve(address(terminal), 20 * 10**18);\n evm.prank(caller); // back to regular msg.sender (bug?)\n terminal.pay(\n projectId,\n 20 * 10**18,\n address(0),\n msg.sender,\n 0,\n false,\n 'Forge test',\n new bytes(0)\n ); // funding target met and 10 token are now in the overflow\n\n // verify: beneficiary should have a balance of JBTokens (divided by 2 -> reserved rate = 50%)\n uint256 _userTokenBalance = PRBMath.mulDiv(20, WEIGHT, 2); // 18dec is in WEIGHT\n assertEq(_tokenStore.balanceOf(msg.sender, projectId), _userTokenBalance);\n\n // verify: balance in terminal should be up to date\n assertEq(jbPaymentTerminalStore().balanceOf(terminal, projectId), 20 * 10**18);\n\n // Discretionary use of overflow allowance by project owner (allowance = 5ETH)\n evm.prank(_projectOwner); // Prank only next call\n terminal.useAllowanceOf(\n projectId,\n 5 * 10**18,\n 1, // Currency\n address(0), //token (unused)\n 0, // Min wei out\n payable(msg.sender), // Beneficiary\n 'MEMO'\n );\n assertEq(\n jbToken().balanceOf(msg.sender),\n PRBMath.mulDiv(5 * 10**18, jbLibraries().MAX_FEE(), jbLibraries().MAX_FEE() + terminal.fee())\n );\n\n // Distribute the funding target ETH -> splits[] is empty -> everything in left-over, to project owner\n uint256 initBalance = jbToken().balanceOf(_projectOwner);\n evm.prank(_projectOwner);\n terminal.distributePayoutsOf(\n projectId,\n 10 * 10**18,\n 1, // Currency\n address(0), //token (unused)\n 0, // Min wei out\n 'Foundry payment' // Memo\n );\n // Funds leaving the ecosystem -> fee taken\n assertEq(\n jbToken().balanceOf(_projectOwner),\n initBalance +\n (10 * 10**18 * jbLibraries().MAX_FEE()) /\n (terminal.fee() + jbLibraries().MAX_FEE())\n );\n\n // redeem eth from the overflow by the token holder:\n uint256 senderBalance = _tokenStore.balanceOf(msg.sender, projectId);\n evm.prank(msg.sender);\n terminal.redeemTokensOf(\n msg.sender,\n projectId,\n senderBalance,\n address(0), //token (unused)\n 0,\n payable(msg.sender),\n 'gimme my money back',\n new bytes(0)\n );\n\n // verify: beneficiary should have a balance of 0 JBTokens\n assertEq(_tokenStore.balanceOf(msg.sender, projectId), 0);\n }\n\n function testFuzzedAllowanceERC20(\n uint232 ALLOWANCE,\n uint232 TARGET,\n uint96 BALANCE\n ) public {\n evm.assume(jbToken().totalSupply() >= BALANCE);\n\n JBERC20PaymentTerminal terminal = jbERC20PaymentTerminal();\n\n _fundAccessConstraints.push(\n JBFundAccessConstraints({\n terminal: terminal,\n token: address(jbToken()),\n distributionLimit: TARGET,\n overflowAllowance: ALLOWANCE,\n distributionLimitCurrency: jbLibraries().ETH(),\n overflowAllowanceCurrency: jbLibraries().ETH()\n })\n );\n\n uint256 projectId = controller.launchProjectFor(\n _projectOwner,\n _projectMetadata,\n _data,\n _metadata,\n block.timestamp,\n _groupedSplits,\n _fundAccessConstraints,\n _terminals,\n ''\n );\n\n address caller = msg.sender;\n evm.label(caller, 'caller');\n evm.prank(_projectOwner);\n jbToken().transfer(caller, BALANCE);\n\n evm.prank(caller); // back to regular msg.sender (bug?)\n jbToken().approve(address(terminal), BALANCE);\n evm.prank(caller); // back to regular msg.sender (bug?)\n terminal.pay(projectId, BALANCE, address(0), msg.sender, 0, false, 'Forge test', new bytes(0)); // funding target met and 10 ETH are now in the overflow\n\n // verify: beneficiary should have a balance of JBTokens (divided by 2 -> reserved rate = 50%)\n uint256 _userTokenBalance = PRBMath.mulDiv(BALANCE, (WEIGHT / 10**18), 2);\n if (BALANCE != 0) assertEq(_tokenStore.balanceOf(msg.sender, projectId), _userTokenBalance);\n\n // verify: ETH balance in terminal should be up to date\n assertEq(jbPaymentTerminalStore().balanceOf(terminal, projectId), BALANCE);\n\n bool willRevert;\n\n // Discretionary use of overflow allowance by project owner (allowance = 5ETH)\n if (ALLOWANCE == 0) {\n evm.expectRevert(abi.encodeWithSignature('INADEQUATE_CONTROLLER_ALLOWANCE()'));\n willRevert = true;\n } else if (TARGET >= BALANCE || ALLOWANCE > (BALANCE - TARGET)) {\n // Too much to withdraw or no overflow ?\n evm.expectRevert(abi.encodeWithSignature('INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE()'));\n willRevert = true;\n }\n\n evm.prank(_projectOwner); // Prank only next call\n terminal.useAllowanceOf(\n projectId,\n ALLOWANCE,\n 1, // Currency\n address(0), //token (unused)\n 0, // Min wei out\n payable(msg.sender), // Beneficiary\n 'MEMO'\n );\n\n if (BALANCE > 1 && !willRevert)\n assertEq(\n jbToken().balanceOf(msg.sender),\n PRBMath.mulDiv(ALLOWANCE, jbLibraries().MAX_FEE(), jbLibraries().MAX_FEE() + terminal.fee())\n );\n\n // Distribute the funding target ETH -> no split then beneficiary is the project owner\n uint256 initBalance = jbToken().balanceOf(_projectOwner);\n\n if (TARGET > BALANCE)\n evm.expectRevert(abi.encodeWithSignature('INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE()'));\n\n if (TARGET == 0)\n evm.expectRevert(abi.encodeWithSignature('DISTRIBUTION_AMOUNT_LIMIT_REACHED()'));\n\n evm.prank(_projectOwner);\n terminal.distributePayoutsOf(\n projectId,\n TARGET,\n 1, // Currency\n address(0), //token (unused)\n 0, // Min wei out\n 'Foundry payment' // Memo\n );\n // Funds leaving the ecosystem -> fee taken\n if (TARGET <= BALANCE && TARGET > 1)\n assertEq(\n jbToken().balanceOf(_projectOwner),\n initBalance +\n PRBMath.mulDiv(TARGET, jbLibraries().MAX_FEE(), terminal.fee() + jbLibraries().MAX_FEE())\n );\n\n // redeem eth from the overflow by the token holder:\n uint256 senderBalance = _tokenStore.balanceOf(msg.sender, projectId);\n\n evm.prank(msg.sender);\n terminal.redeemTokensOf(\n msg.sender,\n projectId,\n senderBalance,\n address(0), //token (unused)\n 0,\n payable(msg.sender),\n 'gimme my token back',\n new bytes(0)\n );\n\n // verify: beneficiary should have a balance of 0 JBTokens\n assertEq(_tokenStore.balanceOf(msg.sender, projectId), 0);\n }\n}\n" }, "contracts/system_tests/TestDelegates.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.6;\n\nimport './helpers/TestBaseWorkflow.sol';\n\ncontract TestDelegates is TestBaseWorkflow {\n JBController controller;\n JBProjectMetadata _projectMetadata;\n JBFundingCycleData _data;\n JBFundingCycleMetadata _metadata;\n JBGroupedSplits[] _groupedSplits;\n JBFundAccessConstraints[] _fundAccessConstraints;\n IJBPaymentTerminal[] _terminals;\n JBTokenStore _tokenStore;\n\n address _projectOwner;\n address _beneficiary;\n address _datasource = address(bytes20(keccak256('datasource')));\n\n uint256 _projectId;\n\n uint256 WEIGHT = 1000 * 10**18;\n\n function setUp() public override {\n super.setUp();\n\n _projectOwner = multisig();\n\n _beneficiary = beneficiary();\n\n _tokenStore = jbTokenStore();\n\n controller = jbController();\n\n _projectMetadata = JBProjectMetadata({content: 'myIPFSHash', domain: 1});\n\n _data = JBFundingCycleData({\n duration: 14,\n weight: WEIGHT,\n discountRate: 450000000,\n ballot: IJBFundingCycleBallot(address(0))\n });\n\n _metadata = JBFundingCycleMetadata({\n global: JBGlobalFundingCycleMetadata({\n allowSetTerminals: false,\n allowSetController: false,\n pauseTransfers: false\n }),\n reservedRate: 5000, //50%\n redemptionRate: 5000, //50%\n ballotRedemptionRate: 0,\n pausePay: false,\n pauseDistributions: false,\n pauseRedeem: false,\n pauseBurn: false,\n allowMinting: false,\n allowTerminalMigration: false,\n allowControllerMigration: false,\n holdFees: false,\n preferClaimedTokenOverride: false,\n useTotalOverflowForRedemptions: false,\n useDataSourceForPay: true,\n useDataSourceForRedeem: true,\n dataSource: _datasource,\n metadata: 0\n });\n\n _terminals.push(jbETHPaymentTerminal());\n _projectId = controller.launchProjectFor(\n _projectOwner,\n _projectMetadata,\n _data,\n _metadata,\n block.timestamp,\n _groupedSplits,\n _fundAccessConstraints,\n _terminals,\n ''\n );\n }\n\n function testPayDelegates(uint128[] memory payDelegateAmounts) public {\n JBPayDelegateAllocation[] memory _allocations = new JBPayDelegateAllocation[](\n payDelegateAmounts.length\n );\n address _beneficiary = address(bytes20(keccak256('beneficiary')));\n uint256 _paySum;\n\n // Check that we are not going to overflow uint256 and calculate the total pay amount\n for (uint256 i = 0; i < payDelegateAmounts.length; i++) {\n evm.assume(type(uint256).max - _paySum > payDelegateAmounts[i]);\n _paySum += payDelegateAmounts[i];\n }\n\n // We can't do a pay without paying\n evm.assume(_paySum > 0);\n\n (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata) = controller\n .currentFundingCycleOf(_projectId);\n for (uint256 i = 0; i < payDelegateAmounts.length; i++) {\n address _delegateAddress = address(bytes20(keccak256(abi.encodePacked('PayDelegate', i))));\n\n _allocations[i] = JBPayDelegateAllocation(\n IJBPayDelegate(_delegateAddress),\n payDelegateAmounts[i]\n );\n\n bytes memory _metadata;\n JBDidPayData memory _data = JBDidPayData(\n _beneficiary,\n _projectId,\n fundingCycle.configuration,\n JBTokenAmount(\n JBTokens.ETH,\n _paySum,\n JBSingleTokenPaymentTerminal(address(_terminals[0])).decimals(),\n JBSingleTokenPaymentTerminal(address(_terminals[0])).currency()\n ),\n JBTokenAmount(\n JBTokens.ETH,\n payDelegateAmounts[i],\n JBSingleTokenPaymentTerminal(address(_terminals[0])).decimals(),\n JBSingleTokenPaymentTerminal(address(_terminals[0])).currency()\n ),\n 0,\n _beneficiary,\n false,\n '',\n _metadata\n );\n\n // Mock the delegate\n evm.mockCall(_delegateAddress, abi.encodeWithSelector(IJBPayDelegate.didPay.selector), '');\n\n // Assert that the delegate gets called with the expected value\n evm.expectCall(\n _delegateAddress,\n payDelegateAmounts[i],\n abi.encodeWithSelector(IJBPayDelegate.didPay.selector, _data)\n );\n\n // Expect an event to be emitted for every delegate\n evm.expectEmit(true, true, true, true);\n emit DelegateDidPay(\n IJBPayDelegate(_delegateAddress),\n _data,\n payDelegateAmounts[i],\n _beneficiary\n );\n }\n\n evm.mockCall(\n _datasource,\n abi.encodeWithSelector(IJBFundingCycleDataSource.payParams.selector),\n abi.encode(\n 0, // weight\n '', // memo\n _allocations // allocations\n )\n );\n\n evm.deal(_beneficiary, _paySum);\n evm.prank(_beneficiary);\n _terminals[0].pay{value: _paySum}(\n _projectId,\n _paySum,\n address(0),\n _beneficiary,\n 0,\n false,\n 'Forge test',\n new bytes(0)\n );\n }\n\n event DelegateDidPay(\n IJBPayDelegate indexed delegate,\n JBDidPayData data,\n uint256 delegatedAmount,\n address caller\n );\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.6;\n\nimport './helpers/TestBaseWorkflow.sol';\n\ncontract TestDelegates is TestBaseWorkflow {\n JBController controller;\n JBProjectMetadata _projectMetadata;\n JBFundingCycleData _data;\n JBFundingCycleMetadata _metadata;\n JBGroupedSplits[] _groupedSplits;\n JBFundAccessConstraints[] _fundAccessConstraints;\n IJBPaymentTerminal[] _terminals;\n JBTokenStore _tokenStore;\n\n address _projectOwner;\n address _beneficiary;\n address _datasource = address(bytes20(keccak256('datasource')));\n\n uint256 _projectId;\n\n uint256 WEIGHT = 1000 * 10**18;\n\n function setUp() public override {\n super.setUp();\n\n _projectOwner = multisig();\n\n _beneficiary = beneficiary();\n\n _tokenStore = jbTokenStore();\n\n controller = jbController();\n\n _projectMetadata = JBProjectMetadata({content: 'myIPFSHash', domain: 1});\n\n _data = JBFundingCycleData({\n duration: 14,\n weight: WEIGHT,\n discountRate: 450000000,\n ballot: IJBFundingCycleBallot(address(0))\n });\n\n _metadata = JBFundingCycleMetadata({\n global: JBGlobalFundingCycleMetadata({\n allowSetTerminals: false,\n allowSetController: false,\n pauseTransfers: false\n }),\n reservedRate: 5000, //50%\n redemptionRate: 5000, //50%\n ballotRedemptionRate: 0,\n pausePay: false,\n pauseDistributions: false,\n pauseRedeem: false,\n pauseBurn: false,\n allowMinting: false,\n allowTerminalMigration: false,\n allowControllerMigration: false,\n holdFees: false,\n preferClaimedTokenOverride: false,\n useTotalOverflowForRedemptions: false,\n useDataSourceForPay: true,\n useDataSourceForRedeem: true,\n dataSource: _datasource,\n metadata: 0\n });\n\n _terminals.push(jbETHPaymentTerminal());\n _projectId = controller.launchProjectFor(\n _projectOwner,\n _projectMetadata,\n _data,\n _metadata,\n block.timestamp,\n _groupedSplits,\n _fundAccessConstraints,\n _terminals,\n ''\n );\n }\n\n function testPayDelegates(uint128[] memory payDelegateAmounts) public {\n JBPayDelegateAllocation[] memory _allocations = new JBPayDelegateAllocation[](\n payDelegateAmounts.length\n );\n address _beneficiary = address(bytes20(keccak256('beneficiary')));\n uint256 _paySum;\n\n // Check that we are not going to overflow uint256 and calculate the total pay amount\n for (uint256 i = 0; i < payDelegateAmounts.length; i++) {\n evm.assume(type(uint256).max - _paySum > payDelegateAmounts[i]);\n _paySum += payDelegateAmounts[i];\n }\n\n // We can't do a pay without paying\n evm.assume(_paySum > 0);\n\n (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata) = controller\n .currentFundingCycleOf(_projectId);\n for (uint256 i = 0; i < payDelegateAmounts.length; i++) {\n address _delegateAddress = address(bytes20(keccak256(abi.encodePacked('PayDelegate', i))));\n\n _allocations[i] = JBPayDelegateAllocation(\n IJBPayDelegate(_delegateAddress),\n payDelegateAmounts[i]\n );\n\n bytes memory _metadata;\n JBDidPayData memory _data = JBDidPayData(\n _beneficiary,\n _projectId,\n fundingCycle.configuration,\n JBTokenAmount(\n JBTokens.GAS_TOKEN,\n _paySum,\n JBSingleTokenPaymentTerminal(address(_terminals[0])).decimals(),\n JBSingleTokenPaymentTerminal(address(_terminals[0])).currency()\n ),\n JBTokenAmount(\n JBTokens.GAS_TOKEN,\n payDelegateAmounts[i],\n JBSingleTokenPaymentTerminal(address(_terminals[0])).decimals(),\n JBSingleTokenPaymentTerminal(address(_terminals[0])).currency()\n ),\n 0,\n _beneficiary,\n false,\n '',\n _metadata\n );\n\n // Mock the delegate\n evm.mockCall(_delegateAddress, abi.encodeWithSelector(IJBPayDelegate.didPay.selector), '');\n\n // Assert that the delegate gets called with the expected value\n evm.expectCall(\n _delegateAddress,\n payDelegateAmounts[i],\n abi.encodeWithSelector(IJBPayDelegate.didPay.selector, _data)\n );\n\n // Expect an event to be emitted for every delegate\n evm.expectEmit(true, true, true, true);\n emit DelegateDidPay(\n IJBPayDelegate(_delegateAddress),\n _data,\n payDelegateAmounts[i],\n _beneficiary\n );\n }\n\n evm.mockCall(\n _datasource,\n abi.encodeWithSelector(IJBFundingCycleDataSource.payParams.selector),\n abi.encode(\n 0, // weight\n '', // memo\n _allocations // allocations\n )\n );\n\n evm.deal(_beneficiary, _paySum);\n evm.prank(_beneficiary);\n _terminals[0].pay{value: _paySum}(\n _projectId,\n _paySum,\n address(0),\n _beneficiary,\n 0,\n false,\n 'Forge test',\n new bytes(0)\n );\n }\n\n event DelegateDidPay(\n IJBPayDelegate indexed delegate,\n JBDidPayData data,\n uint256 delegatedAmount,\n address caller\n );\n}\n" }, "contracts/system_tests/TestAllowance.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.6;\n\nimport './helpers/TestBaseWorkflow.sol';\n\ncontract TestAllowance is TestBaseWorkflow {\n JBController controller;\n JBProjectMetadata _projectMetadata;\n JBFundingCycleData _data;\n JBFundingCycleMetadata _metadata;\n JBGroupedSplits[] _groupedSplits;\n JBFundAccessConstraints[] _fundAccessConstraints;\n IJBPaymentTerminal[] _terminals;\n JBTokenStore _tokenStore;\n address _projectOwner;\n address _beneficiary;\n\n uint256 WEIGHT = 1000 * 10**18;\n\n function setUp() public override {\n super.setUp();\n\n _projectOwner = multisig();\n\n _beneficiary = beneficiary();\n\n _tokenStore = jbTokenStore();\n\n controller = jbController();\n\n _projectMetadata = JBProjectMetadata({content: 'myIPFSHash', domain: 1});\n\n _data = JBFundingCycleData({\n duration: 14,\n weight: WEIGHT,\n discountRate: 450000000,\n ballot: IJBFundingCycleBallot(address(0))\n });\n\n _metadata = JBFundingCycleMetadata({\n global: JBGlobalFundingCycleMetadata({\n allowSetTerminals: false,\n allowSetController: false,\n pauseTransfers: false\n }),\n reservedRate: 5000, //50%\n redemptionRate: 5000, //50%\n ballotRedemptionRate: 0,\n pausePay: false,\n pauseDistributions: false,\n pauseRedeem: false,\n pauseBurn: false,\n allowMinting: false,\n allowTerminalMigration: false,\n allowControllerMigration: false,\n holdFees: false,\n preferClaimedTokenOverride: false,\n useTotalOverflowForRedemptions: false,\n useDataSourceForPay: false,\n useDataSourceForRedeem: false,\n dataSource: address(0),\n metadata: 0\n });\n\n _terminals.push(jbETHPaymentTerminal());\n }\n\n function testAllowance() public {\n JBETHPaymentTerminal terminal = jbETHPaymentTerminal();\n\n _fundAccessConstraints.push(\n JBFundAccessConstraints({\n terminal: terminal,\n token: jbLibraries().ETHToken(),\n distributionLimit: 10 ether,\n overflowAllowance: 5 ether,\n distributionLimitCurrency: jbLibraries().ETH(),\n overflowAllowanceCurrency: jbLibraries().ETH()\n })\n );\n\n uint256 projectId = controller.launchProjectFor(\n _projectOwner,\n _projectMetadata,\n _data,\n _metadata,\n block.timestamp,\n _groupedSplits,\n _fundAccessConstraints,\n _terminals,\n ''\n );\n\n terminal.pay{value: 20 ether}(\n projectId,\n 20 ether,\n address(0),\n _beneficiary,\n 0,\n false,\n 'Forge test',\n new bytes(0)\n ); // funding target met and 10 ETH are now in the overflow\n\n // verify: beneficiary should have a balance of JBTokens (divided by 2 -> reserved rate = 50%)\n uint256 _userTokenBalance = PRBMath.mulDiv(20 ether, (WEIGHT / 10**18), 2);\n assertEq(_tokenStore.balanceOf(_beneficiary, projectId), _userTokenBalance);\n\n // verify: ETH balance in terminal should be up to date\n assertEq(jbPaymentTerminalStore().balanceOf(terminal, projectId), 20 ether);\n\n // Discretionary use of overflow allowance by project owner (allowance = 5ETH)\n evm.prank(_projectOwner); // Prank only next call\n terminal.useAllowanceOf(\n projectId,\n 5 ether,\n 1, // Currency\n address(0), //token (unused)\n 0, // Min wei out\n payable(_beneficiary), // Beneficiary\n 'MEMO'\n );\n assertEq(\n (_beneficiary).balance,\n PRBMath.mulDiv(5 ether, jbLibraries().MAX_FEE(), jbLibraries().MAX_FEE() + terminal.fee())\n );\n\n // Distribute the funding target ETH -> splits[] is empty -> everything in left-over, to project owner\n evm.prank(_projectOwner);\n terminal.distributePayoutsOf(\n projectId,\n 10 ether,\n 1, // Currency\n address(0), //token (unused)\n 0, // Min wei out\n 'Foundry payment' // Memo\n );\n assertEq(\n _projectOwner.balance,\n (10 ether * jbLibraries().MAX_FEE()) / (terminal.fee() + jbLibraries().MAX_FEE())\n );\n\n // redeem eth from the overflow by the token holder:\n uint256 senderBalance = _tokenStore.balanceOf(_beneficiary, projectId);\n evm.prank(_beneficiary);\n terminal.redeemTokensOf(\n _beneficiary,\n projectId,\n senderBalance,\n address(0), //token (unused)\n 0,\n payable(_beneficiary),\n 'gimme my money back',\n new bytes(0)\n );\n\n // verify: beneficiary should have a balance of 0 JBTokens\n assertEq(_tokenStore.balanceOf(_beneficiary, projectId), 0);\n }\n\n function testFuzzAllowance(\n uint232 ALLOWANCE,\n uint232 TARGET,\n uint96 BALANCE\n ) public {\n evm.assume(jbToken().totalSupply() >= BALANCE);\n\n unchecked {\n // Check for overflow\n evm.assume(ALLOWANCE + TARGET >= ALLOWANCE && ALLOWANCE + TARGET >= TARGET);\n }\n\n uint256 CURRENCY = jbLibraries().ETH(); // Avoid testing revert on this call...\n\n JBETHPaymentTerminal terminal = jbETHPaymentTerminal();\n\n _fundAccessConstraints.push(\n JBFundAccessConstraints({\n terminal: terminal,\n token: jbLibraries().ETHToken(),\n distributionLimit: TARGET,\n distributionLimitCurrency: CURRENCY,\n overflowAllowance: ALLOWANCE,\n overflowAllowanceCurrency: CURRENCY\n })\n );\n\n uint256 projectId = controller.launchProjectFor(\n _projectOwner,\n _projectMetadata,\n _data,\n _metadata,\n block.timestamp,\n _groupedSplits,\n _fundAccessConstraints,\n _terminals,\n ''\n );\n\n terminal.pay{value: BALANCE}(\n projectId,\n BALANCE,\n address(0),\n _beneficiary,\n 0,\n false,\n 'Forge test',\n new bytes(0)\n );\n\n // verify: beneficiary should have a balance of JBTokens (divided by 2 -> reserved rate = 50%)\n uint256 _userTokenBalance = PRBMath.mulDiv(BALANCE, (WEIGHT / 10**18), 2);\n if (BALANCE != 0) assertEq(_tokenStore.balanceOf(_beneficiary, projectId), _userTokenBalance);\n\n // verify: ETH balance in terminal should be up to date\n assertEq(jbPaymentTerminalStore().balanceOf(terminal, projectId), BALANCE);\n\n evm.startPrank(_projectOwner);\n\n bool willRevert;\n\n if (ALLOWANCE == 0) {\n evm.expectRevert(abi.encodeWithSignature('INADEQUATE_CONTROLLER_ALLOWANCE()'));\n willRevert = true;\n } else if (TARGET >= BALANCE || ALLOWANCE > (BALANCE - TARGET)) {\n // Too much to withdraw or no overflow ?\n evm.expectRevert(abi.encodeWithSignature('INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE()'));\n willRevert = true;\n }\n terminal.useAllowanceOf(\n projectId,\n ALLOWANCE,\n CURRENCY, // Currency\n address(0), //token (unused)\n 0, // Min wei out\n payable(_beneficiary), // Beneficiary\n 'MEMO'\n );\n\n if (\n !willRevert && BALANCE != 0 // if allowance ==0 or not enough overflow (target>=balance, allowance > overflow) // there is something to transfer\n )\n assertEq(\n (_beneficiary).balance,\n PRBMath.mulDiv(ALLOWANCE, jbLibraries().MAX_FEE(), jbLibraries().MAX_FEE() + terminal.fee())\n );\n\n if (TARGET > BALANCE)\n evm.expectRevert(abi.encodeWithSignature('INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE()'));\n\n if (TARGET == 0)\n evm.expectRevert(abi.encodeWithSignature('DISTRIBUTION_AMOUNT_LIMIT_REACHED()'));\n\n terminal.distributePayoutsOf(\n projectId,\n TARGET,\n 1, // Currency\n address(0), //token (unused)\n 0, // Min wei out\n 'Foundry payment' // Memo\n );\n if (TARGET <= BALANCE && TARGET > 1)\n // Avoid rounding error\n assertEq(\n _projectOwner.balance,\n (TARGET * jbLibraries().MAX_FEE()) / (terminal.fee() + jbLibraries().MAX_FEE())\n );\n }\n}\n" diff --git a/deployments/mainnet/solcInputs/87acdcf5deeaa43ae3ecf62f45455645.json b/deployments/mainnet/solcInputs/87acdcf5deeaa43ae3ecf62f45455645.json index fb4b1dc1f..06d3a1f67 100644 --- a/deployments/mainnet/solcInputs/87acdcf5deeaa43ae3ecf62f45455645.json +++ b/deployments/mainnet/solcInputs/87acdcf5deeaa43ae3ecf62f45455645.json @@ -119,13 +119,13 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport './abstract/JBOperatable.sol';\nimport './interfaces/IJBDirectory.sol';\nimport './libraries/JBGlobalFundingCycleMetadataResolver.sol';\nimport './libraries/JBOperations.sol';\n\n/**\n @notice\n Keeps a reference of which terminal contracts each project is currently accepting funds through, and which controller contract is managing each project's tokens and funding cycles.\n\n @dev\n Adheres to -\n IJBDirectory: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\ncontract JBDirectory is IJBDirectory, JBOperatable, Ownable {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBGlobalFundingCycleMetadataResolver for uint8;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error DUPLICATE_TERMINALS();\n error INVALID_PROJECT_ID_IN_DIRECTORY();\n error SET_CONTROLLER_NOT_ALLOWED();\n error SET_TERMINALS_NOT_ALLOWED();\n error TOKEN_NOT_ACCEPTED();\n\n //*********************************************************************//\n // --------------------- private stored properties ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n For each project ID, the terminals that are currently managing its funds.\n\n _projectId The ID of the project to get terminals of.\n */\n mapping(uint256 => IJBPaymentTerminal[]) private _terminalsOf;\n\n /**\n @notice\n The project's primary terminal for a token.\n\n _projectId The ID of the project to get the primary terminal of.\n _token The token to get the project's primary terminal of.\n */\n mapping(uint256 => mapping(address => IJBPaymentTerminal)) private _primaryTerminalOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n For each project ID, the controller that manages how terminals interact with tokens and funding cycles.\n\n _projectId The ID of the project to get the controller of.\n */\n mapping(uint256 => address) public override controllerOf;\n\n /**\n @notice\n Addresses that can set a project's first controller on their behalf. These addresses/contracts have been vetted and verified by this contract's owner.\n\n _address The address that is either allowed or not.\n */\n mapping(address => bool) public override isAllowedToSetFirstController;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n For each project ID, the terminals that are currently managing its funds.\n\n @param _projectId The ID of the project to get terminals of.\n\n @return An array of terminal addresses.\n */\n function terminalsOf(uint256 _projectId)\n external\n view\n override\n returns (IJBPaymentTerminal[] memory)\n {\n return _terminalsOf[_projectId];\n }\n\n /**\n @notice\n The primary terminal that is managing funds for a project for a specified token.\n\n @dev\n The zero address is returned if a terminal isn't found for the specified token.\n\n @param _projectId The ID of the project to get a terminal for.\n @param _token The token the terminal accepts.\n\n @return The primary terminal for the project for the specified token.\n */\n function primaryTerminalOf(uint256 _projectId, address _token)\n external\n view\n override\n returns (IJBPaymentTerminal)\n {\n // If a primary terminal for the token was specifically set and its one of the project's terminals, return it.\n if (\n _primaryTerminalOf[_projectId][_token] != IJBPaymentTerminal(address(0)) &&\n isTerminalOf(_projectId, _primaryTerminalOf[_projectId][_token])\n ) return _primaryTerminalOf[_projectId][_token];\n\n // Return the first terminal which accepts the specified token.\n for (uint256 _i; _i < _terminalsOf[_projectId].length; _i++) {\n IJBPaymentTerminal _terminal = _terminalsOf[_projectId][_i];\n if (_terminal.acceptsToken(_token, _projectId)) return _terminal;\n }\n\n // Not found.\n return IJBPaymentTerminal(address(0));\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Whether or not a specified terminal is a terminal of the specified project.\n\n @param _projectId The ID of the project to check within.\n @param _terminal The address of the terminal to check for.\n\n @return A flag indicating whether or not the specified terminal is a terminal of the specified project.\n */\n function isTerminalOf(uint256 _projectId, IJBPaymentTerminal _terminal)\n public\n view\n override\n returns (bool)\n {\n for (uint256 _i; _i < _terminalsOf[_projectId].length; _i++)\n if (_terminalsOf[_projectId][_i] == _terminal) return true;\n return false;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _owner The address that will own the contract.\n */\n constructor(\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBFundingCycleStore _fundingCycleStore,\n address _owner\n ) JBOperatable(_operatorStore) {\n projects = _projects;\n fundingCycleStore = _fundingCycleStore;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Update the controller that manages how terminals interact with the ecosystem.\n\n @dev\n A controller can be set if:\n - the message sender is the project owner or an operator having the correct authorization.\n - the message sender is the project's current controller.\n - or, an allowedlisted address is setting a controller for a project that doesn't already have a controller.\n\n @param _projectId The ID of the project to set a new controller for.\n @param _controller The new controller to set.\n */\n function setControllerOf(uint256 _projectId, address _controller)\n external\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.SET_CONTROLLER,\n (msg.sender == address(controllerOf[_projectId]) ||\n (isAllowedToSetFirstController[msg.sender] && controllerOf[_projectId] == address(0)))\n )\n {\n // The project must exist.\n if (projects.count() < _projectId) revert INVALID_PROJECT_ID_IN_DIRECTORY();\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Setting controller is allowed if called from the current controller, or if the project doesn't have a current controller, or if the project's funding cycle allows setting the controller. Revert otherwise.\n if (\n msg.sender != address(controllerOf[_projectId]) &&\n controllerOf[_projectId] != address(0) &&\n !uint8(_fundingCycle.metadata >> 8).setControllerAllowed()\n ) revert SET_CONTROLLER_NOT_ALLOWED();\n\n // Set the new controller.\n controllerOf[_projectId] = _controller;\n\n emit SetController(_projectId, _controller, msg.sender);\n }\n\n /** \n @notice \n Set a project's terminals.\n\n @dev\n Only a project owner, an operator, or its controller can set its terminals.\n\n @param _projectId The ID of the project having terminals set.\n @param _terminals The terminal to set.\n */\n function setTerminalsOf(uint256 _projectId, IJBPaymentTerminal[] calldata _terminals)\n external\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.SET_TERMINALS,\n msg.sender == address(controllerOf[_projectId])\n )\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Setting terminals must be allowed if not called from the current controller.\n if (\n msg.sender != address(controllerOf[_projectId]) &&\n !uint8(_fundingCycle.metadata >> 8).setTerminalsAllowed()\n ) revert SET_TERMINALS_NOT_ALLOWED();\n\n // Delete the stored terminals for the project.\n _terminalsOf[_projectId] = _terminals;\n\n // Make sure duplicates were not added.\n if (_terminals.length > 1)\n for (uint256 _i; _i < _terminals.length; _i++)\n for (uint256 _j = _i + 1; _j < _terminals.length; _j++)\n if (_terminals[_i] == _terminals[_j]) revert DUPLICATE_TERMINALS();\n\n emit SetTerminals(_projectId, _terminals, msg.sender);\n }\n\n /**\n @notice\n Project's can set which terminal should be their primary for a particular token.\n This is useful in case a project has several terminals connected for a particular token.\n\n @dev\n The terminal will be set as the primary terminal where ecosystem contracts should route tokens.\n\n @dev\n If setting a newly added terminal and the funding cycle doesn't allow new terminals, the caller must be the current controller.\n\n @param _projectId The ID of the project for which a primary token is being set.\n @param _token The token to set the primary terminal of.\n @param _terminal The terminal to make primary.\n */\n function setPrimaryTerminalOf(\n uint256 _projectId,\n address _token,\n IJBPaymentTerminal _terminal\n )\n external\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.SET_PRIMARY_TERMINAL)\n {\n // Can't set the primary terminal for a token if it doesn't accept the token.\n if (!_terminal.acceptsToken(_token, _projectId)) revert TOKEN_NOT_ACCEPTED();\n\n // Add the terminal to the project if it hasn't been already.\n _addTerminalIfNeeded(_projectId, _terminal);\n\n // Store the terminal as the primary for the particular token.\n _primaryTerminalOf[_projectId][_token] = _terminal;\n\n emit SetPrimaryTerminal(_projectId, _token, _terminal, msg.sender);\n }\n\n /** \n @notice\t\n Set a contract to the list of trusted addresses that can set a first controller for any project.\t\n\n @dev\n The owner can add addresses which are allowed to change projects' first controllers. \n These addresses are known and vetted controllers as well as contracts designed to launch new projects. \n A project can set its own controller without it being on the allow list.\n\n @dev\n If you would like an address/contract allowlisted, please reach out to the contract owner.\n\n @param _address The address to allow or revoke allowance from.\n @param _flag Whether allowance is being added or revoked.\n */\n function setIsAllowedToSetFirstController(address _address, bool _flag)\n external\n override\n onlyOwner\n {\n // Set the flag in the allowlist.\n isAllowedToSetFirstController[_address] = _flag;\n\n emit SetIsAllowedToSetFirstController(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Add a terminal to a project's list of terminals if it hasn't been already.\n\n @param _projectId The ID of the project having a terminal added.\n @param _terminal The terminal to add.\n */\n function _addTerminalIfNeeded(uint256 _projectId, IJBPaymentTerminal _terminal) private {\n // Check that the terminal has not already been added.\n if (isTerminalOf(_projectId, _terminal)) return;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Setting terminals must be allowed if not called from the current controller.\n if (\n msg.sender != address(controllerOf[_projectId]) &&\n !uint8(_fundingCycle.metadata >> 8).setTerminalsAllowed()\n ) revert SET_TERMINALS_NOT_ALLOWED();\n\n // Add the new terminal.\n _terminalsOf[_projectId].push(_terminal);\n\n emit AddTerminal(_projectId, _terminal, msg.sender);\n }\n}\n" }, "contracts/JBETHPaymentTerminal.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n JBTokens.ETH,\n 18, // 18 decimals.\n JBCurrencies.ETH,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal pure override {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n JBTokens.GAS_TOKEN,\n 18, // 18 decimals.\n JBCurrencies.GAS_CURRENCY,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal pure override {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n}\n" }, "contracts/JBERC20PaymentTerminal.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\n\n/** \n @notice \n Manages the inflows and outflows of an ERC-20 token.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\ncontract JBERC20PaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n IERC20Metadata _token,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n address(_token),\n _token.decimals(),\n _currency,\n _baseWeightCurrency,\n _payoutSplitsGroup,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from == address(this)\n ? IERC20(token).transfer(_to, _amount)\n : IERC20(token).transferFrom(_from, _to, _amount);\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal override {\n IERC20(token).approve(_to, _amount);\n }\n}\n" }, "contracts/JBSingleTokenPaymentTerminalStore.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBSingleTokenPaymentTerminalStore is IJBSingleTokenPaymentTerminalStore, ReentrancyGuard {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n Mint's 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegate A delegate contract to use for subsequent calls.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n IJBPayDelegate delegate,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay()) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegate) = IJBFundingCycleDataSource(fundingCycle.dataSource()).payParams(\n _data\n );\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegate, memo);\n\n // Add the amount to the token balance of the project.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount.value;\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegate, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegate A delegate contract to use for subsequent calls.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n IJBRedemptionDelegate delegate,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\n _projectId,\n fundingCycle.reservedRate()\n );\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow > 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem()) {\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n fundingCycle.redemptionRate(),\n fundingCycle.ballotRedemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegate) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .redeemParams(_data);\n } else {\n memo = _memo;\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (reclaimAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (reclaimAmount > 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n reclaimAmount;\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n return _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i = 0; _i < _terminals.length; _i++)\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.ETH\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.ETH, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBSingleTokenPaymentTerminalStore is IJBSingleTokenPaymentTerminalStore, ReentrancyGuard {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n Mint's 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegate A delegate contract to use for subsequent calls.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n IJBPayDelegate delegate,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay()) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegate) = IJBFundingCycleDataSource(fundingCycle.dataSource()).payParams(\n _data\n );\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegate, memo);\n\n // Add the amount to the token balance of the project.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount.value;\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegate, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegate A delegate contract to use for subsequent calls.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n IJBRedemptionDelegate delegate,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\n _projectId,\n fundingCycle.reservedRate()\n );\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow > 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem()) {\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n fundingCycle.redemptionRate(),\n fundingCycle.ballotRedemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegate) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .redeemParams(_data);\n } else {\n memo = _memo;\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (reclaimAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (reclaimAmount > 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n reclaimAmount;\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n return _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i = 0; _i < _terminals.length; _i++)\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.GAS_CURRENCY\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.GAS_CURRENCY, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" }, "contracts/JBFundingCycleStore.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './abstract/JBControllerUtility.sol';\nimport './libraries/JBConstants.sol';\n\n/** \n @notice \n Manages funding cycle configurations and scheduling.\n\n @dev\n Adheres to -\n IJBTokenStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBControllerUtility: Includes convenience functionality for checking if the message sender is the current controller of the project whose data is being manipulated.\n*/\ncontract JBFundingCycleStore is IJBFundingCycleStore, JBControllerUtility {\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_DISCOUNT_RATE();\n error INVALID_DURATION();\n error INVALID_WEIGHT();\n error NO_SAME_BLOCK_RECONFIGURATION();\n\n //*********************************************************************//\n // --------------------- private stored properties ------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Stores the user defined properties of each funding cycle, packed into one storage slot.\n\n _projectId The ID of the project to get properties of.\n _configuration The funding cycle configuration to get properties of.\n */\n mapping(uint256 => mapping(uint256 => uint256)) private _packedUserPropertiesOf;\n\n /** \n @notice\n Stores the properties added by the mechanism to manage and schedule each funding cycle, packed into one storage slot.\n \n _projectId The ID of the project to get instrinsic properties of.\n _configuration The funding cycle configuration to get properties of.\n */\n mapping(uint256 => mapping(uint256 => uint256)) private _packedIntrinsicPropertiesOf;\n\n /** \n @notice\n Stores the metadata for each funding cycle configuration, packed into one storage slot.\n\n _projectId The ID of the project to get metadata of.\n _configuration The funding cycle configuration to get metadata of.\n */\n mapping(uint256 => mapping(uint256 => uint256)) private _metadataOf;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The latest funding cycle configuration for each project.\n\n _projectId The ID of the project to get the latest funding cycle configuration of.\n */\n mapping(uint256 => uint256) public override latestConfigurationOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice \n Get the funding cycle with the given configuration for the specified project.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n @param _configuration The configuration of the funding cycle to get.\n\n @return fundingCycle The funding cycle.\n */\n function get(uint256 _projectId, uint256 _configuration)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle)\n {\n return _getStructFor(_projectId, _configuration);\n }\n\n /**\n @notice \n The latest funding cycle to be configured for the specified project, and its current ballot state.\n\n @param _projectId The ID of the project to get the latest configured funding cycle of.\n\n @return fundingCycle The project's queued funding cycle.\n @return ballotState The state of the ballot for the reconfiguration.\n */\n function latestConfiguredOf(uint256 _projectId)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle, JBBallotState ballotState)\n {\n // Get a reference to the latest funding cycle configuration.\n uint256 _fundingCycleConfiguration = latestConfigurationOf[_projectId];\n\n // Resolve the funding cycle for the latest configuration.\n fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n // Resolve the ballot state.\n ballotState = _ballotStateOf(\n _projectId,\n fundingCycle.configuration,\n fundingCycle.start,\n fundingCycle.basedOn\n );\n }\n\n /**\n @notice \n The funding cycle that's next up for the specified project.\n\n @dev\n If a queued funding cycle of the project is not found, returns an empty funding cycle with all properties set to 0.\n\n @param _projectId The ID of the project to get the queued funding cycle of.\n\n @return fundingCycle The project's queued funding cycle.\n */\n function queuedOf(uint256 _projectId)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle)\n {\n // If the project does not have a funding cycle, return an empty struct.\n if (latestConfigurationOf[_projectId] == 0) return _getStructFor(0, 0);\n\n // Get a reference to the configuration of the standby funding cycle.\n uint256 _standbyFundingCycleConfiguration = _standbyOf(_projectId);\n\n // If it exists, return its funding cycle if it is approved.\n if (_standbyFundingCycleConfiguration > 0) {\n fundingCycle = _getStructFor(_projectId, _standbyFundingCycleConfiguration);\n\n if (_isApproved(_projectId, fundingCycle)) return fundingCycle;\n\n // Resolve the funding cycle for the latest configured funding cycle.\n fundingCycle = _getStructFor(_projectId, fundingCycle.basedOn);\n } else {\n // Resolve the funding cycle for the latest configured funding cycle.\n fundingCycle = _getStructFor(_projectId, latestConfigurationOf[_projectId]);\n\n // If the latest funding cycle starts in the future, it must start in the distant future\n // since its not in standby. In this case base the queued cycles on the base cycle.\n if (fundingCycle.start > block.timestamp)\n fundingCycle = _getStructFor(_projectId, fundingCycle.basedOn);\n }\n\n // There's no queued if the current has a duration of 0.\n if (fundingCycle.duration == 0) return _getStructFor(0, 0);\n\n // Check to see if this funding cycle's ballot is approved.\n // If so, return a funding cycle based on it.\n if (_isApproved(_projectId, fundingCycle)) return _mockFundingCycleBasedOn(fundingCycle, false);\n\n // Get the funding cycle of its base funding cycle, which carries the last approved configuration.\n fundingCycle = _getStructFor(_projectId, fundingCycle.basedOn);\n\n // There's no queued if the base, which must still be the current, has a duration of 0.\n if (fundingCycle.duration == 0) return _getStructFor(0, 0);\n\n // Return a mock of the next up funding cycle.\n return _mockFundingCycleBasedOn(fundingCycle, false);\n }\n\n /**\n @notice \n The funding cycle that is currently active for the specified project.\n\n @dev\n If a current funding cycle of the project is not found, returns an empty funding cycle with all properties set to 0.\n\n @param _projectId The ID of the project to get the current funding cycle of.\n\n @return fundingCycle The project's current funding cycle.\n */\n function currentOf(uint256 _projectId)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle)\n {\n // If the project does not have a funding cycle, return an empty struct.\n if (latestConfigurationOf[_projectId] == 0) return _getStructFor(0, 0);\n\n // Get a reference to the configuration of the eligible funding cycle.\n uint256 _fundingCycleConfiguration = _eligibleOf(_projectId);\n\n // Keep a reference to the eligible funding cycle.\n JBFundingCycle memory _fundingCycle;\n\n // If an eligible funding cycle exists...\n if (_fundingCycleConfiguration > 0) {\n // Resolve the funding cycle for the eligible configuration.\n _fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n // Check to see if this funding cycle's ballot is approved.\n // If so, return it.\n if (_isApproved(_projectId, _fundingCycle)) return _fundingCycle;\n\n // If it hasn't been approved, set the funding cycle configuration to be the configuration of the funding cycle that it's based on,\n // which carries the last approved configuration.\n _fundingCycleConfiguration = _fundingCycle.basedOn;\n } else {\n // No upcoming funding cycle found that is eligible to become active,\n // so use the last configuration.\n _fundingCycleConfiguration = latestConfigurationOf[_projectId];\n\n // Get the funding cycle for the latest ID.\n _fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n // If it's not approved or if it hasn't yet started, get a reference to the funding cycle that the latest is based on, which has the latest approved configuration.\n if (!_isApproved(_projectId, _fundingCycle) || block.timestamp < _fundingCycle.start)\n _fundingCycleConfiguration = _fundingCycle.basedOn;\n }\n\n // If there is not funding cycle to base the current one on, there can't be a current one.\n if (_fundingCycleConfiguration == 0) return _getStructFor(0, 0);\n\n // The funding cycle to base a current one on.\n _fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n // If the base has no duration, it's still the current one.\n if (_fundingCycle.duration == 0) return _fundingCycle;\n\n // Return a mock of the current funding cycle.\n return _mockFundingCycleBasedOn(_fundingCycle, true);\n }\n\n /** \n @notice \n The current ballot state of the project.\n\n @param _projectId The ID of the project to check the ballot state of.\n\n @return The project's current ballot's state.\n */\n function currentBallotStateOf(uint256 _projectId) external view override returns (JBBallotState) {\n // Get a reference to the latest funding cycle configuration.\n uint256 _fundingCycleConfiguration = latestConfigurationOf[_projectId];\n\n // Resolve the funding cycle for the latest configuration.\n JBFundingCycle memory _fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n return\n _ballotStateOf(\n _projectId,\n _fundingCycle.configuration,\n _fundingCycle.start,\n _fundingCycle.basedOn\n );\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _directory A contract storing directories of terminals and controllers for each project.\n */\n // solhint-disable-next-line no-empty-blocks\n constructor(IJBDirectory _directory) JBControllerUtility(_directory) {}\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice \n Configures the next eligible funding cycle for the specified project.\n\n @dev\n Only a project's current controller can configure its funding cycles.\n\n @param _projectId The ID of the project being configured.\n @param _data The funding cycle configuration data.\n @param _metadata Arbitrary extra data to associate with this funding cycle configuration that's not used within.\n @param _mustStartAtOrAfter The time before which the initialized funding cycle cannot start.\n\n @return The funding cycle that the configuration will take effect during.\n */\n function configureFor(\n uint256 _projectId,\n JBFundingCycleData calldata _data,\n uint256 _metadata,\n uint256 _mustStartAtOrAfter\n ) external override onlyController(_projectId) returns (JBFundingCycle memory) {\n // Duration must fit in a uint64.\n if (_data.duration > type(uint64).max) revert INVALID_DURATION();\n\n // Discount rate must be less than or equal to 100%.\n if (_data.discountRate > JBConstants.MAX_DISCOUNT_RATE) revert INVALID_DISCOUNT_RATE();\n\n // Weight must fit into a uint88.\n if (_data.weight > type(uint88).max) revert INVALID_WEIGHT();\n\n // The configuration timestamp is now.\n uint256 _configuration = block.timestamp;\n\n // Set up a reconfiguration by configuring intrinsic properties.\n _configureIntrinsicPropertiesFor(\n _projectId,\n _configuration,\n _data.weight,\n // Must start on or after the current timestamp.\n _mustStartAtOrAfter > block.timestamp ? _mustStartAtOrAfter : block.timestamp\n );\n\n // Efficiently stores a funding cycles provided user defined properties.\n // If all user config properties are zero, no need to store anything as the default value will have the same outcome.\n if (\n _data.ballot != IJBFundingCycleBallot(address(0)) ||\n _data.duration > 0 ||\n _data.discountRate > 0\n ) {\n // ballot in bits 0-159 bytes.\n uint256 packed = uint160(address(_data.ballot));\n\n // duration in bits 160-223 bytes.\n packed |= _data.duration << 160;\n\n // discountRate in bits 224-255 bytes.\n packed |= _data.discountRate << 224;\n\n // Set in storage.\n _packedUserPropertiesOf[_projectId][_configuration] = packed;\n }\n\n // Set the metadata if needed.\n if (_metadata > 0) _metadataOf[_projectId][_configuration] = _metadata;\n\n emit Configure(_configuration, _projectId, _data, _metadata, _mustStartAtOrAfter, msg.sender);\n\n // Return the funding cycle for the new configuration.\n return _getStructFor(_projectId, _configuration);\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice \n Updates the configurable funding cycle for this project if it exists, otherwise creates one.\n\n @param _projectId The ID of the project to find a configurable funding cycle for.\n @param _configuration The time at which the funding cycle was configured.\n @param _weight The weight to store in the configured funding cycle.\n @param _mustStartAtOrAfter The time before which the initialized funding cycle can't start.\n */\n function _configureIntrinsicPropertiesFor(\n uint256 _projectId,\n uint256 _configuration,\n uint256 _weight,\n uint256 _mustStartAtOrAfter\n ) private {\n // If there's not yet a funding cycle for the project, initialize one.\n if (latestConfigurationOf[_projectId] == 0)\n // Use an empty funding cycle as the base.\n return\n _initFor(_projectId, _getStructFor(0, 0), _configuration, _mustStartAtOrAfter, _weight);\n\n // Get the active funding cycle's configuration.\n uint256 _currentConfiguration = _eligibleOf(_projectId);\n\n // If an eligible funding cycle does not exist, get a reference to the latest funding cycle configuration for the project.\n if (_currentConfiguration == 0)\n // Get the latest funding cycle's configuration.\n _currentConfiguration = latestConfigurationOf[_projectId];\n\n // Get a reference to the funding cycle.\n JBFundingCycle memory _baseFundingCycle = _getStructFor(_projectId, _currentConfiguration);\n\n if (!_isApproved(_projectId, _baseFundingCycle))\n // If it hasn't been approved, set the ID to be the funding cycle it's based on,\n // which carries the latest approved configuration.\n _baseFundingCycle = _getStructFor(_projectId, _baseFundingCycle.basedOn);\n\n // The configuration can't be the same as the base configuration.\n if (_baseFundingCycle.configuration == _configuration) revert NO_SAME_BLOCK_RECONFIGURATION();\n\n // The time after the ballot of the provided funding cycle has expired.\n // If the provided funding cycle has no ballot, return the current timestamp.\n uint256 _timestampAfterBallot = _baseFundingCycle.ballot == IJBFundingCycleBallot(address(0))\n ? 0\n : _configuration + _baseFundingCycle.ballot.duration();\n\n _initFor(\n _projectId,\n _baseFundingCycle,\n _configuration,\n // Can only start after the ballot.\n _timestampAfterBallot > _mustStartAtOrAfter ? _timestampAfterBallot : _mustStartAtOrAfter,\n _weight\n );\n }\n\n /**\n @notice \n Initializes a funding cycle with the specified properties.\n\n @param _projectId The ID of the project to which the funding cycle being initialized belongs.\n @param _baseFundingCycle The funding cycle to base the initialized one on.\n @param _configuration The configuration of the funding cycle being initialized.\n @param _mustStartAtOrAfter The time before which the initialized funding cycle cannot start.\n @param _weight The weight to give the newly initialized funding cycle.\n */\n function _initFor(\n uint256 _projectId,\n JBFundingCycle memory _baseFundingCycle,\n uint256 _configuration,\n uint256 _mustStartAtOrAfter,\n uint256 _weight\n ) private {\n // If there is no base, initialize a first cycle.\n if (_baseFundingCycle.number == 0) {\n // The first number is 1.\n uint256 _number = 1;\n\n // Set fresh intrinsic properties.\n _packAndStoreIntrinsicPropertiesOf(\n _configuration,\n _projectId,\n _number,\n _weight,\n _baseFundingCycle.configuration,\n _mustStartAtOrAfter\n );\n } else {\n // Derive the correct next start time from the base.\n uint256 _start = _deriveStartFrom(_baseFundingCycle, _mustStartAtOrAfter);\n\n // A weight of 1 is treated as a weight of 0.\n // This is to allow a weight of 0 (default) to represent inheriting the discounted weight of the previous funding cycle.\n _weight = _weight > 0\n ? (_weight == 1 ? 0 : _weight)\n : _deriveWeightFrom(_baseFundingCycle, _start);\n\n // Derive the correct number.\n uint256 _number = _deriveNumberFrom(_baseFundingCycle, _start);\n\n // Update the intrinsic properties.\n _packAndStoreIntrinsicPropertiesOf(\n _configuration,\n _projectId,\n _number,\n _weight,\n _baseFundingCycle.configuration,\n _start\n );\n }\n\n // Set the project's latest funding cycle configuration.\n latestConfigurationOf[_projectId] = _configuration;\n\n emit Init(_configuration, _projectId, _baseFundingCycle.configuration);\n }\n\n /**\n @notice \n Efficiently stores a funding cycle's provided intrinsic properties.\n\n @param _configuration The configuration of the funding cycle to pack and store.\n @param _projectId The ID of the project to which the funding cycle belongs.\n @param _number The number of the funding cycle.\n @param _weight The weight of the funding cycle.\n @param _basedOn The configuration of the base funding cycle.\n @param _start The start time of this funding cycle.\n */\n function _packAndStoreIntrinsicPropertiesOf(\n uint256 _configuration,\n uint256 _projectId,\n uint256 _number,\n uint256 _weight,\n uint256 _basedOn,\n uint256 _start\n ) private {\n // weight in bits 0-87.\n uint256 packed = _weight;\n\n // basedOn in bits 88-143.\n packed |= _basedOn << 88;\n\n // start in bits 144-199.\n packed |= _start << 144;\n\n // number in bits 200-255.\n packed |= _number << 200;\n\n // Store the packed value.\n _packedIntrinsicPropertiesOf[_projectId][_configuration] = packed;\n }\n\n /**\n @notice \n The project's stored funding cycle that hasn't yet started and should be used next, if one exists.\n\n @dev\n A value of 0 is returned if no funding cycle was found.\n\n @dev\n Assumes the project has a latest configuration.\n \n @param _projectId The ID of a project to look through for a standby cycle.\n\n @return configuration The configuration of the standby funding cycle if one exists, or 0 if one doesn't exist.\n */\n function _standbyOf(uint256 _projectId) private view returns (uint256 configuration) {\n // Get a reference to the project's latest funding cycle.\n configuration = latestConfigurationOf[_projectId];\n\n // Get the necessary properties for the latest funding cycle.\n JBFundingCycle memory _fundingCycle = _getStructFor(_projectId, configuration);\n\n // There is no upcoming funding cycle if the latest funding cycle has already started.\n if (block.timestamp >= _fundingCycle.start) return 0;\n\n // If this is the first funding cycle, it is queued.\n if (_fundingCycle.number == 1) return configuration;\n\n // Get the necessary properties for the base funding cycle.\n JBFundingCycle memory _baseFundingCycle = _getStructFor(_projectId, _fundingCycle.basedOn);\n\n // If the latest configuration doesn't start until after another base cycle, return 0.\n if (\n _baseFundingCycle.duration > 0 &&\n block.timestamp < _fundingCycle.start - _baseFundingCycle.duration\n ) return 0;\n }\n\n /**\n @notice \n The project's stored funding cycle that has started and hasn't yet expired.\n \n @dev\n A value of 0 is returned if no funding cycle was found.\n\n @dev\n Assumes the project has a latest configuration.\n\n @param _projectId The ID of the project to look through.\n\n @return configuration The configuration of an eligible funding cycle if one exists, or 0 if one doesn't exist.\n */\n function _eligibleOf(uint256 _projectId) private view returns (uint256 configuration) {\n // Get a reference to the project's latest funding cycle.\n configuration = latestConfigurationOf[_projectId];\n\n // Get the latest funding cycle.\n JBFundingCycle memory _fundingCycle = _getStructFor(_projectId, configuration);\n\n // If the latest is expired, return an empty funding cycle.\n // A duration of 0 cannot be expired.\n if (\n _fundingCycle.duration > 0 && block.timestamp >= _fundingCycle.start + _fundingCycle.duration\n ) return 0;\n\n // Return the funding cycle's configuration if it has started.\n if (block.timestamp >= _fundingCycle.start) return _fundingCycle.configuration;\n\n // Get a reference to the cycle's base configuration.\n JBFundingCycle memory _baseFundingCycle = _getStructFor(_projectId, _fundingCycle.basedOn);\n\n // If the base cycle isn't eligible, the project has no eligible cycle.\n // A duration of 0 is always eligible.\n if (\n _baseFundingCycle.duration > 0 &&\n block.timestamp >= _baseFundingCycle.start + _baseFundingCycle.duration\n ) return 0;\n\n // Return the configuration that the latest funding cycle is based on.\n configuration = _fundingCycle.basedOn;\n }\n\n /** \n @notice \n A view of the funding cycle that would be created based on the provided one if the project doesn't make a reconfiguration.\n\n @dev\n Returns an empty funding cycle if there can't be a mock funding cycle based on the provided one.\n\n @dev\n Assumes a funding cycle with a duration of 0 will never be asked to be the base of a mock.\n\n @param _baseFundingCycle The funding cycle that the resulting funding cycle should follow.\n @param _allowMidCycle A flag indicating if the mocked funding cycle is allowed to already be mid cycle.\n\n @return A mock of what the next funding cycle will be.\n */\n function _mockFundingCycleBasedOn(JBFundingCycle memory _baseFundingCycle, bool _allowMidCycle)\n private\n view\n returns (JBFundingCycle memory)\n {\n // Get the distance of the current time to the start of the next possible funding cycle.\n // If the returned mock cycle must not yet have started, the start time of the mock must be in the future.\n uint256 _mustStartAtOrAfter = !_allowMidCycle\n ? block.timestamp + 1\n : block.timestamp - _baseFundingCycle.duration + 1;\n\n // Derive what the start time should be.\n uint256 _start = _deriveStartFrom(_baseFundingCycle, _mustStartAtOrAfter);\n\n // Derive what the number should be.\n uint256 _number = _deriveNumberFrom(_baseFundingCycle, _start);\n\n return\n JBFundingCycle(\n _number,\n _baseFundingCycle.configuration,\n _baseFundingCycle.basedOn,\n _start,\n _baseFundingCycle.duration,\n _deriveWeightFrom(_baseFundingCycle, _start),\n _baseFundingCycle.discountRate,\n _baseFundingCycle.ballot,\n _baseFundingCycle.metadata\n );\n }\n\n /** \n @notice \n The date that is the nearest multiple of the specified funding cycle's duration from its end.\n\n @param _baseFundingCycle The funding cycle to base the calculation on.\n @param _mustStartAtOrAfter A date that the derived start must be on or come after.\n\n @return start The next start time.\n */\n function _deriveStartFrom(JBFundingCycle memory _baseFundingCycle, uint256 _mustStartAtOrAfter)\n private\n pure\n returns (uint256 start)\n {\n // A subsequent cycle to one with a duration of 0 should start as soon as possible.\n if (_baseFundingCycle.duration == 0) return _mustStartAtOrAfter;\n\n // The time when the funding cycle immediately after the specified funding cycle starts.\n uint256 _nextImmediateStart = _baseFundingCycle.start + _baseFundingCycle.duration;\n\n // If the next immediate start is now or in the future, return it.\n if (_nextImmediateStart >= _mustStartAtOrAfter) return _nextImmediateStart;\n\n // The amount of seconds since the `_mustStartAtOrAfter` time which results in a start time that might satisfy the specified constraints.\n uint256 _timeFromImmediateStartMultiple = (_mustStartAtOrAfter - _nextImmediateStart) %\n _baseFundingCycle.duration;\n\n // A reference to the first possible start timestamp.\n start = _mustStartAtOrAfter - _timeFromImmediateStartMultiple;\n\n // Add increments of duration as necessary to satisfy the threshold.\n while (_mustStartAtOrAfter > start) start = start + _baseFundingCycle.duration;\n }\n\n /** \n @notice \n The accumulated weight change since the specified funding cycle.\n\n @param _baseFundingCycle The funding cycle to base the calculation on.\n @param _start The start time of the funding cycle to derive a number for.\n\n @return weight The derived weight, as a fixed point number with 18 decimals.\n */\n function _deriveWeightFrom(JBFundingCycle memory _baseFundingCycle, uint256 _start)\n private\n pure\n returns (uint256 weight)\n {\n // A subsequent cycle to one with a duration of 0 should have the next possible weight.\n if (_baseFundingCycle.duration == 0)\n return\n PRBMath.mulDiv(\n _baseFundingCycle.weight,\n JBConstants.MAX_DISCOUNT_RATE - _baseFundingCycle.discountRate,\n JBConstants.MAX_DISCOUNT_RATE\n );\n\n // The weight should be based off the base funding cycle's weight.\n weight = _baseFundingCycle.weight;\n\n // If the discount is 0, the weight doesn't change.\n if (_baseFundingCycle.discountRate == 0) return weight;\n\n // The difference between the start of the base funding cycle and the proposed start.\n uint256 _startDistance = _start - _baseFundingCycle.start;\n\n // Apply the base funding cycle's discount rate for each cycle that has passed.\n uint256 _discountMultiple = _startDistance / _baseFundingCycle.duration;\n\n for (uint256 i = 0; i < _discountMultiple; i++) {\n // The number of times to apply the discount rate.\n // Base the new weight on the specified funding cycle's weight.\n weight = PRBMath.mulDiv(\n weight,\n JBConstants.MAX_DISCOUNT_RATE - _baseFundingCycle.discountRate,\n JBConstants.MAX_DISCOUNT_RATE\n );\n // The calculation doesn't need to continue if the weight is 0.\n if (weight == 0) break;\n }\n }\n\n /** \n @notice \n The number of the next funding cycle given the specified funding cycle.\n\n @param _baseFundingCycle The funding cycle to base the calculation on.\n @param _start The start time of the funding cycle to derive a number for.\n\n @return The funding cycle number.\n */\n function _deriveNumberFrom(JBFundingCycle memory _baseFundingCycle, uint256 _start)\n private\n pure\n returns (uint256)\n {\n // A subsequent cycle to one with a duration of 0 should be the next number.\n if (_baseFundingCycle.duration == 0) return _baseFundingCycle.number + 1;\n\n // The difference between the start of the base funding cycle and the proposed start.\n uint256 _startDistance = _start - _baseFundingCycle.start;\n\n // Find the number of base cycles that fit in the start distance.\n return _baseFundingCycle.number + (_startDistance / _baseFundingCycle.duration);\n }\n\n /** \n @notice \n Checks to see if the provided funding cycle is approved according to the correct ballot.\n\n @param _projectId The ID of the project to which the funding cycle belongs. \n @param _fundingCycle The funding cycle to get an approval flag for.\n\n @return The approval flag.\n */\n function _isApproved(uint256 _projectId, JBFundingCycle memory _fundingCycle)\n private\n view\n returns (bool)\n {\n return\n _ballotStateOf(\n _projectId,\n _fundingCycle.configuration,\n _fundingCycle.start,\n _fundingCycle.basedOn\n ) == JBBallotState.Approved;\n }\n\n /**\n @notice \n A project's latest funding cycle configuration approval status.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n @param _configuration The funding cycle configuration to get the ballot state of.\n @param _start The start time of the funding cycle configuration to get the ballot state of.\n @param _ballotFundingCycleConfiguration The configuration of the funding cycle which is configured with the ballot that should be used.\n\n @return The ballot state of the project.\n */\n function _ballotStateOf(\n uint256 _projectId,\n uint256 _configuration,\n uint256 _start,\n uint256 _ballotFundingCycleConfiguration\n ) private view returns (JBBallotState) {\n // If there is no ballot funding cycle, implicitly approve.\n if (_ballotFundingCycleConfiguration == 0) return JBBallotState.Approved;\n\n // Get the ballot funding cycle.\n JBFundingCycle memory _ballotFundingCycle = _getStructFor(\n _projectId,\n _ballotFundingCycleConfiguration\n );\n\n // If there is no ballot, the ID is auto approved.\n // Otherwise if the ballot's duration hasn't passed, its still active.\n // Otherwise, return the ballot's state.\n if (_ballotFundingCycle.ballot == IJBFundingCycleBallot(address(0)))\n return JBBallotState.Approved;\n else if (_ballotFundingCycle.ballot.duration() >= block.timestamp - _configuration)\n return JBBallotState.Active;\n else return _ballotFundingCycle.ballot.stateOf(_projectId, _configuration, _start);\n }\n\n /**\n @notice \n Unpack a funding cycle's packed stored values into an easy-to-work-with funding cycle struct.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n @param _configuration The funding cycle configuration to get the full struct for.\n\n @return fundingCycle A funding cycle struct.\n */\n function _getStructFor(uint256 _projectId, uint256 _configuration)\n private\n view\n returns (JBFundingCycle memory fundingCycle)\n {\n // Return an empty funding cycle if the configuration specified is 0.\n if (_configuration == 0) return fundingCycle;\n\n fundingCycle.configuration = _configuration;\n\n uint256 _packedIntrinsicProperties = _packedIntrinsicPropertiesOf[_projectId][_configuration];\n\n // weight in bits 0-87 bits.\n fundingCycle.weight = uint256(uint88(_packedIntrinsicProperties));\n // basedOn in bits 88-143 bits.\n fundingCycle.basedOn = uint256(uint56(_packedIntrinsicProperties >> 88));\n // start in bits 144-199 bits.\n fundingCycle.start = uint256(uint56(_packedIntrinsicProperties >> 144));\n // number in bits 200-255 bits.\n fundingCycle.number = uint256(uint56(_packedIntrinsicProperties >> 200));\n\n uint256 _packedUserProperties = _packedUserPropertiesOf[_projectId][_configuration];\n\n // ballot in bits 0-159 bits.\n fundingCycle.ballot = IJBFundingCycleBallot(address(uint160(_packedUserProperties)));\n // duration in bits 160-223 bits.\n fundingCycle.duration = uint256(uint64(_packedUserProperties >> 160));\n // discountRate in bits 224-255 bits.\n fundingCycle.discountRate = uint256(uint32(_packedUserProperties >> 224));\n\n fundingCycle.metadata = _metadataOf[_projectId][_configuration];\n }\n}\n" @@ -170,7 +170,7 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './../interfaces/IJBSplitAllocator.sol';\n\n/** \n @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.\n @member preferAddToBalance A flag indicating if a distribution to a project should prefer triggering it's addToBalance function instead of its pay function.\n @member percent The percent of the whole group that this split occupies. This number is out of `JBConstants.SPLITS_TOTAL_PERCENT`.\n @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.\n @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.\n @member lockedUntil Specifies if the split should be unchangeable until the specified time, with the exception of extending the locked period.\n @member allocator If an allocator is specified, funds will be sent to the allocator contract along with all properties of this split.\n*/\nstruct JBSplit {\n bool preferClaimed;\n bool preferAddToBalance;\n uint256 percent;\n uint256 projectId;\n address payable beneficiary;\n uint256 lockedUntil;\n IJBSplitAllocator allocator;\n}\n" }, "contracts/system_tests/helpers/AccessJBLib.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '../../libraries/JBCurrencies.sol';\nimport '../../libraries/JBConstants.sol';\nimport '../../libraries/JBTokens.sol';\n\ncontract AccessJBLib {\n function ETH() external pure returns (uint256) {\n return JBCurrencies.ETH;\n }\n\n function USD() external pure returns (uint256) {\n return JBCurrencies.USD;\n }\n\n function ETHToken() external pure returns (address) {\n return JBTokens.ETH;\n }\n\n function MAX_FEE() external pure returns (uint256) {\n return JBConstants.MAX_FEE;\n }\n\n function SPLITS_TOTAL_PERCENT() external pure returns (uint256) {\n return JBConstants.SPLITS_TOTAL_PERCENT;\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '../../libraries/JBCurrencies.sol';\nimport '../../libraries/JBConstants.sol';\nimport '../../libraries/JBTokens.sol';\n\ncontract AccessJBLib {\n function ETH() external pure returns (uint256) {\n return JBCurrencies.GAS_CURRENCY;\n }\n\n function USD() external pure returns (uint256) {\n return JBCurrencies.USD;\n }\n\n function ETHToken() external pure returns (address) {\n return JBTokens.GAS_TOKEN;\n }\n\n function MAX_FEE() external pure returns (uint256) {\n return JBConstants.MAX_FEE;\n }\n\n function SPLITS_TOTAL_PERCENT() external pure returns (uint256) {\n return JBConstants.SPLITS_TOTAL_PERCENT;\n }\n}\n" }, "@paulrberg/contracts/math/PRBMath.sol": { "content": "// SPDX-License-Identifier: Unlicense\npragma solidity >=0.8.4;\n\nimport \"prb-math/contracts/PRBMath.sol\";\n" @@ -227,7 +227,7 @@ "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" }, "contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBSplitsGroups.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal is\n IJBPayoutRedemptionPaymentTerminal,\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n ReentrancyGuard\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- private stored constants -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 private constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The protocol project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 private constant _PROTOCOL_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- private stored properties ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) private _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId) external view override returns (uint256) {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.ETH)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.ETH, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n ) JBSingleTokenPaymentTerminal(_token, _decimals, _currency) JBOperatable(_operatorStore) {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.ETH) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Process each fee.\n for (uint256 _i = 0; _i < _heldFees.length; _i++) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @dev\n If the fee gauge reverts when called upon while a project is attempting to distribute its funds, a project's funds will be locked. This is a known risk.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual;\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual;\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) private returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegate` only used within scope.\n {\n IJBRedemptionDelegate _delegate;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegate, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If a delegate was returned by the data source, issue a callback to it.\n if (_delegate != IJBRedemptionDelegate(address(0))) {\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _beneficiary,\n _memo,\n _metadata\n );\n _delegate.didRedeem(_data);\n emit DelegateDidRedeem(_delegate, _data, msg.sender);\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) private returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convinience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n\n // Take the fee.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || _feeEligibleDistributionAmount == 0\n ? 0\n : _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n );\n\n // Get a reference to how much to distribute to the project owner, which is the leftover amount minus any fees.\n netLeftoverDistributionAmount = _leftoverDistributionAmount == 0\n ? 0\n : _leftoverDistributionAmount - _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n\n // Transfer any remaining balance to the project owner.\n if (netLeftoverDistributionAmount > 0)\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n ) private returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convinience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) private returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i = 0; _i < _splits.length; _i++) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount;\n\n if (_payoutAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (isFeelessAddress[address(_split.allocator)])\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _netPayoutAmount : 0;\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n _netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // Save gas if this contract is being used as the terminal.\n if (_terminal == this) {\n // This distribution does not incur a fee.\n _netPayoutAmount = _payoutAmount;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\n else\n _pay(\n _netPayoutAmount,\n address(this),\n _split.projectId,\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n } else {\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (isFeelessAddress[address(_terminal)])\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _netPayoutAmount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _terminal.addToBalanceOf{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n '',\n _projectMetadata\n );\n else\n _terminal.pay{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n }\n } else {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(\n address(this),\n _split.beneficiary != address(0) ? _split.beneficiary : payable(msg.sender),\n _netPayoutAmount\n );\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _netPayoutAmount,\n msg.sender\n );\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _PROTOCOL_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) private returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n */\n function _processFee(uint256 _amount, address _beneficiary) private {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_PROTOCOL_PROJECT_ID, token);\n\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\n if (_terminal == this)\n _pay(_amount, address(this), _PROTOCOL_PROJECT_ID, _beneficiary, 0, false, '', bytes('')); // Use the local pay call.\n else {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _amount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _amount : 0;\n\n // Send the payment.\n _terminal.pay{value: _payableValue}(\n _PROTOCOL_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the external pay call of the correct terminal.\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) private returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegate` and `_tokenCount` only used within scope.\n {\n IJBPayDelegate _delegate;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegate, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If a delegate was returned by the data source, issue a callback to it.\n if (_delegate != IJBPayDelegate(address(0))) {\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n _delegate.didPay(_data);\n emit DelegateDidPay(_delegate, _data, msg.sender);\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) private {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n private\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Process each fee.\n for (uint256 _i = 0; _i < _heldFees.length; _i++) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n } else {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n leftoverAmount = 0;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) private pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) private view returns (uint256 feeDiscount) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (directory.primaryTerminalOf(_PROTOCOL_PROJECT_ID, token) == IJBPaymentTerminal(address(0)))\n return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge == IJBFeeGauge(address(0)))\n feeDiscount = 0;\n // If the guage reverts, set the discount to 0.\n else\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n feeDiscount = discount;\n } catch {\n feeDiscount = 0;\n }\n\n // If the fee discount is greater than the max, nullify the discount.\n if (feeDiscount > JBConstants.MAX_FEE_DISCOUNT) feeDiscount = 0;\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBSplitsGroups.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal is\n IJBPayoutRedemptionPaymentTerminal,\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n ReentrancyGuard\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- private stored constants -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 private constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The protocol project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 private constant _PROTOCOL_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- private stored properties ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) private _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId) external view override returns (uint256) {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.GAS_CURRENCY)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.GAS_CURRENCY, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n ) JBSingleTokenPaymentTerminal(_token, _decimals, _currency) JBOperatable(_operatorStore) {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.GAS_TOKEN) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Process each fee.\n for (uint256 _i = 0; _i < _heldFees.length; _i++) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @dev\n If the fee gauge reverts when called upon while a project is attempting to distribute its funds, a project's funds will be locked. This is a known risk.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual;\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual;\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) private returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegate` only used within scope.\n {\n IJBRedemptionDelegate _delegate;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegate, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If a delegate was returned by the data source, issue a callback to it.\n if (_delegate != IJBRedemptionDelegate(address(0))) {\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _beneficiary,\n _memo,\n _metadata\n );\n _delegate.didRedeem(_data);\n emit DelegateDidRedeem(_delegate, _data, msg.sender);\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) private returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convinience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n\n // Take the fee.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || _feeEligibleDistributionAmount == 0\n ? 0\n : _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n );\n\n // Get a reference to how much to distribute to the project owner, which is the leftover amount minus any fees.\n netLeftoverDistributionAmount = _leftoverDistributionAmount == 0\n ? 0\n : _leftoverDistributionAmount - _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n\n // Transfer any remaining balance to the project owner.\n if (netLeftoverDistributionAmount > 0)\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n ) private returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convinience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) private returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i = 0; _i < _splits.length; _i++) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount;\n\n if (_payoutAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (isFeelessAddress[address(_split.allocator)])\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0;\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n _netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // Save gas if this contract is being used as the terminal.\n if (_terminal == this) {\n // This distribution does not incur a fee.\n _netPayoutAmount = _payoutAmount;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\n else\n _pay(\n _netPayoutAmount,\n address(this),\n _split.projectId,\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n } else {\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (isFeelessAddress[address(_terminal)])\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _terminal.addToBalanceOf{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n '',\n _projectMetadata\n );\n else\n _terminal.pay{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n }\n } else {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(\n address(this),\n _split.beneficiary != address(0) ? _split.beneficiary : payable(msg.sender),\n _netPayoutAmount\n );\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _netPayoutAmount,\n msg.sender\n );\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _PROTOCOL_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) private returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n */\n function _processFee(uint256 _amount, address _beneficiary) private {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_PROTOCOL_PROJECT_ID, token);\n\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\n if (_terminal == this)\n _pay(_amount, address(this), _PROTOCOL_PROJECT_ID, _beneficiary, 0, false, '', bytes('')); // Use the local pay call.\n else {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _amount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send the payment.\n _terminal.pay{value: _payableValue}(\n _PROTOCOL_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the external pay call of the correct terminal.\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) private returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegate` and `_tokenCount` only used within scope.\n {\n IJBPayDelegate _delegate;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegate, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If a delegate was returned by the data source, issue a callback to it.\n if (_delegate != IJBPayDelegate(address(0))) {\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n _delegate.didPay(_data);\n emit DelegateDidPay(_delegate, _data, msg.sender);\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) private {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n private\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Process each fee.\n for (uint256 _i = 0; _i < _heldFees.length; _i++) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n } else {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n leftoverAmount = 0;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) private pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) private view returns (uint256 feeDiscount) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (directory.primaryTerminalOf(_PROTOCOL_PROJECT_ID, token) == IJBPaymentTerminal(address(0)))\n return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge == IJBFeeGauge(address(0)))\n feeDiscount = 0;\n // If the guage reverts, set the discount to 0.\n else\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n feeDiscount = discount;\n } catch {\n feeDiscount = 0;\n }\n\n // If the fee discount is greater than the max, nullify the discount.\n if (feeDiscount > JBConstants.MAX_FEE_DISCOUNT) feeDiscount = 0;\n }\n}\n" }, "@openzeppelin/contracts/security/ReentrancyGuard.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n constructor() {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n // On the first call to nonReentrant, _notEntered will be true\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n\n _;\n\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n}\n" @@ -311,31 +311,31 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './IJBFundingCycleBallot.sol';\n\ninterface IJBReconfigurationBufferBallot is IJBFundingCycleBallot {\n event Finalize(\n uint256 indexed projectId,\n uint256 indexed configuration,\n JBBallotState indexed ballotState,\n address caller\n );\n\n function finalState(uint256 _projectId, uint256 _configuration)\n external\n view\n returns (JBBallotState);\n\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\n\n function finalize(uint256 _projectId, uint256 _configured) external returns (JBBallotState);\n}\n" }, "contracts/system_tests/TestEIP165.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './helpers/TestBaseWorkflow.sol';\nimport '../JBReconfigurationBufferBallot.sol';\nimport '../JBETHERC20SplitsPayer.sol';\n\ncontract TestEIP165 is TestBaseWorkflow {\n bytes4 constant notSupportedInterface = 0xffffffff;\n\n uint256 constant projectId = 2;\n uint256 constant splitsProjectID = 3;\n address payable constant splitsBeneficiary = payable(address(420));\n uint256 constant splitsDomain = 1;\n uint256 constant splitsGroup = 1;\n bool constant splitsPreferClaimedTokens = false;\n string constant splitsMemo = '';\n bytes constant splitsMetadata = '';\n bool constant splitsPreferAddToBalance = true;\n address constant splitsOwner = address(420);\n\n function testJBController() public {\n JBController controller = jbController();\n\n // Should support these interfaces\n assertTrue(controller.supportsInterface(type(IERC165).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBController).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBMigratable).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!controller.supportsInterface(notSupportedInterface));\n }\n\n function testJBERC20PaymentTerminal() public {\n JBERC20PaymentTerminal terminal = new JBERC20PaymentTerminal(\n jbToken(),\n jbLibraries().USD(), // currency\n jbLibraries().ETH(), // base weight currency\n 1, // JBSplitsGroupe\n jbOperatorStore(),\n jbProjects(),\n jbDirectory(),\n jbSplitsStore(),\n jbPrices(),\n jbPaymentTerminalStore(),\n multisig()\n );\n\n // Should support these interfaces\n assertTrue(terminal.supportsInterface(type(IERC165).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBRedemptionTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBSingleTokenPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!terminal.supportsInterface(notSupportedInterface));\n }\n\n function testJBETHPaymentTerminal() public {\n JBETHPaymentTerminal terminal = jbETHPaymentTerminal();\n\n // Should support these interfaces\n assertTrue(terminal.supportsInterface(type(IERC165).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBRedemptionTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBSingleTokenPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!terminal.supportsInterface(notSupportedInterface));\n }\n\n function testJBProjects() public {\n JBProjects projects = jbProjects();\n\n // Should support these interfaces\n assertTrue(projects.supportsInterface(type(IERC165).interfaceId));\n assertTrue(projects.supportsInterface(type(IERC721).interfaceId));\n assertTrue(projects.supportsInterface(type(IERC721Metadata).interfaceId));\n assertTrue(projects.supportsInterface(type(IJBProjects).interfaceId));\n assertTrue(projects.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!projects.supportsInterface(notSupportedInterface));\n }\n\n function testJBReconfigurationBufferBallot() public {\n JBReconfigurationBufferBallot ballot = new JBReconfigurationBufferBallot(\n 3000,\n jbFundingCycleStore()\n );\n\n // Should support these interfaces\n assertTrue(ballot.supportsInterface(type(IERC165).interfaceId));\n assertTrue(ballot.supportsInterface(type(IJBReconfigurationBufferBallot).interfaceId));\n assertTrue(ballot.supportsInterface(type(IJBFundingCycleBallot).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!ballot.supportsInterface(notSupportedInterface));\n }\n\n function testJBETHERC20SplitsPayer() public {\n JBETHERC20SplitsPayer splitsPayer = new JBETHERC20SplitsPayer(\n splitsProjectID,\n splitsDomain,\n splitsGroup,\n jbSplitsStore(),\n projectId,\n splitsBeneficiary,\n splitsPreferClaimedTokens,\n splitsMemo,\n splitsMetadata,\n splitsPreferAddToBalance,\n splitsOwner\n );\n\n // Should support these interfaces\n assertTrue(splitsPayer.supportsInterface(type(IERC165).interfaceId));\n assertTrue(splitsPayer.supportsInterface(type(IJBSplitsPayer).interfaceId));\n assertTrue(splitsPayer.supportsInterface(type(IJBProjectPayer).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!splitsPayer.supportsInterface(notSupportedInterface));\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './helpers/TestBaseWorkflow.sol';\nimport '../JBReconfigurationBufferBallot.sol';\nimport '../JBGasTokenERC20SplitsPayer.sol';\n\ncontract TestEIP165 is TestBaseWorkflow {\n bytes4 constant notSupportedInterface = 0xffffffff;\n\n uint256 constant projectId = 2;\n uint256 constant splitsProjectID = 3;\n address payable constant splitsBeneficiary = payable(address(420));\n uint256 constant splitsDomain = 1;\n uint256 constant splitsGroup = 1;\n bool constant splitsPreferClaimedTokens = false;\n string constant splitsMemo = '';\n bytes constant splitsMetadata = '';\n bool constant splitsPreferAddToBalance = true;\n address constant splitsOwner = address(420);\n\n function testJBController() public {\n JBController controller = jbController();\n\n // Should support these interfaces\n assertTrue(controller.supportsInterface(type(IERC165).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBController).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBMigratable).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!controller.supportsInterface(notSupportedInterface));\n }\n\n function testJBERC20PaymentTerminal() public {\n JBERC20PaymentTerminal terminal = new JBERC20PaymentTerminal(\n jbToken(),\n jbLibraries().USD(), // currency\n jbLibraries().ETH(), // base weight currency\n 1, // JBSplitsGroupe\n jbOperatorStore(),\n jbProjects(),\n jbDirectory(),\n jbSplitsStore(),\n jbPrices(),\n jbPaymentTerminalStore(),\n multisig()\n );\n\n // Should support these interfaces\n assertTrue(terminal.supportsInterface(type(IERC165).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBRedemptionTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBSingleTokenPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!terminal.supportsInterface(notSupportedInterface));\n }\n\n function testJBETHPaymentTerminal() public {\n JBETHPaymentTerminal terminal = jbETHPaymentTerminal();\n\n // Should support these interfaces\n assertTrue(terminal.supportsInterface(type(IERC165).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBRedemptionTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBSingleTokenPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!terminal.supportsInterface(notSupportedInterface));\n }\n\n function testJBProjects() public {\n JBProjects projects = jbProjects();\n\n // Should support these interfaces\n assertTrue(projects.supportsInterface(type(IERC165).interfaceId));\n assertTrue(projects.supportsInterface(type(IERC721).interfaceId));\n assertTrue(projects.supportsInterface(type(IERC721Metadata).interfaceId));\n assertTrue(projects.supportsInterface(type(IJBProjects).interfaceId));\n assertTrue(projects.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!projects.supportsInterface(notSupportedInterface));\n }\n\n function testJBReconfigurationBufferBallot() public {\n JBReconfigurationBufferBallot ballot = new JBReconfigurationBufferBallot(\n 3000,\n jbFundingCycleStore()\n );\n\n // Should support these interfaces\n assertTrue(ballot.supportsInterface(type(IERC165).interfaceId));\n assertTrue(ballot.supportsInterface(type(IJBReconfigurationBufferBallot).interfaceId));\n assertTrue(ballot.supportsInterface(type(IJBFundingCycleBallot).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!ballot.supportsInterface(notSupportedInterface));\n }\n\n function testJBGasTokenERC20SplitsPayer() public {\n JBGasTokenERC20SplitsPayer splitsPayer = new JBGasTokenERC20SplitsPayer(\n splitsProjectID,\n splitsDomain,\n splitsGroup,\n jbSplitsStore(),\n projectId,\n splitsBeneficiary,\n splitsPreferClaimedTokens,\n splitsMemo,\n splitsMetadata,\n splitsPreferAddToBalance,\n splitsOwner\n );\n\n // Should support these interfaces\n assertTrue(splitsPayer.supportsInterface(type(IERC165).interfaceId));\n assertTrue(splitsPayer.supportsInterface(type(IJBSplitsPayer).interfaceId));\n assertTrue(splitsPayer.supportsInterface(type(IJBProjectPayer).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!splitsPayer.supportsInterface(notSupportedInterface));\n }\n}\n" }, - "contracts/JBETHERC20SplitsPayer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBSplitsPayer.sol';\nimport './interfaces/IJBSplitsStore.sol';\nimport './libraries/JBConstants.sol';\nimport './JBETHERC20ProjectPayer.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\n\n @dev\n Adheres to -\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBETHERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBETHERC20SplitsPayer is IJBSplitsPayer, JBETHERC20ProjectPayer, ReentrancyGuard {\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The ID of project for which the default splits are stored. \n */\n uint256 public override defaultSplitsProjectId;\n\n /**\n @notice\n The domain within which the default splits are stored. \n */\n uint256 public override defaultSplitsDomain;\n\n /**\n @notice\n The group within which the default splits are stored. \n */\n uint256 public override defaultSplitsGroup;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBETHERC20ProjectPayer, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n )\n JBETHERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _preferAddToBalance,\n _splitsStore.directory(),\n _owner\n )\n {\n defaultSplitsProjectId = _defaultSplitsProjectId;\n defaultSplitsDomain = _defaultSplitsDomain;\n defaultSplitsGroup = _defaultSplitsGroup;\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default split group using the stored default properties.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override nonReentrant {\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n JBTokens.ETH,\n address(this).balance,\n 18 // decimals.\n );\n\n // If there is no leftover amount, nothing left to pay.\n if (_leftoverAmount == 0) return;\n\n // If there's a default project ID, try to pay it.\n if (defaultProjectId != 0)\n if (defaultPreferAddToBalance)\n // Pay the project by adding to its balance if prefered.\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.ETH,\n _leftoverAmount,\n 18, // decimals.\n defaultMemo,\n defaultMetadata\n );\n // Otherwise, issue a payment to the project.\n else\n _pay(\n defaultProjectId,\n JBTokens.ETH,\n _leftoverAmount,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n 0, // min returned tokens.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n // If no project was specified, send the funds directly to the beneficiary or the msg.sender.\n else\n Address.sendValue(\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(msg.sender),\n _leftoverAmount\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the location of the splits that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n */\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) external virtual override onlyOwner {\n // Set the default splits project ID if it's changing.\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\n\n // Set the default splits domain if it's changing.\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\n\n // Set the default splits group if it's changing.\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\n\n emit SetDefaultSplits(_projectId, _domain, _group, msg.sender);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals\n );\n\n // Pay any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to pay it.\n if (_projectId != 0) {\n _pay(\n _projectId,\n _token,\n _leftoverAmount,\n _decimals,\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n // If no project was specified, send the funds directly to the beneficiary or the msg.sender.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _beneficiary != address(0) ? payable(_beneficiary) : payable(msg.sender),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).transfer(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _leftoverAmount\n );\n }\n }\n\n emit Pay(\n _projectId,\n _beneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event. \n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals\n );\n\n // Distribute any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to add to its balance.\n if (_projectId != 0)\n // Add to the project's balance.\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\n\n // Otherwise, send a payment to the beneficiary.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(msg.sender),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).transfer(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _leftoverAmount\n );\n }\n }\n\n emit AddToBalance(\n _projectId,\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splitsProjectId The ID of the project to which the splits belong.\n @param _splitsDomain The splits domain to which the group belongs.\n @param _splitsGroup The splits group to pay.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payToSplits(\n uint256 _splitsProjectId,\n uint256 _splitsDomain,\n uint256 _splitsGroup,\n address _token,\n uint256 _amount,\n uint256 _decimals\n ) internal virtual returns (uint256 leftoverAmount) {\n // Get a reference to the splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup);\n\n // Set the leftover amount to the initial balance.\n leftoverAmount = _amount;\n\n // Settle between all splits.\n for (uint256 i = 0; i < _splits.length; i++) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[i];\n\n // The amount to send towards the split.\n uint256 _splitAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n if (_splitAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n _token,\n _splitAmount,\n _decimals,\n defaultProjectId,\n 0,\n _split\n );\n\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\n if (_token != JBTokens.ETH)\n IERC20(_token).approve(address(_split.allocator), _splitAmount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _splitAmount : 0;\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n if (_split.preferAddToBalance)\n _addToBalanceOf(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n defaultMemo,\n defaultMetadata\n );\n } else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _split.beneficiary != address(0) ? _split.beneficiary : payable(msg.sender),\n _splitAmount\n );\n // Or, transfer the ERC20.\n else {\n IERC20(_token).transfer(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n _splitAmount\n );\n }\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _splitAmount;\n }\n\n emit DistributeToSplit(\n _splitsProjectId,\n _splitsDomain,\n _splitsGroup,\n _split,\n _splitAmount,\n msg.sender\n );\n }\n }\n}\n" + "contracts/JBGasTokenERC20SplitsPayer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBSplitsPayer.sol';\nimport './interfaces/IJBSplitsStore.sol';\nimport './libraries/JBConstants.sol';\nimport './JBGasTokenERC20ProjectPayer.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\n\n @dev\n Adheres to -\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBGasTokenERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBGasTokenERC20SplitsPayer is IJBSplitsPayer, JBGasTokenERC20ProjectPayer, ReentrancyGuard {\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The ID of project for which the default splits are stored. \n */\n uint256 public override defaultSplitsProjectId;\n\n /**\n @notice\n The domain within which the default splits are stored. \n */\n uint256 public override defaultSplitsDomain;\n\n /**\n @notice\n The group within which the default splits are stored. \n */\n uint256 public override defaultSplitsGroup;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBGasTokenERC20ProjectPayer, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n )\n JBGasTokenERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _preferAddToBalance,\n _splitsStore.directory(),\n _owner\n )\n {\n defaultSplitsProjectId = _defaultSplitsProjectId;\n defaultSplitsDomain = _defaultSplitsDomain;\n defaultSplitsGroup = _defaultSplitsGroup;\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default split group using the stored default properties.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override nonReentrant {\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18 // decimals.\n );\n\n // If there is no leftover amount, nothing left to pay.\n if (_leftoverAmount == 0) return;\n\n // If there's a default project ID, try to pay it.\n if (defaultProjectId != 0)\n if (defaultPreferAddToBalance)\n // Pay the project by adding to its balance if prefered.\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n _leftoverAmount,\n 18, // decimals.\n defaultMemo,\n defaultMetadata\n );\n // Otherwise, issue a payment to the project.\n else\n _pay(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n _leftoverAmount,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n 0, // min returned tokens.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n // If no project was specified, send the funds directly to the beneficiary or the msg.sender.\n else\n Address.sendValue(\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(msg.sender),\n _leftoverAmount\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the location of the splits that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n */\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) external virtual override onlyOwner {\n // Set the default splits project ID if it's changing.\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\n\n // Set the default splits domain if it's changing.\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\n\n // Set the default splits group if it's changing.\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\n\n emit SetDefaultSplits(_projectId, _domain, _group, msg.sender);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals\n );\n\n // Pay any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to pay it.\n if (_projectId != 0) {\n _pay(\n _projectId,\n _token,\n _leftoverAmount,\n _decimals,\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n // If no project was specified, send the funds directly to the beneficiary or the msg.sender.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _beneficiary != address(0) ? payable(_beneficiary) : payable(msg.sender),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).transfer(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _leftoverAmount\n );\n }\n }\n\n emit Pay(\n _projectId,\n _beneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event. \n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals\n );\n\n // Distribute any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to add to its balance.\n if (_projectId != 0)\n // Add to the project's balance.\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\n\n // Otherwise, send a payment to the beneficiary.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(msg.sender),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).transfer(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _leftoverAmount\n );\n }\n }\n\n emit AddToBalance(\n _projectId,\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splitsProjectId The ID of the project to which the splits belong.\n @param _splitsDomain The splits domain to which the group belongs.\n @param _splitsGroup The splits group to pay.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payToSplits(\n uint256 _splitsProjectId,\n uint256 _splitsDomain,\n uint256 _splitsGroup,\n address _token,\n uint256 _amount,\n uint256 _decimals\n ) internal virtual returns (uint256 leftoverAmount) {\n // Get a reference to the splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup);\n\n // Set the leftover amount to the initial balance.\n leftoverAmount = _amount;\n\n // Settle between all splits.\n for (uint256 i = 0; i < _splits.length; i++) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[i];\n\n // The amount to send towards the split.\n uint256 _splitAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n if (_splitAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n _token,\n _splitAmount,\n _decimals,\n defaultProjectId,\n 0,\n _split\n );\n\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN)\n IERC20(_token).approve(address(_split.allocator), _splitAmount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _splitAmount : 0;\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n if (_split.preferAddToBalance)\n _addToBalanceOf(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n defaultMemo,\n defaultMetadata\n );\n } else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _split.beneficiary != address(0) ? _split.beneficiary : payable(msg.sender),\n _splitAmount\n );\n // Or, transfer the ERC20.\n else {\n IERC20(_token).transfer(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n _splitAmount\n );\n }\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _splitAmount;\n }\n\n emit DistributeToSplit(\n _splitsProjectId,\n _splitsDomain,\n _splitsGroup,\n _split,\n _splitAmount,\n msg.sender\n );\n }\n }\n}\n" }, "contracts/interfaces/IJBSplitsPayer.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './../structs/JBSplit.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBSplitsPayer is IERC165 {\n event SetDefaultSplits(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n address caller\n );\n event Pay(\n uint256 indexed projectId,\n address beneficiary,\n address token,\n uint256 amount,\n uint256 decimals,\n uint256 leftoverAmount,\n uint256 minReturnedTokens,\n bool preferClaimedTokens,\n string memo,\n bytes metadata,\n address caller\n );\n\n event AddToBalance(\n uint256 indexed projectId,\n address beneficiary,\n address token,\n uint256 amount,\n uint256 decimals,\n uint256 leftoverAmount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DistributeToSplit(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n JBSplit split,\n uint256 amount,\n address caller\n );\n\n function defaultSplitsProjectId() external view returns (uint256);\n\n function defaultSplitsDomain() external view returns (uint256);\n\n function defaultSplitsGroup() external view returns (uint256);\n\n function splitsStore() external view returns (IJBSplitsStore);\n\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) external;\n}\n" }, - "contracts/JBETHERC20ProjectPayer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport './interfaces/IJBProjectPayer.sol';\nimport './libraries/JBTokens.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ERC165: Introspection on interface adherance. \n*/\ncontract JBETHERC20ProjectPayer is IJBProjectPayer, Ownable, ERC165 {\n //*********************************************************************//\n // -------------------------- custom errors -------------------------- //\n //*********************************************************************//\n error INCORRECT_DECIMAL_AMOUNT();\n error NO_MSG_VALUE_ALLOWED();\n error TERMINAL_NOT_FOUND();\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice \n A contract storing directories of terminals and controllers for each project.\n */\n IJBDirectory public immutable override directory;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The ID of the project that should be used to forward this contract's received payments.\n */\n uint256 public override defaultProjectId;\n\n /** \n @notice \n The beneficiary that should be used in the payment made when this contract receives payments.\n */\n address payable public override defaultBeneficiary;\n\n /** \n @notice \n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\n */\n bool public override defaultPreferClaimedTokens;\n\n /** \n @notice \n The memo that should be used in the payment made when this contract receives payments.\n */\n string public override defaultMemo;\n\n /** \n @notice \n The metadata that should be used in the payment made when this contract receives payments.\n */\n bytes public override defaultMetadata;\n\n /**\n @notice \n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n bool public override defaultPreferAddToBalance;\n\n //*********************************************************************//\n // ------------------------- public views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) {\n defaultProjectId = _defaultProjectId;\n defaultBeneficiary = _defaultBeneficiary;\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\n defaultMemo = _defaultMemo;\n defaultMetadata = _defaultMetadata;\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n directory = _directory;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default project ID using the stored default properties.\n\n @dev\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override {\n if (defaultPreferAddToBalance)\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.ETH,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n defaultProjectId,\n JBTokens.ETH,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultBeneficiary == address(0) ? msg.sender : defaultBeneficiary,\n 0, // Can't determine expectation of returned tokens ahead of time.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\n\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _beneficiary The address that'll receive the project's tokens. \n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _memo The memo that'll be used. \n @param _metadata The metadata that'll be sent. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external virtual override onlyOwner {\n // Set the default project ID if it has changed.\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\n\n // Set the default beneficiary if it has changed.\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\n\n // Set the default claimed token preference if it has changed.\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\n defaultPreferClaimedTokens = _preferClaimedTokens;\n\n // Set the default memo if it has changed.\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\n defaultMemo = _memo;\n\n // Set the default metadata if it has changed.\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\n defaultMetadata = _metadata;\n\n // Set the add to balance preference if it has changed.\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n\n emit SetDefaultValues(\n _projectId,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata,\n _defaultPreferAddToBalance,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _pay(\n _projectId,\n _token,\n _amount,\n _decimals,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. \n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source and delegate, if provided.\n */\n function _pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.ETH) IERC20(_token).approve(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\n\n // Send funds to the terminal.\n // If the token is ETH, send it in msg.value.\n _terminal.pay{value: _payableValue}(\n _projectId,\n _amount, // ignored if the token is JBTokens.ETH.\n _token,\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.ETH) IERC20(_token).approve(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\n\n // Add to balance so tokens don't get issued.\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\n }\n}\n" + "contracts/JBGasTokenERC20ProjectPayer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport './interfaces/IJBProjectPayer.sol';\nimport './libraries/JBTokens.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ERC165: Introspection on interface adherance. \n*/\ncontract JBGasTokenERC20ProjectPayer is IJBProjectPayer, Ownable, ERC165 {\n //*********************************************************************//\n // -------------------------- custom errors -------------------------- //\n //*********************************************************************//\n error INCORRECT_DECIMAL_AMOUNT();\n error NO_MSG_VALUE_ALLOWED();\n error TERMINAL_NOT_FOUND();\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice \n A contract storing directories of terminals and controllers for each project.\n */\n IJBDirectory public immutable override directory;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The ID of the project that should be used to forward this contract's received payments.\n */\n uint256 public override defaultProjectId;\n\n /** \n @notice \n The beneficiary that should be used in the payment made when this contract receives payments.\n */\n address payable public override defaultBeneficiary;\n\n /** \n @notice \n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\n */\n bool public override defaultPreferClaimedTokens;\n\n /** \n @notice \n The memo that should be used in the payment made when this contract receives payments.\n */\n string public override defaultMemo;\n\n /** \n @notice \n The metadata that should be used in the payment made when this contract receives payments.\n */\n bytes public override defaultMetadata;\n\n /**\n @notice \n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n bool public override defaultPreferAddToBalance;\n\n //*********************************************************************//\n // ------------------------- public views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) {\n defaultProjectId = _defaultProjectId;\n defaultBeneficiary = _defaultBeneficiary;\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\n defaultMemo = _defaultMemo;\n defaultMetadata = _defaultMetadata;\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n directory = _directory;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default project ID using the stored default properties.\n\n @dev\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override {\n if (defaultPreferAddToBalance)\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultBeneficiary == address(0) ? msg.sender : defaultBeneficiary,\n 0, // Can't determine expectation of returned tokens ahead of time.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\n\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _beneficiary The address that'll receive the project's tokens. \n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _memo The memo that'll be used. \n @param _metadata The metadata that'll be sent. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external virtual override onlyOwner {\n // Set the default project ID if it has changed.\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\n\n // Set the default beneficiary if it has changed.\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\n\n // Set the default claimed token preference if it has changed.\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\n defaultPreferClaimedTokens = _preferClaimedTokens;\n\n // Set the default memo if it has changed.\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\n defaultMemo = _memo;\n\n // Set the default metadata if it has changed.\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\n defaultMetadata = _metadata;\n\n // Set the add to balance preference if it has changed.\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n\n emit SetDefaultValues(\n _projectId,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata,\n _defaultPreferAddToBalance,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _pay(\n _projectId,\n _token,\n _amount,\n _decimals,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. \n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source and delegate, if provided.\n */\n function _pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).approve(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send funds to the terminal.\n // If the token is ETH, send it in msg.value.\n _terminal.pay{value: _payableValue}(\n _projectId,\n _amount, // ignored if the token is JBTokens.GAS_TOKEN.\n _token,\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).approve(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Add to balance so tokens don't get issued.\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\n }\n}\n" }, "contracts/interfaces/IJBProjectPayer.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './IJBDirectory.sol';\n\ninterface IJBProjectPayer is IERC165 {\n event SetDefaultValues(\n uint256 indexed projectId,\n address indexed beneficiary,\n bool preferClaimedTokens,\n string memo,\n bytes metadata,\n bool preferAddToBalance,\n address caller\n );\n\n function directory() external view returns (IJBDirectory);\n\n function defaultProjectId() external view returns (uint256);\n\n function defaultBeneficiary() external view returns (address payable);\n\n function defaultPreferClaimedTokens() external view returns (bool);\n\n function defaultMemo() external view returns (string memory);\n\n function defaultMetadata() external view returns (bytes memory);\n\n function defaultPreferAddToBalance() external view returns (bool);\n\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external;\n\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) external payable;\n\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) external payable;\n\n receive() external payable;\n}\n" }, - "contracts/JBETHERC20SplitsPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './interfaces/IJBETHERC20SplitsPayerDeployer.sol';\nimport './JBETHERC20SplitsPayer.sol';\n\n/** \n @notice \n Deploys splits payer contracts.\n\n @dev\n Adheres to -\n IJBETHERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBETHERC20SplitsPayerDeployer is IJBETHERC20SplitsPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBSplitsPayer splitsPayer) {\n // Deploy the splits payer.\n splitsPayer = new JBETHERC20SplitsPayer(\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeploySplitsPayer(\n splitsPayer,\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner,\n msg.sender\n );\n }\n}\n" + "contracts/JBGasTokenERC20SplitsPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './interfaces/IJBGasTokenERC20SplitsPayerDeployer.sol';\nimport './JBGasTokenERC20SplitsPayer.sol';\n\n/** \n @notice \n Deploys splits payer contracts.\n\n @dev\n Adheres to -\n IJBGasTokenERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBGasTokenERC20SplitsPayerDeployer is IJBGasTokenERC20SplitsPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBSplitsPayer splitsPayer) {\n // Deploy the splits payer.\n splitsPayer = new JBGasTokenERC20SplitsPayer(\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeploySplitsPayer(\n splitsPayer,\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner,\n msg.sender\n );\n }\n}\n" }, - "contracts/interfaces/IJBETHERC20SplitsPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './IJBSplitsPayer.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBETHERC20SplitsPayerDeployer {\n event DeploySplitsPayer(\n IJBSplitsPayer indexed splitsPayer,\n uint256 defaultSplitsProjectId,\n uint256 defaultSplitsDomain,\n uint256 defaultSplitsGroup,\n IJBSplitsStore splitsStore,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n address owner,\n address caller\n );\n\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string calldata _defaultMemo,\n bytes calldata _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n}\n" + "contracts/interfaces/IJBGasTokenERC20SplitsPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './IJBSplitsPayer.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBGasTokenERC20SplitsPayerDeployer {\n event DeploySplitsPayer(\n IJBSplitsPayer indexed splitsPayer,\n uint256 defaultSplitsProjectId,\n uint256 defaultSplitsDomain,\n uint256 defaultSplitsGroup,\n IJBSplitsStore splitsStore,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n address owner,\n address caller\n );\n\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string calldata _defaultMemo,\n bytes calldata _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n}\n" }, - "contracts/JBETHERC20ProjectPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './interfaces/IJBETHERC20ProjectPayerDeployer.sol';\nimport './JBETHERC20ProjectPayer.sol';\n\n/** \n @notice \n Deploys project payer contracts.\n\n @dev\n Adheres to -\n IJBETHERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBETHERC20ProjectPayerDeployer is IJBETHERC20ProjectPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new project payer contract.\n\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the project payer contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the project payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the project payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the project payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the project payer.\n\n @return projectPayer The project payer contract.\n */\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external override returns (IJBProjectPayer projectPayer) {\n // Deploy the project payer.\n projectPayer = new JBETHERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner\n );\n\n emit DeployProjectPayer(\n projectPayer,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner,\n msg.sender\n );\n }\n}\n" + "contracts/JBGasTokenERC20ProjectPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './interfaces/IJBGasTokenERC20ProjectPayerDeployer.sol';\nimport './JBGasTokenERC20ProjectPayer.sol';\n\n/** \n @notice \n Deploys project payer contracts.\n\n @dev\n Adheres to -\n IJBGasTokenERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBGasTokenERC20ProjectPayerDeployer is IJBGasTokenERC20ProjectPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new project payer contract.\n\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the project payer contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the project payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the project payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the project payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the project payer.\n\n @return projectPayer The project payer contract.\n */\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external override returns (IJBProjectPayer projectPayer) {\n // Deploy the project payer.\n projectPayer = new JBGasTokenERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner\n );\n\n emit DeployProjectPayer(\n projectPayer,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner,\n msg.sender\n );\n }\n}\n" }, - "contracts/interfaces/IJBETHERC20ProjectPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './IJBDirectory.sol';\nimport './IJBProjectPayer.sol';\n\ninterface IJBETHERC20ProjectPayerDeployer {\n event DeployProjectPayer(\n IJBProjectPayer indexed projectPayer,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n IJBDirectory directory,\n address owner,\n address caller\n );\n\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external returns (IJBProjectPayer projectPayer);\n}\n" + "contracts/interfaces/IJBGasTokenERC20ProjectPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './IJBDirectory.sol';\nimport './IJBProjectPayer.sol';\n\ninterface IJBGasTokenERC20ProjectPayerDeployer {\n event DeployProjectPayer(\n IJBProjectPayer indexed projectPayer,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n IJBDirectory directory,\n address owner,\n address caller\n );\n\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external returns (IJBProjectPayer projectPayer);\n}\n" }, "contracts/system_tests/TestPayBurnRedeemFlow.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport '@paulrberg/contracts/math/PRBMathUD60x18.sol';\n\nimport './helpers/TestBaseWorkflow.sol';\n\n/**\n * This system test file verifies the following flow:\n * launch project → issue token → pay project (claimed tokens) → burn some of the claimed tokens → redeem rest of tokens\n */\ncontract TestPayBurnRedeemFlow is TestBaseWorkflow {\n JBController private _controller;\n JBETHPaymentTerminal private _terminal;\n JBTokenStore private _tokenStore;\n\n JBProjectMetadata private _projectMetadata;\n JBFundingCycleData private _data;\n JBFundingCycleMetadata private _metadata;\n JBGroupedSplits[] private _groupedSplits; // Default empty\n JBFundAccessConstraints[] private _fundAccessConstraints; // Default empty\n IJBPaymentTerminal[] private _terminals; // Default empty\n\n uint256 private _projectId;\n address private _projectOwner;\n uint256 private _weight = 1000 * 10**18;\n uint256 private _targetInWei = 10 * 10**18;\n\n function setUp() public override {\n super.setUp();\n\n _controller = jbController();\n _terminal = jbETHPaymentTerminal();\n _tokenStore = jbTokenStore();\n\n _projectMetadata = JBProjectMetadata({content: 'myIPFSHash', domain: 1});\n\n _data = JBFundingCycleData({\n duration: 14,\n weight: _weight,\n discountRate: 450000000,\n ballot: IJBFundingCycleBallot(address(0))\n });\n\n _metadata = JBFundingCycleMetadata({\n global: JBGlobalFundingCycleMetadata({allowSetTerminals: false, allowSetController: false}),\n reservedRate: 0,\n redemptionRate: 10000, //100%\n ballotRedemptionRate: 0,\n pausePay: false,\n pauseDistributions: false,\n pauseRedeem: false,\n pauseBurn: false,\n allowMinting: false,\n allowChangeToken: false,\n allowTerminalMigration: false,\n allowControllerMigration: false,\n holdFees: false,\n useTotalOverflowForRedemptions: false,\n useDataSourceForPay: false,\n useDataSourceForRedeem: false,\n dataSource: address(0)\n });\n\n _terminals.push(_terminal);\n\n _fundAccessConstraints.push(\n JBFundAccessConstraints({\n terminal: _terminal,\n token: jbLibraries().ETHToken(),\n distributionLimit: _targetInWei, // 10 ETH target\n overflowAllowance: 5 ether,\n distributionLimitCurrency: 1, // Currency = ETH\n overflowAllowanceCurrency: 1\n })\n );\n\n _projectOwner = multisig();\n\n _projectId = _controller.launchProjectFor(\n _projectOwner,\n _projectMetadata,\n _data,\n _metadata,\n block.timestamp,\n _groupedSplits,\n _fundAccessConstraints,\n _terminals,\n ''\n );\n }\n\n function testFuzzPayBurnRedeemFlow(\n bool payPreferClaimed, //false\n bool burnPreferClaimed, //false\n uint96 payAmountInWei, // 1\n uint256 burnTokenAmount, // 0\n uint256 redeemTokenAmount // 0\n ) external {\n // issue an ERC-20 token for project\n evm.prank(_projectOwner);\n _controller.issueTokenFor(_projectId, 'TestName', 'TestSymbol');\n\n address _userWallet = address(1234);\n\n // pay terminal\n _terminal.pay{value: payAmountInWei}(\n _projectId,\n payAmountInWei,\n address(0),\n _userWallet,\n /* _minReturnedTokens */\n 0,\n /* _preferClaimedTokens */\n payPreferClaimed,\n /* _memo */\n 'Take my money!',\n /* _delegateMetadata */\n new bytes(0)\n );\n\n // verify: beneficiary should have a balance of JBTokens\n uint256 _userTokenBalance = PRBMathUD60x18.mul(payAmountInWei, _weight);\n assertEq(_tokenStore.balanceOf(_userWallet, _projectId), _userTokenBalance);\n\n // verify: ETH balance in terminal should be up to date\n uint256 _terminalBalanceInWei = payAmountInWei;\n assertEq(jbPaymentTerminalStore().balanceOf(_terminal, _projectId), _terminalBalanceInWei);\n\n // burn tokens from beneficiary addr\n if (burnTokenAmount == 0) evm.expectRevert(abi.encodeWithSignature('NO_BURNABLE_TOKENS()'));\n else if (burnTokenAmount > _userTokenBalance)\n evm.expectRevert(abi.encodeWithSignature('INSUFFICIENT_FUNDS()'));\n else if (burnTokenAmount > uint256(type(int256).max))\n evm.expectRevert(abi.encodeWithSignature('Panic(uint256)', 0x11));\n else _userTokenBalance = _userTokenBalance - burnTokenAmount;\n\n evm.prank(_userWallet);\n _controller.burnTokensOf(\n _userWallet,\n _projectId,\n /* _tokenCount */\n burnTokenAmount,\n /* _memo */\n 'I hate tokens!',\n /* _preferClaimedTokens */\n burnPreferClaimed\n );\n\n // verify: beneficiary should have a new balance of JBTokens\n assertEq(_tokenStore.balanceOf(_userWallet, _projectId), _userTokenBalance);\n\n // redeem tokens\n if (redeemTokenAmount > _userTokenBalance)\n evm.expectRevert(abi.encodeWithSignature('INSUFFICIENT_TOKENS()'));\n else _userTokenBalance = _userTokenBalance - redeemTokenAmount;\n\n evm.prank(_userWallet);\n uint256 _reclaimAmtInWei = _terminal.redeemTokensOf(\n /* _holder */\n _userWallet,\n /* _projectId */\n _projectId,\n /* _tokenCount */\n redeemTokenAmount,\n /* token (unused) */\n address(0),\n /* _minReturnedWei */\n 0,\n /* _beneficiary */\n payable(_userWallet),\n /* _memo */\n 'Refund me now!',\n /* _delegateMetadata */\n new bytes(0)\n );\n\n // verify: beneficiary should have a new balance of JBTokens\n assertEq(_tokenStore.balanceOf(_userWallet, _projectId), _userTokenBalance);\n\n // verify: ETH balance in terminal should be up to date\n assertEq(\n jbPaymentTerminalStore().balanceOf(_terminal, _projectId),\n _terminalBalanceInWei - _reclaimAmtInWei\n );\n }\n}\n" @@ -392,11 +392,13 @@ "storageLayout", "evm.gasEstimates" ], - "": ["ast"] + "": [ + "ast" + ] } }, "metadata": { "useLiteralContent": true } } -} +} \ No newline at end of file diff --git a/deployments/mainnet/solcInputs/a1f674e02c4866a16e5bde886a31b82e.json b/deployments/mainnet/solcInputs/a1f674e02c4866a16e5bde886a31b82e.json index 6a06882bf..4f0a7689d 100644 --- a/deployments/mainnet/solcInputs/a1f674e02c4866a16e5bde886a31b82e.json +++ b/deployments/mainnet/solcInputs/a1f674e02c4866a16e5bde886a31b82e.json @@ -119,13 +119,13 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport './abstract/JBOperatable.sol';\nimport './interfaces/IJBDirectory.sol';\nimport './libraries/JBGlobalFundingCycleMetadataResolver.sol';\nimport './libraries/JBOperations.sol';\n\n/**\n @notice\n Keeps a reference of which terminal contracts each project is currently accepting funds through, and which controller contract is managing each project's tokens and funding cycles.\n\n @dev\n Adheres to -\n IJBDirectory: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\ncontract JBDirectory is IJBDirectory, JBOperatable, Ownable {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBGlobalFundingCycleMetadataResolver for uint8;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error DUPLICATE_TERMINALS();\n error INVALID_PROJECT_ID_IN_DIRECTORY();\n error SET_CONTROLLER_NOT_ALLOWED();\n error SET_TERMINALS_NOT_ALLOWED();\n error TOKEN_NOT_ACCEPTED();\n\n //*********************************************************************//\n // --------------------- private stored properties ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n For each project ID, the terminals that are currently managing its funds.\n\n _projectId The ID of the project to get terminals of.\n */\n mapping(uint256 => IJBPaymentTerminal[]) private _terminalsOf;\n\n /**\n @notice\n The project's primary terminal for a token.\n\n _projectId The ID of the project to get the primary terminal of.\n _token The token to get the project's primary terminal of.\n */\n mapping(uint256 => mapping(address => IJBPaymentTerminal)) private _primaryTerminalOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n For each project ID, the controller that manages how terminals interact with tokens and funding cycles.\n\n _projectId The ID of the project to get the controller of.\n */\n mapping(uint256 => address) public override controllerOf;\n\n /**\n @notice\n Addresses that can set a project's first controller on their behalf. These addresses/contracts have been vetted and verified by this contract's owner.\n\n _address The address that is either allowed or not.\n */\n mapping(address => bool) public override isAllowedToSetFirstController;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n For each project ID, the terminals that are currently managing its funds.\n\n @param _projectId The ID of the project to get terminals of.\n\n @return An array of terminal addresses.\n */\n function terminalsOf(uint256 _projectId)\n external\n view\n override\n returns (IJBPaymentTerminal[] memory)\n {\n return _terminalsOf[_projectId];\n }\n\n /**\n @notice\n The primary terminal that is managing funds for a project for a specified token.\n\n @dev\n The zero address is returned if a terminal isn't found for the specified token.\n\n @param _projectId The ID of the project to get a terminal for.\n @param _token The token the terminal accepts.\n\n @return The primary terminal for the project for the specified token.\n */\n function primaryTerminalOf(uint256 _projectId, address _token)\n external\n view\n override\n returns (IJBPaymentTerminal)\n {\n // If a primary terminal for the token was specifically set and its one of the project's terminals, return it.\n if (\n _primaryTerminalOf[_projectId][_token] != IJBPaymentTerminal(address(0)) &&\n isTerminalOf(_projectId, _primaryTerminalOf[_projectId][_token])\n ) return _primaryTerminalOf[_projectId][_token];\n\n // Return the first terminal which accepts the specified token.\n for (uint256 _i; _i < _terminalsOf[_projectId].length; _i++) {\n IJBPaymentTerminal _terminal = _terminalsOf[_projectId][_i];\n if (_terminal.acceptsToken(_token, _projectId)) return _terminal;\n }\n\n // Not found.\n return IJBPaymentTerminal(address(0));\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Whether or not a specified terminal is a terminal of the specified project.\n\n @param _projectId The ID of the project to check within.\n @param _terminal The address of the terminal to check for.\n\n @return A flag indicating whether or not the specified terminal is a terminal of the specified project.\n */\n function isTerminalOf(uint256 _projectId, IJBPaymentTerminal _terminal)\n public\n view\n override\n returns (bool)\n {\n for (uint256 _i; _i < _terminalsOf[_projectId].length; _i++)\n if (_terminalsOf[_projectId][_i] == _terminal) return true;\n return false;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _owner The address that will own the contract.\n */\n constructor(\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBFundingCycleStore _fundingCycleStore,\n address _owner\n ) JBOperatable(_operatorStore) {\n projects = _projects;\n fundingCycleStore = _fundingCycleStore;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Update the controller that manages how terminals interact with the ecosystem.\n\n @dev\n A controller can be set if:\n - the message sender is the project owner or an operator having the correct authorization.\n - the message sender is the project's current controller.\n - or, an allowedlisted address is setting a controller for a project that doesn't already have a controller.\n\n @param _projectId The ID of the project to set a new controller for.\n @param _controller The new controller to set.\n */\n function setControllerOf(uint256 _projectId, address _controller)\n external\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.SET_CONTROLLER,\n (msg.sender == address(controllerOf[_projectId]) ||\n (isAllowedToSetFirstController[msg.sender] && controllerOf[_projectId] == address(0)))\n )\n {\n // The project must exist.\n if (projects.count() < _projectId) revert INVALID_PROJECT_ID_IN_DIRECTORY();\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Setting controller is allowed if called from the current controller, or if the project doesn't have a current controller, or if the project's funding cycle allows setting the controller. Revert otherwise.\n if (\n msg.sender != address(controllerOf[_projectId]) &&\n controllerOf[_projectId] != address(0) &&\n !uint8(_fundingCycle.metadata >> 8).setControllerAllowed()\n ) revert SET_CONTROLLER_NOT_ALLOWED();\n\n // Set the new controller.\n controllerOf[_projectId] = _controller;\n\n emit SetController(_projectId, _controller, msg.sender);\n }\n\n /** \n @notice \n Set a project's terminals.\n\n @dev\n Only a project owner, an operator, or its controller can set its terminals.\n\n @param _projectId The ID of the project having terminals set.\n @param _terminals The terminal to set.\n */\n function setTerminalsOf(uint256 _projectId, IJBPaymentTerminal[] calldata _terminals)\n external\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.SET_TERMINALS,\n msg.sender == address(controllerOf[_projectId])\n )\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Setting terminals must be allowed if not called from the current controller.\n if (\n msg.sender != address(controllerOf[_projectId]) &&\n !uint8(_fundingCycle.metadata >> 8).setTerminalsAllowed()\n ) revert SET_TERMINALS_NOT_ALLOWED();\n\n // Delete the stored terminals for the project.\n _terminalsOf[_projectId] = _terminals;\n\n // Make sure duplicates were not added.\n if (_terminals.length > 1)\n for (uint256 _i; _i < _terminals.length; _i++)\n for (uint256 _j = _i + 1; _j < _terminals.length; _j++)\n if (_terminals[_i] == _terminals[_j]) revert DUPLICATE_TERMINALS();\n\n emit SetTerminals(_projectId, _terminals, msg.sender);\n }\n\n /**\n @notice\n Project's can set which terminal should be their primary for a particular token.\n This is useful in case a project has several terminals connected for a particular token.\n\n @dev\n The terminal will be set as the primary terminal where ecosystem contracts should route tokens.\n\n @dev\n If setting a newly added terminal and the funding cycle doesn't allow new terminals, the caller must be the current controller.\n\n @param _projectId The ID of the project for which a primary token is being set.\n @param _token The token to set the primary terminal of.\n @param _terminal The terminal to make primary.\n */\n function setPrimaryTerminalOf(\n uint256 _projectId,\n address _token,\n IJBPaymentTerminal _terminal\n )\n external\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.SET_PRIMARY_TERMINAL)\n {\n // Can't set the primary terminal for a token if it doesn't accept the token.\n if (!_terminal.acceptsToken(_token, _projectId)) revert TOKEN_NOT_ACCEPTED();\n\n // Add the terminal to the project if it hasn't been already.\n _addTerminalIfNeeded(_projectId, _terminal);\n\n // Store the terminal as the primary for the particular token.\n _primaryTerminalOf[_projectId][_token] = _terminal;\n\n emit SetPrimaryTerminal(_projectId, _token, _terminal, msg.sender);\n }\n\n /** \n @notice\t\n Set a contract to the list of trusted addresses that can set a first controller for any project.\t\n\n @dev\n The owner can add addresses which are allowed to change projects' first controllers. \n These addresses are known and vetted controllers as well as contracts designed to launch new projects. \n A project can set its own controller without it being on the allow list.\n\n @dev\n If you would like an address/contract allowlisted, please reach out to the contract owner.\n\n @param _address The address to allow or revoke allowance from.\n @param _flag Whether allowance is being added or revoked.\n */\n function setIsAllowedToSetFirstController(address _address, bool _flag)\n external\n override\n onlyOwner\n {\n // Set the flag in the allowlist.\n isAllowedToSetFirstController[_address] = _flag;\n\n emit SetIsAllowedToSetFirstController(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Add a terminal to a project's list of terminals if it hasn't been already.\n\n @param _projectId The ID of the project having a terminal added.\n @param _terminal The terminal to add.\n */\n function _addTerminalIfNeeded(uint256 _projectId, IJBPaymentTerminal _terminal) private {\n // Check that the terminal has not already been added.\n if (isTerminalOf(_projectId, _terminal)) return;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Setting terminals must be allowed if not called from the current controller.\n if (\n msg.sender != address(controllerOf[_projectId]) &&\n !uint8(_fundingCycle.metadata >> 8).setTerminalsAllowed()\n ) revert SET_TERMINALS_NOT_ALLOWED();\n\n // Add the new terminal.\n _terminalsOf[_projectId].push(_terminal);\n\n emit AddTerminal(_projectId, _terminal, msg.sender);\n }\n}\n" }, "contracts/JBETHPaymentTerminal.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n JBTokens.ETH,\n 18, // 18 decimals.\n JBCurrencies.ETH,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal pure override {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n JBTokens.GAS_TOKEN,\n 18, // 18 decimals.\n JBCurrencies.GAS_CURRENCY,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal pure override {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n}\n" }, "contracts/JBERC20PaymentTerminal.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\n\n/** \n @notice \n Manages the inflows and outflows of an ERC-20 token.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\ncontract JBERC20PaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n IERC20Metadata _token,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n address(_token),\n _token.decimals(),\n _currency,\n _baseWeightCurrency,\n _payoutSplitsGroup,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from == address(this)\n ? IERC20(token).transfer(_to, _amount)\n : IERC20(token).transferFrom(_from, _to, _amount);\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal override {\n IERC20(token).approve(_to, _amount);\n }\n}\n" }, "contracts/JBSingleTokenPaymentTerminalStore.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBSingleTokenPaymentTerminalStore is IJBSingleTokenPaymentTerminalStore, ReentrancyGuard {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n Mint's 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegate A delegate contract to use for subsequent calls.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n IJBPayDelegate delegate,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay()) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegate) = IJBFundingCycleDataSource(fundingCycle.dataSource()).payParams(\n _data\n );\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegate, memo);\n\n // Add the amount to the token balance of the project.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount.value;\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegate, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegate A delegate contract to use for subsequent calls.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n IJBRedemptionDelegate delegate,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\n _projectId,\n fundingCycle.reservedRate()\n );\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow > 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem()) {\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n fundingCycle.redemptionRate(),\n fundingCycle.ballotRedemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegate) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .redeemParams(_data);\n } else {\n memo = _memo;\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (reclaimAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (reclaimAmount > 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n reclaimAmount;\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n return _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i = 0; _i < _terminals.length; _i++)\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.ETH\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.ETH, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBSingleTokenPaymentTerminalStore is IJBSingleTokenPaymentTerminalStore, ReentrancyGuard {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n Mint's 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegate A delegate contract to use for subsequent calls.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n IJBPayDelegate delegate,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay()) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegate) = IJBFundingCycleDataSource(fundingCycle.dataSource()).payParams(\n _data\n );\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegate, memo);\n\n // Add the amount to the token balance of the project.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount.value;\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegate, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegate A delegate contract to use for subsequent calls.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n IJBRedemptionDelegate delegate,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\n _projectId,\n fundingCycle.reservedRate()\n );\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow > 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem()) {\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n fundingCycle.redemptionRate(),\n fundingCycle.ballotRedemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegate) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .redeemParams(_data);\n } else {\n memo = _memo;\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (reclaimAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (reclaimAmount > 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n reclaimAmount;\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n return _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i = 0; _i < _terminals.length; _i++)\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.GAS_CURRENCY\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.GAS_CURRENCY, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" }, "contracts/JBFundingCycleStore.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './abstract/JBControllerUtility.sol';\nimport './libraries/JBConstants.sol';\n\n/** \n @notice \n Manages funding cycle configurations and scheduling.\n\n @dev\n Adheres to -\n IJBTokenStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBControllerUtility: Includes convenience functionality for checking if the message sender is the current controller of the project whose data is being manipulated.\n*/\ncontract JBFundingCycleStore is IJBFundingCycleStore, JBControllerUtility {\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_DISCOUNT_RATE();\n error INVALID_DURATION();\n error INVALID_WEIGHT();\n error INVALID_BALLOT();\n error NO_SAME_BLOCK_RECONFIGURATION();\n\n //*********************************************************************//\n // --------------------- private stored properties ------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Stores the user defined properties of each funding cycle, packed into one storage slot.\n\n _projectId The ID of the project to get properties of.\n _configuration The funding cycle configuration to get properties of.\n */\n mapping(uint256 => mapping(uint256 => uint256)) private _packedUserPropertiesOf;\n\n /** \n @notice\n Stores the properties added by the mechanism to manage and schedule each funding cycle, packed into one storage slot.\n \n _projectId The ID of the project to get instrinsic properties of.\n _configuration The funding cycle configuration to get properties of.\n */\n mapping(uint256 => mapping(uint256 => uint256)) private _packedIntrinsicPropertiesOf;\n\n /** \n @notice\n Stores the metadata for each funding cycle configuration, packed into one storage slot.\n\n _projectId The ID of the project to get metadata of.\n _configuration The funding cycle configuration to get metadata of.\n */\n mapping(uint256 => mapping(uint256 => uint256)) private _metadataOf;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The latest funding cycle configuration for each project.\n\n _projectId The ID of the project to get the latest funding cycle configuration of.\n */\n mapping(uint256 => uint256) public override latestConfigurationOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice \n Get the funding cycle with the given configuration for the specified project.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n @param _configuration The configuration of the funding cycle to get.\n\n @return fundingCycle The funding cycle.\n */\n function get(uint256 _projectId, uint256 _configuration)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle)\n {\n return _getStructFor(_projectId, _configuration);\n }\n\n /**\n @notice \n The latest funding cycle to be configured for the specified project, and its current ballot state.\n\n @param _projectId The ID of the project to get the latest configured funding cycle of.\n\n @return fundingCycle The project's queued funding cycle.\n @return ballotState The state of the ballot for the reconfiguration.\n */\n function latestConfiguredOf(uint256 _projectId)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle, JBBallotState ballotState)\n {\n // Get a reference to the latest funding cycle configuration.\n uint256 _fundingCycleConfiguration = latestConfigurationOf[_projectId];\n\n // Resolve the funding cycle for the latest configuration.\n fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n // Resolve the ballot state.\n ballotState = _ballotStateOf(\n _projectId,\n fundingCycle.configuration,\n fundingCycle.start,\n fundingCycle.basedOn\n );\n }\n\n /**\n @notice \n The funding cycle that's next up for the specified project.\n\n @dev\n If a queued funding cycle of the project is not found, returns an empty funding cycle with all properties set to 0.\n\n @param _projectId The ID of the project to get the queued funding cycle of.\n\n @return fundingCycle The project's queued funding cycle.\n */\n function queuedOf(uint256 _projectId)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle)\n {\n // If the project does not have a funding cycle, return an empty struct.\n if (latestConfigurationOf[_projectId] == 0) return _getStructFor(0, 0);\n\n // Get a reference to the configuration of the standby funding cycle.\n uint256 _standbyFundingCycleConfiguration = _standbyOf(_projectId);\n\n // If it exists, return its funding cycle if it is approved.\n if (_standbyFundingCycleConfiguration > 0) {\n fundingCycle = _getStructFor(_projectId, _standbyFundingCycleConfiguration);\n\n if (_isApproved(_projectId, fundingCycle)) return fundingCycle;\n\n // Resolve the funding cycle for the latest configured funding cycle.\n fundingCycle = _getStructFor(_projectId, fundingCycle.basedOn);\n } else {\n // Resolve the funding cycle for the latest configured funding cycle.\n fundingCycle = _getStructFor(_projectId, latestConfigurationOf[_projectId]);\n\n // If the latest funding cycle starts in the future, it must start in the distant future\n // since its not in standby. In this case base the queued cycles on the base cycle.\n if (fundingCycle.start > block.timestamp)\n fundingCycle = _getStructFor(_projectId, fundingCycle.basedOn);\n }\n\n // There's no queued if the current has a duration of 0.\n if (fundingCycle.duration == 0) return _getStructFor(0, 0);\n\n // Check to see if this funding cycle's ballot is approved.\n // If so, return a funding cycle based on it.\n if (_isApproved(_projectId, fundingCycle)) return _mockFundingCycleBasedOn(fundingCycle, false);\n\n // Get the funding cycle of its base funding cycle, which carries the last approved configuration.\n fundingCycle = _getStructFor(_projectId, fundingCycle.basedOn);\n\n // There's no queued if the base, which must still be the current, has a duration of 0.\n if (fundingCycle.duration == 0) return _getStructFor(0, 0);\n\n // Return a mock of the next up funding cycle.\n return _mockFundingCycleBasedOn(fundingCycle, false);\n }\n\n /**\n @notice \n The funding cycle that is currently active for the specified project.\n\n @dev\n If a current funding cycle of the project is not found, returns an empty funding cycle with all properties set to 0.\n\n @param _projectId The ID of the project to get the current funding cycle of.\n\n @return fundingCycle The project's current funding cycle.\n */\n function currentOf(uint256 _projectId)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle)\n {\n // If the project does not have a funding cycle, return an empty struct.\n if (latestConfigurationOf[_projectId] == 0) return _getStructFor(0, 0);\n\n // Get a reference to the configuration of the eligible funding cycle.\n uint256 _fundingCycleConfiguration = _eligibleOf(_projectId);\n\n // Keep a reference to the eligible funding cycle.\n JBFundingCycle memory _fundingCycle;\n\n // If an eligible funding cycle exists...\n if (_fundingCycleConfiguration > 0) {\n // Resolve the funding cycle for the eligible configuration.\n _fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n // Check to see if this funding cycle's ballot is approved.\n // If so, return it.\n if (_isApproved(_projectId, _fundingCycle)) return _fundingCycle;\n\n // If it hasn't been approved, set the funding cycle configuration to be the configuration of the funding cycle that it's based on,\n // which carries the last approved configuration.\n _fundingCycleConfiguration = _fundingCycle.basedOn;\n } else {\n // No upcoming funding cycle found that is eligible to become active,\n // so use the last configuration.\n _fundingCycleConfiguration = latestConfigurationOf[_projectId];\n\n // Get the funding cycle for the latest ID.\n _fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n // If it's not approved or if it hasn't yet started, get a reference to the funding cycle that the latest is based on, which has the latest approved configuration.\n if (!_isApproved(_projectId, _fundingCycle) || block.timestamp < _fundingCycle.start)\n _fundingCycleConfiguration = _fundingCycle.basedOn;\n }\n\n // If there is not funding cycle to base the current one on, there can't be a current one.\n if (_fundingCycleConfiguration == 0) return _getStructFor(0, 0);\n\n // The funding cycle to base a current one on.\n _fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n // If the base has no duration, it's still the current one.\n if (_fundingCycle.duration == 0) return _fundingCycle;\n\n // Return a mock of the current funding cycle.\n return _mockFundingCycleBasedOn(_fundingCycle, true);\n }\n\n /** \n @notice \n The current ballot state of the project.\n\n @param _projectId The ID of the project to check the ballot state of.\n\n @return The project's current ballot's state.\n */\n function currentBallotStateOf(uint256 _projectId) external view override returns (JBBallotState) {\n // Get a reference to the latest funding cycle configuration.\n uint256 _fundingCycleConfiguration = latestConfigurationOf[_projectId];\n\n // Resolve the funding cycle for the latest configuration.\n JBFundingCycle memory _fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n return\n _ballotStateOf(\n _projectId,\n _fundingCycle.configuration,\n _fundingCycle.start,\n _fundingCycle.basedOn\n );\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _directory A contract storing directories of terminals and controllers for each project.\n */\n // solhint-disable-next-line no-empty-blocks\n constructor(IJBDirectory _directory) JBControllerUtility(_directory) {}\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice \n Configures the next eligible funding cycle for the specified project.\n\n @dev\n Only a project's current controller can configure its funding cycles.\n\n @param _projectId The ID of the project being configured.\n @param _data The funding cycle configuration data.\n @param _metadata Arbitrary extra data to associate with this funding cycle configuration that's not used within.\n @param _mustStartAtOrAfter The time before which the initialized funding cycle cannot start.\n\n @return The funding cycle that the configuration will take effect during.\n */\n function configureFor(\n uint256 _projectId,\n JBFundingCycleData calldata _data,\n uint256 _metadata,\n uint256 _mustStartAtOrAfter\n ) external override onlyController(_projectId) returns (JBFundingCycle memory) {\n // Duration must fit in a uint64.\n if (_data.duration > type(uint64).max) revert INVALID_DURATION();\n\n // Discount rate must be less than or equal to 100%.\n if (_data.discountRate > JBConstants.MAX_DISCOUNT_RATE) revert INVALID_DISCOUNT_RATE();\n\n // Weight must fit into a uint88.\n if (_data.weight > type(uint88).max) revert INVALID_WEIGHT();\n\n // Ballot should be a valid contract, supporting the correct interface\n if(_data.ballot != IJBFundingCycleBallot(address(0))) {\n\n address _ballot = address(_data.ballot);\n uint32 _size;\n assembly {\n _size := extcodesize(_ballot) // No contract at the address ?\n }\n if (_size == 0) revert INVALID_BALLOT();\n\n try _data.ballot.supportsInterface(type(IJBFundingCycleBallot).interfaceId) returns (bool _supports) {\n if(!_supports) revert INVALID_BALLOT(); // Contract exists at the address but with the wrong interface\n } catch {\n revert INVALID_BALLOT(); // No ERC165 support\n }\n }\n\n // The configuration timestamp is now.\n uint256 _configuration = block.timestamp;\n\n // Set up a reconfiguration by configuring intrinsic properties.\n _configureIntrinsicPropertiesFor(\n _projectId,\n _configuration,\n _data.weight,\n // Must start on or after the current timestamp.\n _mustStartAtOrAfter > block.timestamp ? _mustStartAtOrAfter : block.timestamp\n );\n\n // Efficiently stores a funding cycles provided user defined properties.\n // If all user config properties are zero, no need to store anything as the default value will have the same outcome.\n if (\n _data.ballot != IJBFundingCycleBallot(address(0)) ||\n _data.duration > 0 ||\n _data.discountRate > 0\n ) {\n // ballot in bits 0-159 bytes.\n uint256 packed = uint160(address(_data.ballot));\n\n // duration in bits 160-223 bytes.\n packed |= _data.duration << 160;\n\n // discountRate in bits 224-255 bytes.\n packed |= _data.discountRate << 224;\n\n // Set in storage.\n _packedUserPropertiesOf[_projectId][_configuration] = packed;\n }\n\n // Set the metadata if needed.\n if (_metadata > 0) _metadataOf[_projectId][_configuration] = _metadata;\n\n emit Configure(_configuration, _projectId, _data, _metadata, _mustStartAtOrAfter, msg.sender);\n\n // Return the funding cycle for the new configuration.\n return _getStructFor(_projectId, _configuration);\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice \n Updates the configurable funding cycle for this project if it exists, otherwise creates one.\n\n @param _projectId The ID of the project to find a configurable funding cycle for.\n @param _configuration The time at which the funding cycle was configured.\n @param _weight The weight to store in the configured funding cycle.\n @param _mustStartAtOrAfter The time before which the initialized funding cycle can't start.\n */\n function _configureIntrinsicPropertiesFor(\n uint256 _projectId,\n uint256 _configuration,\n uint256 _weight,\n uint256 _mustStartAtOrAfter\n ) private {\n // If there's not yet a funding cycle for the project, initialize one.\n if (latestConfigurationOf[_projectId] == 0)\n // Use an empty funding cycle as the base.\n return\n _initFor(_projectId, _getStructFor(0, 0), _configuration, _mustStartAtOrAfter, _weight);\n\n // Get the active funding cycle's configuration.\n uint256 _currentConfiguration = _eligibleOf(_projectId);\n\n // If an eligible funding cycle does not exist, get a reference to the latest funding cycle configuration for the project.\n if (_currentConfiguration == 0)\n // Get the latest funding cycle's configuration.\n _currentConfiguration = latestConfigurationOf[_projectId];\n\n // Get a reference to the funding cycle.\n JBFundingCycle memory _baseFundingCycle = _getStructFor(_projectId, _currentConfiguration);\n\n if (!_isApproved(_projectId, _baseFundingCycle) || block.timestamp < _baseFundingCycle.start)\n // If it hasn't been approved or hasn't yet started, set the ID to be the funding cycle it's based on,\n // which carries the latest approved configuration.\n _baseFundingCycle = _getStructFor(_projectId, _baseFundingCycle.basedOn);\n\n // The configuration can't be the same as the base configuration.\n if (_baseFundingCycle.configuration == _configuration) revert NO_SAME_BLOCK_RECONFIGURATION();\n\n // The time after the ballot of the provided funding cycle has expired.\n // If the provided funding cycle has no ballot, return the current timestamp.\n uint256 _timestampAfterBallot = _baseFundingCycle.ballot == IJBFundingCycleBallot(address(0))\n ? 0\n : _configuration + _baseFundingCycle.ballot.duration();\n\n _initFor(\n _projectId,\n _baseFundingCycle,\n _configuration,\n // Can only start after the ballot.\n _timestampAfterBallot > _mustStartAtOrAfter ? _timestampAfterBallot : _mustStartAtOrAfter,\n _weight\n );\n }\n\n /**\n @notice \n Initializes a funding cycle with the specified properties.\n\n @param _projectId The ID of the project to which the funding cycle being initialized belongs.\n @param _baseFundingCycle The funding cycle to base the initialized one on.\n @param _configuration The configuration of the funding cycle being initialized.\n @param _mustStartAtOrAfter The time before which the initialized funding cycle cannot start.\n @param _weight The weight to give the newly initialized funding cycle.\n */\n function _initFor(\n uint256 _projectId,\n JBFundingCycle memory _baseFundingCycle,\n uint256 _configuration,\n uint256 _mustStartAtOrAfter,\n uint256 _weight\n ) private {\n // If there is no base, initialize a first cycle.\n if (_baseFundingCycle.number == 0) {\n // The first number is 1.\n uint256 _number = 1;\n\n // Set fresh intrinsic properties.\n _packAndStoreIntrinsicPropertiesOf(\n _configuration,\n _projectId,\n _number,\n _weight,\n _baseFundingCycle.configuration,\n _mustStartAtOrAfter\n );\n } else {\n // Derive the correct next start time from the base.\n uint256 _start = _deriveStartFrom(_baseFundingCycle, _mustStartAtOrAfter);\n\n // A weight of 1 is treated as a weight of 0.\n // This is to allow a weight of 0 (default) to represent inheriting the discounted weight of the previous funding cycle.\n _weight = _weight > 0\n ? (_weight == 1 ? 0 : _weight)\n : _deriveWeightFrom(_baseFundingCycle, _start);\n\n // Derive the correct number.\n uint256 _number = _deriveNumberFrom(_baseFundingCycle, _start);\n\n // Update the intrinsic properties.\n _packAndStoreIntrinsicPropertiesOf(\n _configuration,\n _projectId,\n _number,\n _weight,\n _baseFundingCycle.configuration,\n _start\n );\n }\n\n // Set the project's latest funding cycle configuration.\n latestConfigurationOf[_projectId] = _configuration;\n\n emit Init(_configuration, _projectId, _baseFundingCycle.configuration);\n }\n\n /**\n @notice \n Efficiently stores a funding cycle's provided intrinsic properties.\n\n @param _configuration The configuration of the funding cycle to pack and store.\n @param _projectId The ID of the project to which the funding cycle belongs.\n @param _number The number of the funding cycle.\n @param _weight The weight of the funding cycle.\n @param _basedOn The configuration of the base funding cycle.\n @param _start The start time of this funding cycle.\n */\n function _packAndStoreIntrinsicPropertiesOf(\n uint256 _configuration,\n uint256 _projectId,\n uint256 _number,\n uint256 _weight,\n uint256 _basedOn,\n uint256 _start\n ) private {\n // weight in bits 0-87.\n uint256 packed = _weight;\n\n // basedOn in bits 88-143.\n packed |= _basedOn << 88;\n\n // start in bits 144-199.\n packed |= _start << 144;\n\n // number in bits 200-255.\n packed |= _number << 200;\n\n // Store the packed value.\n _packedIntrinsicPropertiesOf[_projectId][_configuration] = packed;\n }\n\n /**\n @notice \n The project's stored funding cycle that hasn't yet started and should be used next, if one exists.\n\n @dev\n A value of 0 is returned if no funding cycle was found.\n\n @dev\n Assumes the project has a latest configuration.\n \n @param _projectId The ID of a project to look through for a standby cycle.\n\n @return configuration The configuration of the standby funding cycle if one exists, or 0 if one doesn't exist.\n */\n function _standbyOf(uint256 _projectId) private view returns (uint256 configuration) {\n // Get a reference to the project's latest funding cycle.\n configuration = latestConfigurationOf[_projectId];\n\n // Get the necessary properties for the latest funding cycle.\n JBFundingCycle memory _fundingCycle = _getStructFor(_projectId, configuration);\n\n // There is no upcoming funding cycle if the latest funding cycle has already started.\n if (block.timestamp >= _fundingCycle.start) return 0;\n\n // If this is the first funding cycle, it is queued.\n if (_fundingCycle.number == 1) return configuration;\n\n // Get the necessary properties for the base funding cycle.\n JBFundingCycle memory _baseFundingCycle = _getStructFor(_projectId, _fundingCycle.basedOn);\n\n // If the latest configuration doesn't start until after another base cycle, return 0.\n if (\n _baseFundingCycle.duration > 0 &&\n block.timestamp < _fundingCycle.start - _baseFundingCycle.duration\n ) return 0;\n }\n\n /**\n @notice \n The project's stored funding cycle that has started and hasn't yet expired.\n \n @dev\n A value of 0 is returned if no funding cycle was found.\n\n @dev\n Assumes the project has a latest configuration.\n\n @param _projectId The ID of the project to look through.\n\n @return configuration The configuration of an eligible funding cycle if one exists, or 0 if one doesn't exist.\n */\n function _eligibleOf(uint256 _projectId) private view returns (uint256 configuration) {\n // Get a reference to the project's latest funding cycle.\n configuration = latestConfigurationOf[_projectId];\n\n // Get the latest funding cycle.\n JBFundingCycle memory _fundingCycle = _getStructFor(_projectId, configuration);\n\n // If the latest is expired, return an empty funding cycle.\n // A duration of 0 cannot be expired.\n if (\n _fundingCycle.duration > 0 && block.timestamp >= _fundingCycle.start + _fundingCycle.duration\n ) return 0;\n\n // Return the funding cycle's configuration if it has started.\n if (block.timestamp >= _fundingCycle.start) return _fundingCycle.configuration;\n\n // Get a reference to the cycle's base configuration.\n JBFundingCycle memory _baseFundingCycle = _getStructFor(_projectId, _fundingCycle.basedOn);\n\n // If the base cycle isn't eligible, the project has no eligible cycle.\n // A duration of 0 is always eligible.\n if (\n _baseFundingCycle.duration > 0 &&\n block.timestamp >= _baseFundingCycle.start + _baseFundingCycle.duration\n ) return 0;\n\n // Return the configuration that the latest funding cycle is based on.\n configuration = _fundingCycle.basedOn;\n }\n\n /** \n @notice \n A view of the funding cycle that would be created based on the provided one if the project doesn't make a reconfiguration.\n\n @dev\n Returns an empty funding cycle if there can't be a mock funding cycle based on the provided one.\n\n @dev\n Assumes a funding cycle with a duration of 0 will never be asked to be the base of a mock.\n\n @param _baseFundingCycle The funding cycle that the resulting funding cycle should follow.\n @param _allowMidCycle A flag indicating if the mocked funding cycle is allowed to already be mid cycle.\n\n @return A mock of what the next funding cycle will be.\n */\n function _mockFundingCycleBasedOn(JBFundingCycle memory _baseFundingCycle, bool _allowMidCycle)\n private\n view\n returns (JBFundingCycle memory)\n {\n // Get the distance of the current time to the start of the next possible funding cycle.\n // If the returned mock cycle must not yet have started, the start time of the mock must be in the future.\n uint256 _mustStartAtOrAfter = !_allowMidCycle\n ? block.timestamp + 1\n : block.timestamp - _baseFundingCycle.duration + 1;\n\n // Derive what the start time should be.\n uint256 _start = _deriveStartFrom(_baseFundingCycle, _mustStartAtOrAfter);\n\n // Derive what the number should be.\n uint256 _number = _deriveNumberFrom(_baseFundingCycle, _start);\n\n return\n JBFundingCycle(\n _number,\n _baseFundingCycle.configuration,\n _baseFundingCycle.basedOn,\n _start,\n _baseFundingCycle.duration,\n _deriveWeightFrom(_baseFundingCycle, _start),\n _baseFundingCycle.discountRate,\n _baseFundingCycle.ballot,\n _baseFundingCycle.metadata\n );\n }\n\n /** \n @notice \n The date that is the nearest multiple of the specified funding cycle's duration from its end.\n\n @param _baseFundingCycle The funding cycle to base the calculation on.\n @param _mustStartAtOrAfter A date that the derived start must be on or come after.\n\n @return start The next start time.\n */\n function _deriveStartFrom(JBFundingCycle memory _baseFundingCycle, uint256 _mustStartAtOrAfter)\n private\n pure\n returns (uint256 start)\n {\n // A subsequent cycle to one with a duration of 0 should start as soon as possible.\n if (_baseFundingCycle.duration == 0) return _mustStartAtOrAfter;\n\n // The time when the funding cycle immediately after the specified funding cycle starts.\n uint256 _nextImmediateStart = _baseFundingCycle.start + _baseFundingCycle.duration;\n\n // If the next immediate start is now or in the future, return it.\n if (_nextImmediateStart >= _mustStartAtOrAfter) return _nextImmediateStart;\n\n // The amount of seconds since the `_mustStartAtOrAfter` time which results in a start time that might satisfy the specified constraints.\n uint256 _timeFromImmediateStartMultiple = (_mustStartAtOrAfter - _nextImmediateStart) %\n _baseFundingCycle.duration;\n\n // A reference to the first possible start timestamp.\n start = _mustStartAtOrAfter - _timeFromImmediateStartMultiple;\n\n // Add increments of duration as necessary to satisfy the threshold.\n while (_mustStartAtOrAfter > start) start = start + _baseFundingCycle.duration;\n }\n\n /** \n @notice \n The accumulated weight change since the specified funding cycle.\n\n @param _baseFundingCycle The funding cycle to base the calculation on.\n @param _start The start time of the funding cycle to derive a number for.\n\n @return weight The derived weight, as a fixed point number with 18 decimals.\n */\n function _deriveWeightFrom(JBFundingCycle memory _baseFundingCycle, uint256 _start)\n private\n pure\n returns (uint256 weight)\n {\n // A subsequent cycle to one with a duration of 0 should have the next possible weight.\n if (_baseFundingCycle.duration == 0)\n return\n PRBMath.mulDiv(\n _baseFundingCycle.weight,\n JBConstants.MAX_DISCOUNT_RATE - _baseFundingCycle.discountRate,\n JBConstants.MAX_DISCOUNT_RATE\n );\n\n // The weight should be based off the base funding cycle's weight.\n weight = _baseFundingCycle.weight;\n\n // If the discount is 0, the weight doesn't change.\n if (_baseFundingCycle.discountRate == 0) return weight;\n\n // The difference between the start of the base funding cycle and the proposed start.\n uint256 _startDistance = _start - _baseFundingCycle.start;\n\n // Apply the base funding cycle's discount rate for each cycle that has passed.\n uint256 _discountMultiple = _startDistance / _baseFundingCycle.duration;\n\n for (uint256 i = 0; i < _discountMultiple; i++) {\n // The number of times to apply the discount rate.\n // Base the new weight on the specified funding cycle's weight.\n weight = PRBMath.mulDiv(\n weight,\n JBConstants.MAX_DISCOUNT_RATE - _baseFundingCycle.discountRate,\n JBConstants.MAX_DISCOUNT_RATE\n );\n // The calculation doesn't need to continue if the weight is 0.\n if (weight == 0) break;\n }\n }\n\n /** \n @notice \n The number of the next funding cycle given the specified funding cycle.\n\n @param _baseFundingCycle The funding cycle to base the calculation on.\n @param _start The start time of the funding cycle to derive a number for.\n\n @return The funding cycle number.\n */\n function _deriveNumberFrom(JBFundingCycle memory _baseFundingCycle, uint256 _start)\n private\n pure\n returns (uint256)\n {\n // A subsequent cycle to one with a duration of 0 should be the next number.\n if (_baseFundingCycle.duration == 0) return _baseFundingCycle.number + 1;\n\n // The difference between the start of the base funding cycle and the proposed start.\n uint256 _startDistance = _start - _baseFundingCycle.start;\n\n // Find the number of base cycles that fit in the start distance.\n return _baseFundingCycle.number + (_startDistance / _baseFundingCycle.duration);\n }\n\n /** \n @notice \n Checks to see if the provided funding cycle is approved according to the correct ballot.\n\n @param _projectId The ID of the project to which the funding cycle belongs. \n @param _fundingCycle The funding cycle to get an approval flag for.\n\n @return The approval flag.\n */\n function _isApproved(uint256 _projectId, JBFundingCycle memory _fundingCycle)\n private\n view\n returns (bool)\n {\n return\n _ballotStateOf(\n _projectId,\n _fundingCycle.configuration,\n _fundingCycle.start,\n _fundingCycle.basedOn\n ) == JBBallotState.Approved;\n }\n\n /**\n @notice \n A project's latest funding cycle configuration approval status.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n @param _configuration The funding cycle configuration to get the ballot state of.\n @param _start The start time of the funding cycle configuration to get the ballot state of.\n @param _ballotFundingCycleConfiguration The configuration of the funding cycle which is configured with the ballot that should be used.\n\n @return The ballot state of the project.\n */\n function _ballotStateOf(\n uint256 _projectId,\n uint256 _configuration,\n uint256 _start,\n uint256 _ballotFundingCycleConfiguration\n ) private view returns (JBBallotState) {\n // If there is no ballot funding cycle, implicitly approve.\n if (_ballotFundingCycleConfiguration == 0) return JBBallotState.Approved;\n\n // Get the ballot funding cycle.\n JBFundingCycle memory _ballotFundingCycle = _getStructFor(\n _projectId,\n _ballotFundingCycleConfiguration\n );\n\n // If there is no ballot, the ID is auto approved.\n // Otherwise if the ballot's duration hasn't passed, its still active.\n // Otherwise, return the ballot's state.\n if (_ballotFundingCycle.ballot == IJBFundingCycleBallot(address(0)))\n return JBBallotState.Approved;\n else if (_ballotFundingCycle.ballot.duration() >= block.timestamp - _configuration)\n return JBBallotState.Active;\n else return _ballotFundingCycle.ballot.stateOf(_projectId, _configuration, _start);\n }\n\n /**\n @notice \n Unpack a funding cycle's packed stored values into an easy-to-work-with funding cycle struct.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n @param _configuration The funding cycle configuration to get the full struct for.\n\n @return fundingCycle A funding cycle struct.\n */\n function _getStructFor(uint256 _projectId, uint256 _configuration)\n private\n view\n returns (JBFundingCycle memory fundingCycle)\n {\n // Return an empty funding cycle if the configuration specified is 0.\n if (_configuration == 0) return fundingCycle;\n\n fundingCycle.configuration = _configuration;\n\n uint256 _packedIntrinsicProperties = _packedIntrinsicPropertiesOf[_projectId][_configuration];\n\n // weight in bits 0-87 bits.\n fundingCycle.weight = uint256(uint88(_packedIntrinsicProperties));\n // basedOn in bits 88-143 bits.\n fundingCycle.basedOn = uint256(uint56(_packedIntrinsicProperties >> 88));\n // start in bits 144-199 bits.\n fundingCycle.start = uint256(uint56(_packedIntrinsicProperties >> 144));\n // number in bits 200-255 bits.\n fundingCycle.number = uint256(uint56(_packedIntrinsicProperties >> 200));\n\n uint256 _packedUserProperties = _packedUserPropertiesOf[_projectId][_configuration];\n\n // ballot in bits 0-159 bits.\n fundingCycle.ballot = IJBFundingCycleBallot(address(uint160(_packedUserProperties)));\n // duration in bits 160-223 bits.\n fundingCycle.duration = uint256(uint64(_packedUserProperties >> 160));\n // discountRate in bits 224-255 bits.\n fundingCycle.discountRate = uint256(uint32(_packedUserProperties >> 224));\n\n fundingCycle.metadata = _metadataOf[_projectId][_configuration];\n }\n}\n" @@ -170,7 +170,7 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './../interfaces/IJBSplitAllocator.sol';\n\n/** \n @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.\n @member preferAddToBalance A flag indicating if a distribution to a project should prefer triggering it's addToBalance function instead of its pay function.\n @member percent The percent of the whole group that this split occupies. This number is out of `JBConstants.SPLITS_TOTAL_PERCENT`.\n @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.\n @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.\n @member lockedUntil Specifies if the split should be unchangeable until the specified time, with the exception of extending the locked period.\n @member allocator If an allocator is specified, funds will be sent to the allocator contract along with all properties of this split.\n*/\nstruct JBSplit {\n bool preferClaimed;\n bool preferAddToBalance;\n uint256 percent;\n uint256 projectId;\n address payable beneficiary;\n uint256 lockedUntil;\n IJBSplitAllocator allocator;\n}\n" }, "contracts/system_tests/helpers/AccessJBLib.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '../../libraries/JBCurrencies.sol';\nimport '../../libraries/JBConstants.sol';\nimport '../../libraries/JBTokens.sol';\n\ncontract AccessJBLib {\n function ETH() external pure returns (uint256) {\n return JBCurrencies.ETH;\n }\n\n function USD() external pure returns (uint256) {\n return JBCurrencies.USD;\n }\n\n function ETHToken() external pure returns (address) {\n return JBTokens.ETH;\n }\n\n function MAX_FEE() external pure returns (uint256) {\n return JBConstants.MAX_FEE;\n }\n\n function MAX_RESERVED_RATE() external pure returns (uint256) {\n return JBConstants.MAX_RESERVED_RATE;\n }\n\n function MAX_REDEMPTION_RATE() external pure returns (uint256) {\n return JBConstants.MAX_REDEMPTION_RATE;\n }\n\n function MAX_DISCOUNT_RATE() external pure returns (uint256) {\n return JBConstants.MAX_DISCOUNT_RATE;\n }\n\n function SPLITS_TOTAL_PERCENT() external pure returns (uint256) {\n return JBConstants.SPLITS_TOTAL_PERCENT;\n }\n\n function MAX_FEE_DISCOUNT() external pure returns (uint256) {\n return JBConstants.MAX_FEE_DISCOUNT;\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '../../libraries/JBCurrencies.sol';\nimport '../../libraries/JBConstants.sol';\nimport '../../libraries/JBTokens.sol';\n\ncontract AccessJBLib {\n function ETH() external pure returns (uint256) {\n return JBCurrencies.GAS_CURRENCY;\n }\n\n function USD() external pure returns (uint256) {\n return JBCurrencies.USD;\n }\n\n function ETHToken() external pure returns (address) {\n return JBTokens.GAS_TOKEN;\n }\n\n function MAX_FEE() external pure returns (uint256) {\n return JBConstants.MAX_FEE;\n }\n\n function MAX_RESERVED_RATE() external pure returns (uint256) {\n return JBConstants.MAX_RESERVED_RATE;\n }\n\n function MAX_REDEMPTION_RATE() external pure returns (uint256) {\n return JBConstants.MAX_REDEMPTION_RATE;\n }\n\n function MAX_DISCOUNT_RATE() external pure returns (uint256) {\n return JBConstants.MAX_DISCOUNT_RATE;\n }\n\n function SPLITS_TOTAL_PERCENT() external pure returns (uint256) {\n return JBConstants.SPLITS_TOTAL_PERCENT;\n }\n\n function MAX_FEE_DISCOUNT() external pure returns (uint256) {\n return JBConstants.MAX_FEE_DISCOUNT;\n }\n}\n" }, "@paulrberg/contracts/math/PRBMath.sol": { "content": "// SPDX-License-Identifier: Unlicense\npragma solidity >=0.8.4;\n\nimport \"prb-math/contracts/PRBMath.sol\";\n" @@ -227,7 +227,7 @@ "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" }, "contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBSplitsGroups.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal is\n IJBPayoutRedemptionPaymentTerminal,\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n ReentrancyGuard\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The protocol project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _PROTOCOL_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.ETH)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.ETH, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.ETH) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i = 0; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @dev\n If the fee gauge reverts when called upon while a project is attempting to distribute its funds, a project's funds will be locked. This is a known risk.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual;\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual;\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegate` only used within scope.\n {\n IJBRedemptionDelegate _delegate;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegate, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If a delegate was returned by the data source, issue a callback to it.\n if (_delegate != IJBRedemptionDelegate(address(0))) {\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _beneficiary,\n _memo,\n _metadata\n );\n _delegate.didRedeem(_data);\n emit DelegateDidRedeem(_delegate, _data, msg.sender);\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convinience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n\n // Take the fee.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || _feeEligibleDistributionAmount == 0\n ? 0\n : _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n );\n\n // Get a reference to how much to distribute to the project owner, which is the leftover amount minus any fees.\n\n unchecked {\n netLeftoverDistributionAmount = _leftoverDistributionAmount == 0\n ? 0\n : _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n }\n\n // Transfer any remaining balance to the project owner.\n if (netLeftoverDistributionAmount > 0)\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convinience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i = 0; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount;\n\n if (_payoutAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (isFeelessAddress[address(_split.allocator)])\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _netPayoutAmount : 0;\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n _netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // Save gas if this contract is being used as the terminal.\n if (_terminal == this) {\n // This distribution does not incur a fee.\n _netPayoutAmount = _payoutAmount;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\n else\n _pay(\n _netPayoutAmount,\n address(this),\n _split.projectId,\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n } else {\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (isFeelessAddress[address(_terminal)])\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _netPayoutAmount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _terminal.addToBalanceOf{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n '',\n _projectMetadata\n );\n else\n _terminal.pay{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n }\n } else {\n unchecked {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(\n address(this),\n _split.beneficiary != address(0) ? _split.beneficiary : payable(msg.sender),\n _netPayoutAmount\n );\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _PROTOCOL_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n */\n function _processFee(uint256 _amount, address _beneficiary) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_PROTOCOL_PROJECT_ID, token);\n\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\n if (_terminal == this)\n _pay(_amount, address(this), _PROTOCOL_PROJECT_ID, _beneficiary, 0, false, '', bytes('')); // Use the local pay call.\n else {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _amount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _amount : 0;\n\n // Send the payment.\n _terminal.pay{value: _payableValue}(\n _PROTOCOL_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the external pay call of the correct terminal.\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegate` and `_tokenCount` only used within scope.\n {\n IJBPayDelegate _delegate;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegate, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If a delegate was returned by the data source, issue a callback to it.\n if (_delegate != IJBPayDelegate(address(0))) {\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n _delegate.didPay(_data);\n emit DelegateDidPay(_delegate, _data, msg.sender);\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i = 0; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n unchecked {\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256 feeDiscount) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (directory.primaryTerminalOf(_PROTOCOL_PROJECT_ID, token) == IJBPaymentTerminal(address(0)))\n return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge == IJBFeeGauge(address(0)))\n feeDiscount = 0;\n // If the guage reverts, set the discount to 0.\n else\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n feeDiscount = discount;\n } catch {\n feeDiscount = 0;\n }\n\n // If the fee discount is greater than the max, nullify the discount.\n if (feeDiscount > JBConstants.MAX_FEE_DISCOUNT) feeDiscount = 0;\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBSplitsGroups.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal is\n IJBPayoutRedemptionPaymentTerminal,\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n ReentrancyGuard\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The protocol project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _PROTOCOL_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.GAS_CURRENCY)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.GAS_CURRENCY, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.GAS_TOKEN) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i = 0; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @dev\n If the fee gauge reverts when called upon while a project is attempting to distribute its funds, a project's funds will be locked. This is a known risk.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual;\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual;\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegate` only used within scope.\n {\n IJBRedemptionDelegate _delegate;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegate, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If a delegate was returned by the data source, issue a callback to it.\n if (_delegate != IJBRedemptionDelegate(address(0))) {\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _beneficiary,\n _memo,\n _metadata\n );\n _delegate.didRedeem(_data);\n emit DelegateDidRedeem(_delegate, _data, msg.sender);\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convinience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n\n // Take the fee.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || _feeEligibleDistributionAmount == 0\n ? 0\n : _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n );\n\n // Get a reference to how much to distribute to the project owner, which is the leftover amount minus any fees.\n\n unchecked {\n netLeftoverDistributionAmount = _leftoverDistributionAmount == 0\n ? 0\n : _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n }\n\n // Transfer any remaining balance to the project owner.\n if (netLeftoverDistributionAmount > 0)\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convinience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i = 0; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount;\n\n if (_payoutAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (isFeelessAddress[address(_split.allocator)])\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0;\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n _netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // Save gas if this contract is being used as the terminal.\n if (_terminal == this) {\n // This distribution does not incur a fee.\n _netPayoutAmount = _payoutAmount;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\n else\n _pay(\n _netPayoutAmount,\n address(this),\n _split.projectId,\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n } else {\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (isFeelessAddress[address(_terminal)])\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _terminal.addToBalanceOf{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n '',\n _projectMetadata\n );\n else\n _terminal.pay{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n }\n } else {\n unchecked {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(\n address(this),\n _split.beneficiary != address(0) ? _split.beneficiary : payable(msg.sender),\n _netPayoutAmount\n );\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _PROTOCOL_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n */\n function _processFee(uint256 _amount, address _beneficiary) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_PROTOCOL_PROJECT_ID, token);\n\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\n if (_terminal == this)\n _pay(_amount, address(this), _PROTOCOL_PROJECT_ID, _beneficiary, 0, false, '', bytes('')); // Use the local pay call.\n else {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _amount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send the payment.\n _terminal.pay{value: _payableValue}(\n _PROTOCOL_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the external pay call of the correct terminal.\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegate` and `_tokenCount` only used within scope.\n {\n IJBPayDelegate _delegate;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegate, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If a delegate was returned by the data source, issue a callback to it.\n if (_delegate != IJBPayDelegate(address(0))) {\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n _delegate.didPay(_data);\n emit DelegateDidPay(_delegate, _data, msg.sender);\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i = 0; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n unchecked {\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256 feeDiscount) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (directory.primaryTerminalOf(_PROTOCOL_PROJECT_ID, token) == IJBPaymentTerminal(address(0)))\n return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge == IJBFeeGauge(address(0)))\n feeDiscount = 0;\n // If the guage reverts, set the discount to 0.\n else\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n feeDiscount = discount;\n } catch {\n feeDiscount = 0;\n }\n\n // If the fee discount is greater than the max, nullify the discount.\n if (feeDiscount > JBConstants.MAX_FEE_DISCOUNT) feeDiscount = 0;\n }\n}\n" }, "@openzeppelin/contracts/security/ReentrancyGuard.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n constructor() {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n // On the first call to nonReentrant, _notEntered will be true\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n\n _;\n\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n}\n" @@ -311,31 +311,31 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './IJBFundingCycleBallot.sol';\n\ninterface IJBReconfigurationBufferBallot is IJBFundingCycleBallot {\n event Finalize(\n uint256 indexed projectId,\n uint256 indexed configuration,\n JBBallotState indexed ballotState,\n address caller\n );\n\n function finalState(uint256 _projectId, uint256 _configuration)\n external\n view\n returns (JBBallotState);\n\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\n\n function finalize(uint256 _projectId, uint256 _configured) external returns (JBBallotState);\n}\n" }, "contracts/system_tests/TestEIP165.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './helpers/TestBaseWorkflow.sol';\nimport '../JBReconfigurationBufferBallot.sol';\nimport '../JBETHERC20SplitsPayer.sol';\n\ncontract TestEIP165 is TestBaseWorkflow {\n bytes4 constant notSupportedInterface = 0xffffffff;\n\n uint256 constant projectId = 2;\n uint256 constant splitsProjectID = 3;\n address payable constant splitsBeneficiary = payable(address(420));\n uint256 constant splitsDomain = 1;\n uint256 constant splitsGroup = 1;\n bool constant splitsPreferClaimedTokens = false;\n string constant splitsMemo = '';\n bytes constant splitsMetadata = '';\n bool constant splitsPreferAddToBalance = true;\n address constant splitsOwner = address(420);\n\n function testJBController() public {\n JBController controller = jbController();\n\n // Should support these interfaces\n assertTrue(controller.supportsInterface(type(IERC165).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBController).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBMigratable).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!controller.supportsInterface(notSupportedInterface));\n }\n\n function testJBERC20PaymentTerminal() public {\n JBERC20PaymentTerminal terminal = new JBERC20PaymentTerminal(\n jbToken(),\n jbLibraries().USD(), // currency\n jbLibraries().ETH(), // base weight currency\n 1, // JBSplitsGroupe\n jbOperatorStore(),\n jbProjects(),\n jbDirectory(),\n jbSplitsStore(),\n jbPrices(),\n jbPaymentTerminalStore(),\n multisig()\n );\n\n // Should support these interfaces\n assertTrue(terminal.supportsInterface(type(IERC165).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBRedemptionTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBSingleTokenPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!terminal.supportsInterface(notSupportedInterface));\n }\n\n function testJBETHPaymentTerminal() public {\n JBETHPaymentTerminal terminal = jbETHPaymentTerminal();\n\n // Should support these interfaces\n assertTrue(terminal.supportsInterface(type(IERC165).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBRedemptionTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBSingleTokenPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!terminal.supportsInterface(notSupportedInterface));\n }\n\n function testJBProjects() public {\n JBProjects projects = jbProjects();\n\n // Should support these interfaces\n assertTrue(projects.supportsInterface(type(IERC165).interfaceId));\n assertTrue(projects.supportsInterface(type(IERC721).interfaceId));\n assertTrue(projects.supportsInterface(type(IERC721Metadata).interfaceId));\n assertTrue(projects.supportsInterface(type(IJBProjects).interfaceId));\n assertTrue(projects.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!projects.supportsInterface(notSupportedInterface));\n }\n\n function testJBReconfigurationBufferBallot() public {\n JBReconfigurationBufferBallot ballot = new JBReconfigurationBufferBallot(\n 3000,\n jbFundingCycleStore()\n );\n\n // Should support these interfaces\n assertTrue(ballot.supportsInterface(type(IERC165).interfaceId));\n assertTrue(ballot.supportsInterface(type(IJBReconfigurationBufferBallot).interfaceId));\n assertTrue(ballot.supportsInterface(type(IJBFundingCycleBallot).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!ballot.supportsInterface(notSupportedInterface));\n }\n\n function testJBETHERC20SplitsPayer() public {\n JBETHERC20SplitsPayer splitsPayer = new JBETHERC20SplitsPayer(\n splitsProjectID,\n splitsDomain,\n splitsGroup,\n jbSplitsStore(),\n projectId,\n splitsBeneficiary,\n splitsPreferClaimedTokens,\n splitsMemo,\n splitsMetadata,\n splitsPreferAddToBalance,\n splitsOwner\n );\n\n // Should support these interfaces\n assertTrue(splitsPayer.supportsInterface(type(IERC165).interfaceId));\n assertTrue(splitsPayer.supportsInterface(type(IJBSplitsPayer).interfaceId));\n assertTrue(splitsPayer.supportsInterface(type(IJBProjectPayer).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!splitsPayer.supportsInterface(notSupportedInterface));\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './helpers/TestBaseWorkflow.sol';\nimport '../JBReconfigurationBufferBallot.sol';\nimport '../JBGasTokenERC20SplitsPayer.sol';\n\ncontract TestEIP165 is TestBaseWorkflow {\n bytes4 constant notSupportedInterface = 0xffffffff;\n\n uint256 constant projectId = 2;\n uint256 constant splitsProjectID = 3;\n address payable constant splitsBeneficiary = payable(address(420));\n uint256 constant splitsDomain = 1;\n uint256 constant splitsGroup = 1;\n bool constant splitsPreferClaimedTokens = false;\n string constant splitsMemo = '';\n bytes constant splitsMetadata = '';\n bool constant splitsPreferAddToBalance = true;\n address constant splitsOwner = address(420);\n\n function testJBController() public {\n JBController controller = jbController();\n\n // Should support these interfaces\n assertTrue(controller.supportsInterface(type(IERC165).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBController).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBMigratable).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!controller.supportsInterface(notSupportedInterface));\n }\n\n function testJBERC20PaymentTerminal() public {\n JBERC20PaymentTerminal terminal = new JBERC20PaymentTerminal(\n jbToken(),\n jbLibraries().USD(), // currency\n jbLibraries().ETH(), // base weight currency\n 1, // JBSplitsGroupe\n jbOperatorStore(),\n jbProjects(),\n jbDirectory(),\n jbSplitsStore(),\n jbPrices(),\n jbPaymentTerminalStore(),\n multisig()\n );\n\n // Should support these interfaces\n assertTrue(terminal.supportsInterface(type(IERC165).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBRedemptionTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBSingleTokenPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!terminal.supportsInterface(notSupportedInterface));\n }\n\n function testJBETHPaymentTerminal() public {\n JBETHPaymentTerminal terminal = jbETHPaymentTerminal();\n\n // Should support these interfaces\n assertTrue(terminal.supportsInterface(type(IERC165).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBRedemptionTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBSingleTokenPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!terminal.supportsInterface(notSupportedInterface));\n }\n\n function testJBProjects() public {\n JBProjects projects = jbProjects();\n\n // Should support these interfaces\n assertTrue(projects.supportsInterface(type(IERC165).interfaceId));\n assertTrue(projects.supportsInterface(type(IERC721).interfaceId));\n assertTrue(projects.supportsInterface(type(IERC721Metadata).interfaceId));\n assertTrue(projects.supportsInterface(type(IJBProjects).interfaceId));\n assertTrue(projects.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!projects.supportsInterface(notSupportedInterface));\n }\n\n function testJBReconfigurationBufferBallot() public {\n JBReconfigurationBufferBallot ballot = new JBReconfigurationBufferBallot(\n 3000,\n jbFundingCycleStore()\n );\n\n // Should support these interfaces\n assertTrue(ballot.supportsInterface(type(IERC165).interfaceId));\n assertTrue(ballot.supportsInterface(type(IJBReconfigurationBufferBallot).interfaceId));\n assertTrue(ballot.supportsInterface(type(IJBFundingCycleBallot).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!ballot.supportsInterface(notSupportedInterface));\n }\n\n function testJBGasTokenERC20SplitsPayer() public {\n JBGasTokenERC20SplitsPayer splitsPayer = new JBGasTokenERC20SplitsPayer(\n splitsProjectID,\n splitsDomain,\n splitsGroup,\n jbSplitsStore(),\n projectId,\n splitsBeneficiary,\n splitsPreferClaimedTokens,\n splitsMemo,\n splitsMetadata,\n splitsPreferAddToBalance,\n splitsOwner\n );\n\n // Should support these interfaces\n assertTrue(splitsPayer.supportsInterface(type(IERC165).interfaceId));\n assertTrue(splitsPayer.supportsInterface(type(IJBSplitsPayer).interfaceId));\n assertTrue(splitsPayer.supportsInterface(type(IJBProjectPayer).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!splitsPayer.supportsInterface(notSupportedInterface));\n }\n}\n" }, - "contracts/JBETHERC20SplitsPayer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBSplitsPayer.sol';\nimport './interfaces/IJBSplitsStore.sol';\nimport './libraries/JBConstants.sol';\nimport './JBETHERC20ProjectPayer.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\n\n @dev\n Adheres to -\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBETHERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBETHERC20SplitsPayer is IJBSplitsPayer, JBETHERC20ProjectPayer, ReentrancyGuard {\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The ID of project for which the default splits are stored. \n */\n uint256 public override defaultSplitsProjectId;\n\n /**\n @notice\n The domain within which the default splits are stored. \n */\n uint256 public override defaultSplitsDomain;\n\n /**\n @notice\n The group within which the default splits are stored. \n */\n uint256 public override defaultSplitsGroup;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBETHERC20ProjectPayer, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n )\n JBETHERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _preferAddToBalance,\n _splitsStore.directory(),\n _owner\n )\n {\n defaultSplitsProjectId = _defaultSplitsProjectId;\n defaultSplitsDomain = _defaultSplitsDomain;\n defaultSplitsGroup = _defaultSplitsGroup;\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default split group using the stored default properties.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override nonReentrant {\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n JBTokens.ETH,\n address(this).balance,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender\n );\n\n // If there is no leftover amount, nothing left to pay.\n if (_leftoverAmount == 0) return;\n\n // If there's a default project ID, try to pay it.\n if (defaultProjectId != 0)\n if (defaultPreferAddToBalance)\n // Pay the project by adding to its balance if prefered.\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.ETH,\n _leftoverAmount,\n 18, // decimals.\n defaultMemo,\n defaultMetadata\n );\n // Otherwise, issue a payment to the project.\n else\n _pay(\n defaultProjectId,\n JBTokens.ETH,\n _leftoverAmount,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n 0, // min returned tokens.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n // If no project was specified, send the funds directly to the beneficiary or the msg.sender.\n else\n Address.sendValue(\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(msg.sender),\n _leftoverAmount\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the location of the splits that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n */\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) external virtual override onlyOwner {\n // Set the default splits project ID if it's changing.\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\n\n // Set the default splits domain if it's changing.\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\n\n // Set the default splits group if it's changing.\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\n\n emit SetDefaultSplits(_projectId, _domain, _group, msg.sender);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender\n );\n\n // Pay any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to pay it.\n if (_projectId != 0) {\n _pay(\n _projectId,\n _token,\n _leftoverAmount,\n _decimals,\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n // If no project was specified, send the funds directly to the beneficiary or the msg.sender.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _beneficiary != address(0) ? payable(_beneficiary) : payable(msg.sender),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).transfer(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _leftoverAmount\n );\n }\n }\n\n emit Pay(\n _projectId,\n _beneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event. \n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender\n );\n\n // Distribute any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to add to its balance.\n if (_projectId != 0)\n // Add to the project's balance.\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\n\n // Otherwise, send a payment to the beneficiary.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(msg.sender),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).transfer(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _leftoverAmount\n );\n }\n }\n\n emit AddToBalance(\n _projectId,\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splitsProjectId The ID of the project to which the splits belong.\n @param _splitsDomain The splits domain to which the group belongs.\n @param _splitsGroup The splits group to pay.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payToSplits(\n uint256 _splitsProjectId,\n uint256 _splitsDomain,\n uint256 _splitsGroup,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Get a reference to the splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup);\n\n // Set the leftover amount to the initial balance.\n leftoverAmount = _amount;\n\n // Settle between all splits.\n for (uint256 i = 0; i < _splits.length; i++) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[i];\n\n // The amount to send towards the split.\n uint256 _splitAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n if (_splitAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n _token,\n _splitAmount,\n _decimals,\n defaultProjectId,\n 0,\n _split\n );\n\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\n if (_token != JBTokens.ETH)\n IERC20(_token).approve(address(_split.allocator), _splitAmount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _splitAmount : 0;\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n if (_split.preferAddToBalance)\n _addToBalanceOf(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n 0,\n _split.preferClaimed,\n defaultMemo,\n defaultMetadata\n );\n } else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : payable(_defaultBeneficiary),\n _splitAmount\n );\n // Or, transfer the ERC20.\n else {\n IERC20(_token).transfer(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n _splitAmount\n );\n }\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _splitAmount;\n }\n\n emit DistributeToSplit(\n _splitsProjectId,\n _splitsDomain,\n _splitsGroup,\n _split,\n _splitAmount,\n _defaultBeneficiary,\n msg.sender\n );\n }\n }\n}\n" + "contracts/JBGasTokenERC20SplitsPayer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBSplitsPayer.sol';\nimport './interfaces/IJBSplitsStore.sol';\nimport './libraries/JBConstants.sol';\nimport './JBGasTokenERC20ProjectPayer.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\n\n @dev\n Adheres to -\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBGasTokenERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBGasTokenERC20SplitsPayer is IJBSplitsPayer, JBGasTokenERC20ProjectPayer, ReentrancyGuard {\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The ID of project for which the default splits are stored. \n */\n uint256 public override defaultSplitsProjectId;\n\n /**\n @notice\n The domain within which the default splits are stored. \n */\n uint256 public override defaultSplitsDomain;\n\n /**\n @notice\n The group within which the default splits are stored. \n */\n uint256 public override defaultSplitsGroup;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBGasTokenERC20ProjectPayer, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n )\n JBGasTokenERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _preferAddToBalance,\n _splitsStore.directory(),\n _owner\n )\n {\n defaultSplitsProjectId = _defaultSplitsProjectId;\n defaultSplitsDomain = _defaultSplitsDomain;\n defaultSplitsGroup = _defaultSplitsGroup;\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default split group using the stored default properties.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override nonReentrant {\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender\n );\n\n // If there is no leftover amount, nothing left to pay.\n if (_leftoverAmount == 0) return;\n\n // If there's a default project ID, try to pay it.\n if (defaultProjectId != 0)\n if (defaultPreferAddToBalance)\n // Pay the project by adding to its balance if prefered.\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n _leftoverAmount,\n 18, // decimals.\n defaultMemo,\n defaultMetadata\n );\n // Otherwise, issue a payment to the project.\n else\n _pay(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n _leftoverAmount,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n 0, // min returned tokens.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n // If no project was specified, send the funds directly to the beneficiary or the msg.sender.\n else\n Address.sendValue(\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(msg.sender),\n _leftoverAmount\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the location of the splits that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n */\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) external virtual override onlyOwner {\n // Set the default splits project ID if it's changing.\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\n\n // Set the default splits domain if it's changing.\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\n\n // Set the default splits group if it's changing.\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\n\n emit SetDefaultSplits(_projectId, _domain, _group, msg.sender);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender\n );\n\n // Pay any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to pay it.\n if (_projectId != 0) {\n _pay(\n _projectId,\n _token,\n _leftoverAmount,\n _decimals,\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n // If no project was specified, send the funds directly to the beneficiary or the msg.sender.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _beneficiary != address(0) ? payable(_beneficiary) : payable(msg.sender),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).transfer(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _leftoverAmount\n );\n }\n }\n\n emit Pay(\n _projectId,\n _beneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event. \n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender\n );\n\n // Distribute any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to add to its balance.\n if (_projectId != 0)\n // Add to the project's balance.\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\n\n // Otherwise, send a payment to the beneficiary.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(msg.sender),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).transfer(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _leftoverAmount\n );\n }\n }\n\n emit AddToBalance(\n _projectId,\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splitsProjectId The ID of the project to which the splits belong.\n @param _splitsDomain The splits domain to which the group belongs.\n @param _splitsGroup The splits group to pay.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payToSplits(\n uint256 _splitsProjectId,\n uint256 _splitsDomain,\n uint256 _splitsGroup,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Get a reference to the splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup);\n\n // Set the leftover amount to the initial balance.\n leftoverAmount = _amount;\n\n // Settle between all splits.\n for (uint256 i = 0; i < _splits.length; i++) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[i];\n\n // The amount to send towards the split.\n uint256 _splitAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n if (_splitAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n _token,\n _splitAmount,\n _decimals,\n defaultProjectId,\n 0,\n _split\n );\n\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN)\n IERC20(_token).approve(address(_split.allocator), _splitAmount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _splitAmount : 0;\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n if (_split.preferAddToBalance)\n _addToBalanceOf(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n 0,\n _split.preferClaimed,\n defaultMemo,\n defaultMetadata\n );\n } else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : payable(_defaultBeneficiary),\n _splitAmount\n );\n // Or, transfer the ERC20.\n else {\n IERC20(_token).transfer(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n _splitAmount\n );\n }\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _splitAmount;\n }\n\n emit DistributeToSplit(\n _splitsProjectId,\n _splitsDomain,\n _splitsGroup,\n _split,\n _splitAmount,\n _defaultBeneficiary,\n msg.sender\n );\n }\n }\n}\n" }, "contracts/interfaces/IJBSplitsPayer.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './../structs/JBSplit.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBSplitsPayer is IERC165 {\n event SetDefaultSplits(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n address caller\n );\n event Pay(\n uint256 indexed projectId,\n address beneficiary,\n address token,\n uint256 amount,\n uint256 decimals,\n uint256 leftoverAmount,\n uint256 minReturnedTokens,\n bool preferClaimedTokens,\n string memo,\n bytes metadata,\n address caller\n );\n\n event AddToBalance(\n uint256 indexed projectId,\n address beneficiary,\n address token,\n uint256 amount,\n uint256 decimals,\n uint256 leftoverAmount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DistributeToSplit(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n JBSplit split,\n uint256 amount,\n address defaultBeneficiary,\n address caller\n );\n\n function defaultSplitsProjectId() external view returns (uint256);\n\n function defaultSplitsDomain() external view returns (uint256);\n\n function defaultSplitsGroup() external view returns (uint256);\n\n function splitsStore() external view returns (IJBSplitsStore);\n\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) external;\n}\n" }, - "contracts/JBETHERC20ProjectPayer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport './interfaces/IJBProjectPayer.sol';\nimport './libraries/JBTokens.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ERC165: Introspection on interface adherance. \n*/\ncontract JBETHERC20ProjectPayer is IJBProjectPayer, Ownable, ERC165 {\n //*********************************************************************//\n // -------------------------- custom errors -------------------------- //\n //*********************************************************************//\n error INCORRECT_DECIMAL_AMOUNT();\n error NO_MSG_VALUE_ALLOWED();\n error TERMINAL_NOT_FOUND();\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice \n A contract storing directories of terminals and controllers for each project.\n */\n IJBDirectory public immutable override directory;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The ID of the project that should be used to forward this contract's received payments.\n */\n uint256 public override defaultProjectId;\n\n /** \n @notice \n The beneficiary that should be used in the payment made when this contract receives payments.\n */\n address payable public override defaultBeneficiary;\n\n /** \n @notice \n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\n */\n bool public override defaultPreferClaimedTokens;\n\n /** \n @notice \n The memo that should be used in the payment made when this contract receives payments.\n */\n string public override defaultMemo;\n\n /** \n @notice \n The metadata that should be used in the payment made when this contract receives payments.\n */\n bytes public override defaultMetadata;\n\n /**\n @notice \n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n bool public override defaultPreferAddToBalance;\n\n //*********************************************************************//\n // ------------------------- public views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) {\n defaultProjectId = _defaultProjectId;\n defaultBeneficiary = _defaultBeneficiary;\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\n defaultMemo = _defaultMemo;\n defaultMetadata = _defaultMetadata;\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n directory = _directory;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default project ID using the stored default properties.\n\n @dev\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override {\n if (defaultPreferAddToBalance)\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.ETH,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n defaultProjectId,\n JBTokens.ETH,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultBeneficiary == address(0) ? msg.sender : defaultBeneficiary,\n 0, // Can't determine expectation of returned tokens ahead of time.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\n\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _beneficiary The address that'll receive the project's tokens. \n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _memo The memo that'll be used. \n @param _metadata The metadata that'll be sent. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external virtual override onlyOwner {\n // Set the default project ID if it has changed.\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\n\n // Set the default beneficiary if it has changed.\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\n\n // Set the default claimed token preference if it has changed.\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\n defaultPreferClaimedTokens = _preferClaimedTokens;\n\n // Set the default memo if it has changed.\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\n defaultMemo = _memo;\n\n // Set the default metadata if it has changed.\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\n defaultMetadata = _metadata;\n\n // Set the add to balance preference if it has changed.\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n\n emit SetDefaultValues(\n _projectId,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata,\n _defaultPreferAddToBalance,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _pay(\n _projectId,\n _token,\n _amount,\n _decimals,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. \n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source and delegate, if provided.\n */\n function _pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.ETH) IERC20(_token).approve(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\n\n // Send funds to the terminal.\n // If the token is ETH, send it in msg.value.\n _terminal.pay{value: _payableValue}(\n _projectId,\n _amount, // ignored if the token is JBTokens.ETH.\n _token,\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.ETH) IERC20(_token).approve(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\n\n // Add to balance so tokens don't get issued.\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\n }\n}\n" + "contracts/JBGasTokenERC20ProjectPayer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport './interfaces/IJBProjectPayer.sol';\nimport './libraries/JBTokens.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ERC165: Introspection on interface adherance. \n*/\ncontract JBGasTokenERC20ProjectPayer is IJBProjectPayer, Ownable, ERC165 {\n //*********************************************************************//\n // -------------------------- custom errors -------------------------- //\n //*********************************************************************//\n error INCORRECT_DECIMAL_AMOUNT();\n error NO_MSG_VALUE_ALLOWED();\n error TERMINAL_NOT_FOUND();\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice \n A contract storing directories of terminals and controllers for each project.\n */\n IJBDirectory public immutable override directory;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The ID of the project that should be used to forward this contract's received payments.\n */\n uint256 public override defaultProjectId;\n\n /** \n @notice \n The beneficiary that should be used in the payment made when this contract receives payments.\n */\n address payable public override defaultBeneficiary;\n\n /** \n @notice \n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\n */\n bool public override defaultPreferClaimedTokens;\n\n /** \n @notice \n The memo that should be used in the payment made when this contract receives payments.\n */\n string public override defaultMemo;\n\n /** \n @notice \n The metadata that should be used in the payment made when this contract receives payments.\n */\n bytes public override defaultMetadata;\n\n /**\n @notice \n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n bool public override defaultPreferAddToBalance;\n\n //*********************************************************************//\n // ------------------------- public views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) {\n defaultProjectId = _defaultProjectId;\n defaultBeneficiary = _defaultBeneficiary;\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\n defaultMemo = _defaultMemo;\n defaultMetadata = _defaultMetadata;\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n directory = _directory;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default project ID using the stored default properties.\n\n @dev\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override {\n if (defaultPreferAddToBalance)\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultBeneficiary == address(0) ? msg.sender : defaultBeneficiary,\n 0, // Can't determine expectation of returned tokens ahead of time.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\n\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _beneficiary The address that'll receive the project's tokens. \n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _memo The memo that'll be used. \n @param _metadata The metadata that'll be sent. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external virtual override onlyOwner {\n // Set the default project ID if it has changed.\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\n\n // Set the default beneficiary if it has changed.\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\n\n // Set the default claimed token preference if it has changed.\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\n defaultPreferClaimedTokens = _preferClaimedTokens;\n\n // Set the default memo if it has changed.\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\n defaultMemo = _memo;\n\n // Set the default metadata if it has changed.\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\n defaultMetadata = _metadata;\n\n // Set the add to balance preference if it has changed.\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n\n emit SetDefaultValues(\n _projectId,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata,\n _defaultPreferAddToBalance,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _pay(\n _projectId,\n _token,\n _amount,\n _decimals,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. \n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source and delegate, if provided.\n */\n function _pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).approve(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send funds to the terminal.\n // If the token is ETH, send it in msg.value.\n _terminal.pay{value: _payableValue}(\n _projectId,\n _amount, // ignored if the token is JBTokens.GAS_TOKEN.\n _token,\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).approve(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Add to balance so tokens don't get issued.\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\n }\n}\n" }, "contracts/interfaces/IJBProjectPayer.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './IJBDirectory.sol';\n\ninterface IJBProjectPayer is IERC165 {\n event SetDefaultValues(\n uint256 indexed projectId,\n address indexed beneficiary,\n bool preferClaimedTokens,\n string memo,\n bytes metadata,\n bool preferAddToBalance,\n address caller\n );\n\n function directory() external view returns (IJBDirectory);\n\n function defaultProjectId() external view returns (uint256);\n\n function defaultBeneficiary() external view returns (address payable);\n\n function defaultPreferClaimedTokens() external view returns (bool);\n\n function defaultMemo() external view returns (string memory);\n\n function defaultMetadata() external view returns (bytes memory);\n\n function defaultPreferAddToBalance() external view returns (bool);\n\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external;\n\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) external payable;\n\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) external payable;\n\n receive() external payable;\n}\n" }, - "contracts/JBETHERC20SplitsPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './interfaces/IJBETHERC20SplitsPayerDeployer.sol';\nimport './JBETHERC20SplitsPayer.sol';\n\n/** \n @notice \n Deploys splits payer contracts.\n\n @dev\n Adheres to -\n IJBETHERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBETHERC20SplitsPayerDeployer is IJBETHERC20SplitsPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBSplitsPayer splitsPayer) {\n // Deploy the splits payer.\n splitsPayer = new JBETHERC20SplitsPayer(\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeploySplitsPayer(\n splitsPayer,\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner,\n msg.sender\n );\n }\n}\n" + "contracts/JBGasTokenERC20SplitsPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './interfaces/IJBGasTokenERC20SplitsPayerDeployer.sol';\nimport './JBGasTokenERC20SplitsPayer.sol';\n\n/** \n @notice \n Deploys splits payer contracts.\n\n @dev\n Adheres to -\n IJBGasTokenERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBGasTokenERC20SplitsPayerDeployer is IJBGasTokenERC20SplitsPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBSplitsPayer splitsPayer) {\n // Deploy the splits payer.\n splitsPayer = new JBGasTokenERC20SplitsPayer(\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeploySplitsPayer(\n splitsPayer,\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner,\n msg.sender\n );\n }\n}\n" }, - "contracts/interfaces/IJBETHERC20SplitsPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './IJBSplitsPayer.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBETHERC20SplitsPayerDeployer {\n event DeploySplitsPayer(\n IJBSplitsPayer indexed splitsPayer,\n uint256 defaultSplitsProjectId,\n uint256 defaultSplitsDomain,\n uint256 defaultSplitsGroup,\n IJBSplitsStore splitsStore,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n address owner,\n address caller\n );\n\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string calldata _defaultMemo,\n bytes calldata _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n}\n" + "contracts/interfaces/IJBGasTokenERC20SplitsPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './IJBSplitsPayer.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBGasTokenERC20SplitsPayerDeployer {\n event DeploySplitsPayer(\n IJBSplitsPayer indexed splitsPayer,\n uint256 defaultSplitsProjectId,\n uint256 defaultSplitsDomain,\n uint256 defaultSplitsGroup,\n IJBSplitsStore splitsStore,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n address owner,\n address caller\n );\n\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string calldata _defaultMemo,\n bytes calldata _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n}\n" }, - "contracts/JBETHERC20ProjectPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './interfaces/IJBETHERC20ProjectPayerDeployer.sol';\nimport './JBETHERC20ProjectPayer.sol';\n\n/** \n @notice \n Deploys project payer contracts.\n\n @dev\n Adheres to -\n IJBETHERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBETHERC20ProjectPayerDeployer is IJBETHERC20ProjectPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new project payer contract.\n\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the project payer contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the project payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the project payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the project payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the project payer.\n\n @return projectPayer The project payer contract.\n */\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external override returns (IJBProjectPayer projectPayer) {\n // Deploy the project payer.\n projectPayer = new JBETHERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner\n );\n\n emit DeployProjectPayer(\n projectPayer,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner,\n msg.sender\n );\n }\n}\n" + "contracts/JBGasTokenERC20ProjectPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './interfaces/IJBGasTokenERC20ProjectPayerDeployer.sol';\nimport './JBGasTokenERC20ProjectPayer.sol';\n\n/** \n @notice \n Deploys project payer contracts.\n\n @dev\n Adheres to -\n IJBGasTokenERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBGasTokenERC20ProjectPayerDeployer is IJBGasTokenERC20ProjectPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new project payer contract.\n\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the project payer contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the project payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the project payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the project payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the project payer.\n\n @return projectPayer The project payer contract.\n */\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external override returns (IJBProjectPayer projectPayer) {\n // Deploy the project payer.\n projectPayer = new JBGasTokenERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner\n );\n\n emit DeployProjectPayer(\n projectPayer,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner,\n msg.sender\n );\n }\n}\n" }, - "contracts/interfaces/IJBETHERC20ProjectPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './IJBDirectory.sol';\nimport './IJBProjectPayer.sol';\n\ninterface IJBETHERC20ProjectPayerDeployer {\n event DeployProjectPayer(\n IJBProjectPayer indexed projectPayer,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n IJBDirectory directory,\n address owner,\n address caller\n );\n\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external returns (IJBProjectPayer projectPayer);\n}\n" + "contracts/interfaces/IJBGasTokenERC20ProjectPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './IJBDirectory.sol';\nimport './IJBProjectPayer.sol';\n\ninterface IJBGasTokenERC20ProjectPayerDeployer {\n event DeployProjectPayer(\n IJBProjectPayer indexed projectPayer,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n IJBDirectory directory,\n address owner,\n address caller\n );\n\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external returns (IJBProjectPayer projectPayer);\n}\n" }, "contracts/system_tests/TestPayBurnRedeemFlow.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport '@paulrberg/contracts/math/PRBMathUD60x18.sol';\n\nimport './helpers/TestBaseWorkflow.sol';\n\n/**\n * This system test file verifies the following flow:\n * launch project → issue token → pay project (claimed tokens) → burn some of the claimed tokens → redeem rest of tokens\n */\ncontract TestPayBurnRedeemFlow is TestBaseWorkflow {\n JBController private _controller;\n JBETHPaymentTerminal private _terminal;\n JBTokenStore private _tokenStore;\n\n JBProjectMetadata private _projectMetadata;\n JBFundingCycleData private _data;\n JBFundingCycleMetadata private _metadata;\n JBGroupedSplits[] private _groupedSplits; // Default empty\n JBFundAccessConstraints[] private _fundAccessConstraints; // Default empty\n IJBPaymentTerminal[] private _terminals; // Default empty\n\n uint256 private _projectId;\n address private _projectOwner;\n uint256 private _weight = 1000 * 10**18;\n uint256 private _targetInWei = 10 * 10**18;\n\n function setUp() public override {\n super.setUp();\n\n _controller = jbController();\n _terminal = jbETHPaymentTerminal();\n _tokenStore = jbTokenStore();\n\n _projectMetadata = JBProjectMetadata({content: 'myIPFSHash', domain: 1});\n\n _data = JBFundingCycleData({\n duration: 14,\n weight: _weight,\n discountRate: 450000000,\n ballot: IJBFundingCycleBallot(address(0))\n });\n\n _metadata = JBFundingCycleMetadata({\n global: JBGlobalFundingCycleMetadata({allowSetTerminals: false, allowSetController: false}),\n reservedRate: 0,\n redemptionRate: 10000, //100%\n ballotRedemptionRate: 0,\n pausePay: false,\n pauseDistributions: false,\n pauseRedeem: false,\n pauseBurn: false,\n allowMinting: false,\n allowChangeToken: false,\n allowTerminalMigration: false,\n allowControllerMigration: false,\n holdFees: false,\n useTotalOverflowForRedemptions: false,\n useDataSourceForPay: false,\n useDataSourceForRedeem: false,\n dataSource: address(0)\n });\n\n _terminals.push(_terminal);\n\n _fundAccessConstraints.push(\n JBFundAccessConstraints({\n terminal: _terminal,\n token: jbLibraries().ETHToken(),\n distributionLimit: _targetInWei, // 10 ETH target\n overflowAllowance: 5 ether,\n distributionLimitCurrency: 1, // Currency = ETH\n overflowAllowanceCurrency: 1\n })\n );\n\n _projectOwner = multisig();\n\n _projectId = _controller.launchProjectFor(\n _projectOwner,\n _projectMetadata,\n _data,\n _metadata,\n block.timestamp,\n _groupedSplits,\n _fundAccessConstraints,\n _terminals,\n ''\n );\n }\n\n function testFuzzPayBurnRedeemFlow(\n bool payPreferClaimed, //false\n bool burnPreferClaimed, //false\n uint96 payAmountInWei, // 1\n uint256 burnTokenAmount, // 0\n uint256 redeemTokenAmount // 0\n ) external {\n // issue an ERC-20 token for project\n evm.prank(_projectOwner);\n _controller.issueTokenFor(_projectId, 'TestName', 'TestSymbol');\n\n address _userWallet = address(1234);\n\n // pay terminal\n _terminal.pay{value: payAmountInWei}(\n _projectId,\n payAmountInWei,\n address(0),\n _userWallet,\n /* _minReturnedTokens */\n 0,\n /* _preferClaimedTokens */\n payPreferClaimed,\n /* _memo */\n 'Take my money!',\n /* _delegateMetadata */\n new bytes(0)\n );\n\n // verify: beneficiary should have a balance of JBTokens\n uint256 _userTokenBalance = PRBMathUD60x18.mul(payAmountInWei, _weight);\n assertEq(_tokenStore.balanceOf(_userWallet, _projectId), _userTokenBalance);\n\n // verify: ETH balance in terminal should be up to date\n uint256 _terminalBalanceInWei = payAmountInWei;\n assertEq(jbPaymentTerminalStore().balanceOf(_terminal, _projectId), _terminalBalanceInWei);\n\n // burn tokens from beneficiary addr\n if (burnTokenAmount == 0) evm.expectRevert(abi.encodeWithSignature('NO_BURNABLE_TOKENS()'));\n else if (burnTokenAmount > _userTokenBalance)\n evm.expectRevert(abi.encodeWithSignature('INSUFFICIENT_FUNDS()'));\n else if (burnTokenAmount > uint256(type(int256).max))\n evm.expectRevert(abi.encodeWithSignature('Panic(uint256)', 0x11));\n else _userTokenBalance = _userTokenBalance - burnTokenAmount;\n\n evm.prank(_userWallet);\n _controller.burnTokensOf(\n _userWallet,\n _projectId,\n /* _tokenCount */\n burnTokenAmount,\n /* _memo */\n 'I hate tokens!',\n /* _preferClaimedTokens */\n burnPreferClaimed\n );\n\n // verify: beneficiary should have a new balance of JBTokens\n assertEq(_tokenStore.balanceOf(_userWallet, _projectId), _userTokenBalance);\n\n // redeem tokens\n if (redeemTokenAmount > _userTokenBalance)\n evm.expectRevert(abi.encodeWithSignature('INSUFFICIENT_TOKENS()'));\n else _userTokenBalance = _userTokenBalance - redeemTokenAmount;\n\n evm.prank(_userWallet);\n uint256 _reclaimAmtInWei = _terminal.redeemTokensOf(\n /* _holder */\n _userWallet,\n /* _projectId */\n _projectId,\n /* _tokenCount */\n redeemTokenAmount,\n /* token (unused) */\n address(0),\n /* _minReturnedWei */\n 0,\n /* _beneficiary */\n payable(_userWallet),\n /* _memo */\n 'Refund me now!',\n /* _delegateMetadata */\n new bytes(0)\n );\n\n // verify: beneficiary should have a new balance of JBTokens\n assertEq(_tokenStore.balanceOf(_userWallet, _projectId), _userTokenBalance);\n\n // verify: ETH balance in terminal should be up to date\n assertEq(\n jbPaymentTerminalStore().balanceOf(_terminal, _projectId),\n _terminalBalanceInWei - _reclaimAmtInWei\n );\n }\n}\n" diff --git a/deployments/mainnet/solcInputs/ba079c3b841cf131865f97c4e38baa17.json b/deployments/mainnet/solcInputs/ba079c3b841cf131865f97c4e38baa17.json index c8e01b6db..3c3aefd77 100644 --- a/deployments/mainnet/solcInputs/ba079c3b841cf131865f97c4e38baa17.json +++ b/deployments/mainnet/solcInputs/ba079c3b841cf131865f97c4e38baa17.json @@ -119,13 +119,13 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport './abstract/JBOperatable.sol';\nimport './interfaces/IJBDirectory.sol';\nimport './libraries/JBGlobalFundingCycleMetadataResolver.sol';\nimport './libraries/JBOperations.sol';\n\n/**\n @notice\n Keeps a reference of which terminal contracts each project is currently accepting funds through, and which controller contract is managing each project's tokens and funding cycles.\n\n @dev\n Adheres to -\n IJBDirectory: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\ncontract JBDirectory is IJBDirectory, JBOperatable, Ownable {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBGlobalFundingCycleMetadataResolver for uint8;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error DUPLICATE_TERMINALS();\n error INVALID_PROJECT_ID_IN_DIRECTORY();\n error SET_CONTROLLER_NOT_ALLOWED();\n error SET_TERMINALS_NOT_ALLOWED();\n error TOKEN_NOT_ACCEPTED();\n\n //*********************************************************************//\n // --------------------- private stored properties ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n For each project ID, the terminals that are currently managing its funds.\n\n _projectId The ID of the project to get terminals of.\n */\n mapping(uint256 => IJBPaymentTerminal[]) private _terminalsOf;\n\n /**\n @notice\n The project's primary terminal for a token.\n\n _projectId The ID of the project to get the primary terminal of.\n _token The token to get the project's primary terminal of.\n */\n mapping(uint256 => mapping(address => IJBPaymentTerminal)) private _primaryTerminalOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n For each project ID, the controller that manages how terminals interact with tokens and funding cycles.\n\n _projectId The ID of the project to get the controller of.\n */\n mapping(uint256 => address) public override controllerOf;\n\n /**\n @notice\n Addresses that can set a project's first controller on their behalf. These addresses/contracts have been vetted and verified by this contract's owner.\n\n _address The address that is either allowed or not.\n */\n mapping(address => bool) public override isAllowedToSetFirstController;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n For each project ID, the terminals that are currently managing its funds.\n\n @param _projectId The ID of the project to get terminals of.\n\n @return An array of terminal addresses.\n */\n function terminalsOf(uint256 _projectId)\n external\n view\n override\n returns (IJBPaymentTerminal[] memory)\n {\n return _terminalsOf[_projectId];\n }\n\n /**\n @notice\n The primary terminal that is managing funds for a project for a specified token.\n\n @dev\n The zero address is returned if a terminal isn't found for the specified token.\n\n @param _projectId The ID of the project to get a terminal for.\n @param _token The token the terminal accepts.\n\n @return The primary terminal for the project for the specified token.\n */\n function primaryTerminalOf(uint256 _projectId, address _token)\n external\n view\n override\n returns (IJBPaymentTerminal)\n {\n // If a primary terminal for the token was specifically set and its one of the project's terminals, return it.\n if (\n _primaryTerminalOf[_projectId][_token] != IJBPaymentTerminal(address(0)) &&\n isTerminalOf(_projectId, _primaryTerminalOf[_projectId][_token])\n ) return _primaryTerminalOf[_projectId][_token];\n\n // Return the first terminal which accepts the specified token.\n for (uint256 _i; _i < _terminalsOf[_projectId].length; _i++) {\n IJBPaymentTerminal _terminal = _terminalsOf[_projectId][_i];\n if (_terminal.acceptsToken(_token, _projectId)) return _terminal;\n }\n\n // Not found.\n return IJBPaymentTerminal(address(0));\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Whether or not a specified terminal is a terminal of the specified project.\n\n @param _projectId The ID of the project to check within.\n @param _terminal The address of the terminal to check for.\n\n @return A flag indicating whether or not the specified terminal is a terminal of the specified project.\n */\n function isTerminalOf(uint256 _projectId, IJBPaymentTerminal _terminal)\n public\n view\n override\n returns (bool)\n {\n for (uint256 _i; _i < _terminalsOf[_projectId].length; _i++)\n if (_terminalsOf[_projectId][_i] == _terminal) return true;\n return false;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _owner The address that will own the contract.\n */\n constructor(\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBFundingCycleStore _fundingCycleStore,\n address _owner\n ) JBOperatable(_operatorStore) {\n projects = _projects;\n fundingCycleStore = _fundingCycleStore;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Update the controller that manages how terminals interact with the ecosystem.\n\n @dev\n A controller can be set if:\n - the message sender is the project owner or an operator having the correct authorization.\n - the message sender is the project's current controller.\n - or, an allowedlisted address is setting a controller for a project that doesn't already have a controller.\n\n @param _projectId The ID of the project to set a new controller for.\n @param _controller The new controller to set.\n */\n function setControllerOf(uint256 _projectId, address _controller)\n external\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.SET_CONTROLLER,\n (msg.sender == address(controllerOf[_projectId]) ||\n (isAllowedToSetFirstController[msg.sender] && controllerOf[_projectId] == address(0)))\n )\n {\n // The project must exist.\n if (projects.count() < _projectId) revert INVALID_PROJECT_ID_IN_DIRECTORY();\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Setting controller is allowed if called from the current controller, or if the project doesn't have a current controller, or if the project's funding cycle allows setting the controller. Revert otherwise.\n if (\n msg.sender != address(controllerOf[_projectId]) &&\n controllerOf[_projectId] != address(0) &&\n !uint8(_fundingCycle.metadata >> 8).setControllerAllowed()\n ) revert SET_CONTROLLER_NOT_ALLOWED();\n\n // Set the new controller.\n controllerOf[_projectId] = _controller;\n\n emit SetController(_projectId, _controller, msg.sender);\n }\n\n /** \n @notice \n Set a project's terminals.\n\n @dev\n Only a project owner, an operator, or its controller can set its terminals.\n\n @param _projectId The ID of the project having terminals set.\n @param _terminals The terminal to set.\n */\n function setTerminalsOf(uint256 _projectId, IJBPaymentTerminal[] calldata _terminals)\n external\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.SET_TERMINALS,\n msg.sender == address(controllerOf[_projectId])\n )\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Setting terminals must be allowed if not called from the current controller.\n if (\n msg.sender != address(controllerOf[_projectId]) &&\n !uint8(_fundingCycle.metadata >> 8).setTerminalsAllowed()\n ) revert SET_TERMINALS_NOT_ALLOWED();\n\n // Delete the stored terminals for the project.\n _terminalsOf[_projectId] = _terminals;\n\n // Make sure duplicates were not added.\n if (_terminals.length > 1)\n for (uint256 _i; _i < _terminals.length; _i++)\n for (uint256 _j = _i + 1; _j < _terminals.length; _j++)\n if (_terminals[_i] == _terminals[_j]) revert DUPLICATE_TERMINALS();\n\n emit SetTerminals(_projectId, _terminals, msg.sender);\n }\n\n /**\n @notice\n Project's can set which terminal should be their primary for a particular token.\n This is useful in case a project has several terminals connected for a particular token.\n\n @dev\n The terminal will be set as the primary terminal where ecosystem contracts should route tokens.\n\n @dev\n If setting a newly added terminal and the funding cycle doesn't allow new terminals, the caller must be the current controller.\n\n @param _projectId The ID of the project for which a primary token is being set.\n @param _token The token to set the primary terminal of.\n @param _terminal The terminal to make primary.\n */\n function setPrimaryTerminalOf(\n uint256 _projectId,\n address _token,\n IJBPaymentTerminal _terminal\n )\n external\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.SET_PRIMARY_TERMINAL)\n {\n // Can't set the primary terminal for a token if it doesn't accept the token.\n if (!_terminal.acceptsToken(_token, _projectId)) revert TOKEN_NOT_ACCEPTED();\n\n // Add the terminal to the project if it hasn't been already.\n _addTerminalIfNeeded(_projectId, _terminal);\n\n // Store the terminal as the primary for the particular token.\n _primaryTerminalOf[_projectId][_token] = _terminal;\n\n emit SetPrimaryTerminal(_projectId, _token, _terminal, msg.sender);\n }\n\n /** \n @notice\t\n Set a contract to the list of trusted addresses that can set a first controller for any project.\t\n\n @dev\n The owner can add addresses which are allowed to change projects' first controllers. \n These addresses are known and vetted controllers as well as contracts designed to launch new projects. \n A project can set its own controller without it being on the allow list.\n\n @dev\n If you would like an address/contract allowlisted, please reach out to the contract owner.\n\n @param _address The address to allow or revoke allowance from.\n @param _flag Whether allowance is being added or revoked.\n */\n function setIsAllowedToSetFirstController(address _address, bool _flag)\n external\n override\n onlyOwner\n {\n // Set the flag in the allowlist.\n isAllowedToSetFirstController[_address] = _flag;\n\n emit SetIsAllowedToSetFirstController(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Add a terminal to a project's list of terminals if it hasn't been already.\n\n @param _projectId The ID of the project having a terminal added.\n @param _terminal The terminal to add.\n */\n function _addTerminalIfNeeded(uint256 _projectId, IJBPaymentTerminal _terminal) private {\n // Check that the terminal has not already been added.\n if (isTerminalOf(_projectId, _terminal)) return;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Setting terminals must be allowed if not called from the current controller.\n if (\n msg.sender != address(controllerOf[_projectId]) &&\n !uint8(_fundingCycle.metadata >> 8).setTerminalsAllowed()\n ) revert SET_TERMINALS_NOT_ALLOWED();\n\n // Add the new terminal.\n _terminalsOf[_projectId].push(_terminal);\n\n emit AddTerminal(_projectId, _terminal, msg.sender);\n }\n}\n" }, "contracts/JBETHPaymentTerminal.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n JBTokens.ETH,\n 18, // 18 decimals.\n JBCurrencies.ETH,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal pure override {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n JBTokens.GAS_TOKEN,\n 18, // 18 decimals.\n JBCurrencies.GAS_CURRENCY,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal pure override {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n}\n" }, "contracts/JBERC20PaymentTerminal.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\n\n/** \n @notice \n Manages the inflows and outflows of an ERC-20 token.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\ncontract JBERC20PaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n IERC20Metadata _token,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n address(_token),\n _token.decimals(),\n _currency,\n _baseWeightCurrency,\n _payoutSplitsGroup,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from == address(this)\n ? IERC20(token).transfer(_to, _amount)\n : IERC20(token).transferFrom(_from, _to, _amount);\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal override {\n IERC20(token).approve(_to, _amount);\n }\n}\n" }, "contracts/JBSingleTokenPaymentTerminalStore.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBSingleTokenPaymentTerminalStore is IJBSingleTokenPaymentTerminalStore, ReentrancyGuard {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n Mint's 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegate A delegate contract to use for subsequent calls.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n IJBPayDelegate delegate,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay()) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegate) = IJBFundingCycleDataSource(fundingCycle.dataSource()).payParams(\n _data\n );\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegate, memo);\n\n // Add the amount to the token balance of the project.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount.value;\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegate, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegate A delegate contract to use for subsequent calls.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n IJBRedemptionDelegate delegate,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\n _projectId,\n fundingCycle.reservedRate()\n );\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow > 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem()) {\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n fundingCycle.redemptionRate(),\n fundingCycle.ballotRedemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegate) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .redeemParams(_data);\n } else {\n memo = _memo;\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (reclaimAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (reclaimAmount > 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n reclaimAmount;\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n return _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i = 0; _i < _terminals.length; _i++)\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.ETH\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.ETH, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBSingleTokenPaymentTerminalStore is IJBSingleTokenPaymentTerminalStore, ReentrancyGuard {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n Mint's 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegate A delegate contract to use for subsequent calls.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n IJBPayDelegate delegate,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay()) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegate) = IJBFundingCycleDataSource(fundingCycle.dataSource()).payParams(\n _data\n );\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegate, memo);\n\n // Add the amount to the token balance of the project.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount.value;\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegate, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegate A delegate contract to use for subsequent calls.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n IJBRedemptionDelegate delegate,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\n _projectId,\n fundingCycle.reservedRate()\n );\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow > 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem()) {\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n fundingCycle.redemptionRate(),\n fundingCycle.ballotRedemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegate) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .redeemParams(_data);\n } else {\n memo = _memo;\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (reclaimAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (reclaimAmount > 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n reclaimAmount;\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n return _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i = 0; _i < _terminals.length; _i++)\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.GAS_CURRENCY\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.GAS_CURRENCY, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" }, "contracts/JBFundingCycleStore.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './abstract/JBControllerUtility.sol';\nimport './libraries/JBConstants.sol';\n\n/** \n @notice \n Manages funding cycle configurations and scheduling.\n\n @dev\n Adheres to -\n IJBTokenStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBControllerUtility: Includes convenience functionality for checking if the message sender is the current controller of the project whose data is being manipulated.\n*/\ncontract JBFundingCycleStore is IJBFundingCycleStore, JBControllerUtility {\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_DISCOUNT_RATE();\n error INVALID_DURATION();\n error INVALID_WEIGHT();\n error INVALID_BALLOT();\n error NO_SAME_BLOCK_RECONFIGURATION();\n\n //*********************************************************************//\n // --------------------- private stored properties ------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Stores the user defined properties of each funding cycle, packed into one storage slot.\n\n _projectId The ID of the project to get properties of.\n _configuration The funding cycle configuration to get properties of.\n */\n mapping(uint256 => mapping(uint256 => uint256)) private _packedUserPropertiesOf;\n\n /** \n @notice\n Stores the properties added by the mechanism to manage and schedule each funding cycle, packed into one storage slot.\n \n _projectId The ID of the project to get instrinsic properties of.\n _configuration The funding cycle configuration to get properties of.\n */\n mapping(uint256 => mapping(uint256 => uint256)) private _packedIntrinsicPropertiesOf;\n\n /** \n @notice\n Stores the metadata for each funding cycle configuration, packed into one storage slot.\n\n _projectId The ID of the project to get metadata of.\n _configuration The funding cycle configuration to get metadata of.\n */\n mapping(uint256 => mapping(uint256 => uint256)) private _metadataOf;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The latest funding cycle configuration for each project.\n\n _projectId The ID of the project to get the latest funding cycle configuration of.\n */\n mapping(uint256 => uint256) public override latestConfigurationOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice \n Get the funding cycle with the given configuration for the specified project.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n @param _configuration The configuration of the funding cycle to get.\n\n @return fundingCycle The funding cycle.\n */\n function get(uint256 _projectId, uint256 _configuration)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle)\n {\n return _getStructFor(_projectId, _configuration);\n }\n\n /**\n @notice \n The latest funding cycle to be configured for the specified project, and its current ballot state.\n\n @param _projectId The ID of the project to get the latest configured funding cycle of.\n\n @return fundingCycle The project's queued funding cycle.\n @return ballotState The state of the ballot for the reconfiguration.\n */\n function latestConfiguredOf(uint256 _projectId)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle, JBBallotState ballotState)\n {\n // Get a reference to the latest funding cycle configuration.\n uint256 _fundingCycleConfiguration = latestConfigurationOf[_projectId];\n\n // Resolve the funding cycle for the latest configuration.\n fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n // Resolve the ballot state.\n ballotState = _ballotStateOf(\n _projectId,\n fundingCycle.configuration,\n fundingCycle.start,\n fundingCycle.basedOn\n );\n }\n\n /**\n @notice \n The funding cycle that's next up for the specified project.\n\n @dev\n If a queued funding cycle of the project is not found, returns an empty funding cycle with all properties set to 0.\n\n @param _projectId The ID of the project to get the queued funding cycle of.\n\n @return fundingCycle The project's queued funding cycle.\n */\n function queuedOf(uint256 _projectId)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle)\n {\n // If the project does not have a funding cycle, return an empty struct.\n if (latestConfigurationOf[_projectId] == 0) return _getStructFor(0, 0);\n\n // Get a reference to the configuration of the standby funding cycle.\n uint256 _standbyFundingCycleConfiguration = _standbyOf(_projectId);\n\n // If it exists, return its funding cycle if it is approved.\n if (_standbyFundingCycleConfiguration > 0) {\n fundingCycle = _getStructFor(_projectId, _standbyFundingCycleConfiguration);\n\n if (_isApproved(_projectId, fundingCycle)) return fundingCycle;\n\n // Resolve the funding cycle for the latest configured funding cycle.\n fundingCycle = _getStructFor(_projectId, fundingCycle.basedOn);\n } else {\n // Resolve the funding cycle for the latest configured funding cycle.\n fundingCycle = _getStructFor(_projectId, latestConfigurationOf[_projectId]);\n\n // If the latest funding cycle starts in the future, it must start in the distant future\n // since its not in standby. In this case base the queued cycles on the base cycle.\n if (fundingCycle.start > block.timestamp)\n fundingCycle = _getStructFor(_projectId, fundingCycle.basedOn);\n }\n\n // There's no queued if the current has a duration of 0.\n if (fundingCycle.duration == 0) return _getStructFor(0, 0);\n\n // Check to see if this funding cycle's ballot is approved.\n // If so, return a funding cycle based on it.\n if (_isApproved(_projectId, fundingCycle)) return _mockFundingCycleBasedOn(fundingCycle, false);\n\n // Get the funding cycle of its base funding cycle, which carries the last approved configuration.\n fundingCycle = _getStructFor(_projectId, fundingCycle.basedOn);\n\n // There's no queued if the base, which must still be the current, has a duration of 0.\n if (fundingCycle.duration == 0) return _getStructFor(0, 0);\n\n // Return a mock of the next up funding cycle.\n return _mockFundingCycleBasedOn(fundingCycle, false);\n }\n\n /**\n @notice \n The funding cycle that is currently active for the specified project.\n\n @dev\n If a current funding cycle of the project is not found, returns an empty funding cycle with all properties set to 0.\n\n @param _projectId The ID of the project to get the current funding cycle of.\n\n @return fundingCycle The project's current funding cycle.\n */\n function currentOf(uint256 _projectId)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle)\n {\n // If the project does not have a funding cycle, return an empty struct.\n if (latestConfigurationOf[_projectId] == 0) return _getStructFor(0, 0);\n\n // Get a reference to the configuration of the eligible funding cycle.\n uint256 _fundingCycleConfiguration = _eligibleOf(_projectId);\n\n // Keep a reference to the eligible funding cycle.\n JBFundingCycle memory _fundingCycle;\n\n // If an eligible funding cycle exists...\n if (_fundingCycleConfiguration > 0) {\n // Resolve the funding cycle for the eligible configuration.\n _fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n // Check to see if this funding cycle's ballot is approved.\n // If so, return it.\n if (_isApproved(_projectId, _fundingCycle)) return _fundingCycle;\n\n // If it hasn't been approved, set the funding cycle configuration to be the configuration of the funding cycle that it's based on,\n // which carries the last approved configuration.\n _fundingCycleConfiguration = _fundingCycle.basedOn;\n } else {\n // No upcoming funding cycle found that is eligible to become active,\n // so use the last configuration.\n _fundingCycleConfiguration = latestConfigurationOf[_projectId];\n\n // Get the funding cycle for the latest ID.\n _fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n // If it's not approved or if it hasn't yet started, get a reference to the funding cycle that the latest is based on, which has the latest approved configuration.\n if (!_isApproved(_projectId, _fundingCycle) || block.timestamp < _fundingCycle.start)\n _fundingCycleConfiguration = _fundingCycle.basedOn;\n }\n\n // If there is not funding cycle to base the current one on, there can't be a current one.\n if (_fundingCycleConfiguration == 0) return _getStructFor(0, 0);\n\n // The funding cycle to base a current one on.\n _fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n // If the base has no duration, it's still the current one.\n if (_fundingCycle.duration == 0) return _fundingCycle;\n\n // Return a mock of the current funding cycle.\n return _mockFundingCycleBasedOn(_fundingCycle, true);\n }\n\n /** \n @notice \n The current ballot state of the project.\n\n @param _projectId The ID of the project to check the ballot state of.\n\n @return The project's current ballot's state.\n */\n function currentBallotStateOf(uint256 _projectId) external view override returns (JBBallotState) {\n // Get a reference to the latest funding cycle configuration.\n uint256 _fundingCycleConfiguration = latestConfigurationOf[_projectId];\n\n // Resolve the funding cycle for the latest configuration.\n JBFundingCycle memory _fundingCycle = _getStructFor(_projectId, _fundingCycleConfiguration);\n\n return\n _ballotStateOf(\n _projectId,\n _fundingCycle.configuration,\n _fundingCycle.start,\n _fundingCycle.basedOn\n );\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _directory A contract storing directories of terminals and controllers for each project.\n */\n // solhint-disable-next-line no-empty-blocks\n constructor(IJBDirectory _directory) JBControllerUtility(_directory) {}\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice \n Configures the next eligible funding cycle for the specified project.\n\n @dev\n Only a project's current controller can configure its funding cycles.\n\n @param _projectId The ID of the project being configured.\n @param _data The funding cycle configuration data.\n @param _metadata Arbitrary extra data to associate with this funding cycle configuration that's not used within.\n @param _mustStartAtOrAfter The time before which the initialized funding cycle cannot start.\n\n @return The funding cycle that the configuration will take effect during.\n */\n function configureFor(\n uint256 _projectId,\n JBFundingCycleData calldata _data,\n uint256 _metadata,\n uint256 _mustStartAtOrAfter\n ) external override onlyController(_projectId) returns (JBFundingCycle memory) {\n // Duration must fit in a uint64.\n if (_data.duration > type(uint64).max) revert INVALID_DURATION();\n\n // Discount rate must be less than or equal to 100%.\n if (_data.discountRate > JBConstants.MAX_DISCOUNT_RATE) revert INVALID_DISCOUNT_RATE();\n\n // Weight must fit into a uint88.\n if (_data.weight > type(uint88).max) revert INVALID_WEIGHT();\n\n // Ballot should be a valid contract, supporting the correct interface\n if(_data.ballot != IJBFundingCycleBallot(address(0))) {\n\n address _ballot = address(_data.ballot);\n uint32 _size;\n assembly {\n _size := extcodesize(_ballot) // No contract at the address ?\n }\n if (_size == 0) revert INVALID_BALLOT();\n\n try _data.ballot.supportsInterface(type(IJBFundingCycleBallot).interfaceId) returns (bool _supports) {\n if(!_supports) revert INVALID_BALLOT(); // Contract exists at the address but with the wrong interface\n } catch {\n revert INVALID_BALLOT(); // No ERC165 support\n }\n }\n\n // The configuration timestamp is now.\n uint256 _configuration = block.timestamp;\n\n // Set up a reconfiguration by configuring intrinsic properties.\n _configureIntrinsicPropertiesFor(\n _projectId,\n _configuration,\n _data.weight,\n // Must start on or after the current timestamp.\n _mustStartAtOrAfter > block.timestamp ? _mustStartAtOrAfter : block.timestamp\n );\n\n // Efficiently stores a funding cycles provided user defined properties.\n // If all user config properties are zero, no need to store anything as the default value will have the same outcome.\n if (\n _data.ballot != IJBFundingCycleBallot(address(0)) ||\n _data.duration > 0 ||\n _data.discountRate > 0\n ) {\n // ballot in bits 0-159 bytes.\n uint256 packed = uint160(address(_data.ballot));\n\n // duration in bits 160-223 bytes.\n packed |= _data.duration << 160;\n\n // discountRate in bits 224-255 bytes.\n packed |= _data.discountRate << 224;\n\n // Set in storage.\n _packedUserPropertiesOf[_projectId][_configuration] = packed;\n }\n\n // Set the metadata if needed.\n if (_metadata > 0) _metadataOf[_projectId][_configuration] = _metadata;\n\n emit Configure(_configuration, _projectId, _data, _metadata, _mustStartAtOrAfter, msg.sender);\n\n // Return the funding cycle for the new configuration.\n return _getStructFor(_projectId, _configuration);\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice \n Updates the configurable funding cycle for this project if it exists, otherwise creates one.\n\n @param _projectId The ID of the project to find a configurable funding cycle for.\n @param _configuration The time at which the funding cycle was configured.\n @param _weight The weight to store in the configured funding cycle.\n @param _mustStartAtOrAfter The time before which the initialized funding cycle can't start.\n */\n function _configureIntrinsicPropertiesFor(\n uint256 _projectId,\n uint256 _configuration,\n uint256 _weight,\n uint256 _mustStartAtOrAfter\n ) private {\n // If there's not yet a funding cycle for the project, initialize one.\n if (latestConfigurationOf[_projectId] == 0)\n // Use an empty funding cycle as the base.\n return\n _initFor(_projectId, _getStructFor(0, 0), _configuration, _mustStartAtOrAfter, _weight);\n\n // Get the active funding cycle's configuration.\n uint256 _currentConfiguration = _eligibleOf(_projectId);\n\n // If an eligible funding cycle does not exist, get a reference to the latest funding cycle configuration for the project.\n if (_currentConfiguration == 0)\n // Get the latest funding cycle's configuration.\n _currentConfiguration = latestConfigurationOf[_projectId];\n\n // Get a reference to the funding cycle.\n JBFundingCycle memory _baseFundingCycle = _getStructFor(_projectId, _currentConfiguration);\n\n if (!_isApproved(_projectId, _baseFundingCycle) || block.timestamp < _baseFundingCycle.start)\n // If it hasn't been approved or hasn't yet started, set the ID to be the funding cycle it's based on,\n // which carries the latest approved configuration.\n _baseFundingCycle = _getStructFor(_projectId, _baseFundingCycle.basedOn);\n\n // The configuration can't be the same as the base configuration.\n if (_baseFundingCycle.configuration == _configuration) revert NO_SAME_BLOCK_RECONFIGURATION();\n\n // The time after the ballot of the provided funding cycle has expired.\n // If the provided funding cycle has no ballot, return the current timestamp.\n uint256 _timestampAfterBallot = _baseFundingCycle.ballot == IJBFundingCycleBallot(address(0))\n ? 0\n : _configuration + _baseFundingCycle.ballot.duration();\n\n _initFor(\n _projectId,\n _baseFundingCycle,\n _configuration,\n // Can only start after the ballot.\n _timestampAfterBallot > _mustStartAtOrAfter ? _timestampAfterBallot : _mustStartAtOrAfter,\n _weight\n );\n }\n\n /**\n @notice \n Initializes a funding cycle with the specified properties.\n\n @param _projectId The ID of the project to which the funding cycle being initialized belongs.\n @param _baseFundingCycle The funding cycle to base the initialized one on.\n @param _configuration The configuration of the funding cycle being initialized.\n @param _mustStartAtOrAfter The time before which the initialized funding cycle cannot start.\n @param _weight The weight to give the newly initialized funding cycle.\n */\n function _initFor(\n uint256 _projectId,\n JBFundingCycle memory _baseFundingCycle,\n uint256 _configuration,\n uint256 _mustStartAtOrAfter,\n uint256 _weight\n ) private {\n // If there is no base, initialize a first cycle.\n if (_baseFundingCycle.number == 0) {\n // The first number is 1.\n uint256 _number = 1;\n\n // Set fresh intrinsic properties.\n _packAndStoreIntrinsicPropertiesOf(\n _configuration,\n _projectId,\n _number,\n _weight,\n _baseFundingCycle.configuration,\n _mustStartAtOrAfter\n );\n } else {\n // Derive the correct next start time from the base.\n uint256 _start = _deriveStartFrom(_baseFundingCycle, _mustStartAtOrAfter);\n\n // A weight of 1 is treated as a weight of 0.\n // This is to allow a weight of 0 (default) to represent inheriting the discounted weight of the previous funding cycle.\n _weight = _weight > 0\n ? (_weight == 1 ? 0 : _weight)\n : _deriveWeightFrom(_baseFundingCycle, _start);\n\n // Derive the correct number.\n uint256 _number = _deriveNumberFrom(_baseFundingCycle, _start);\n\n // Update the intrinsic properties.\n _packAndStoreIntrinsicPropertiesOf(\n _configuration,\n _projectId,\n _number,\n _weight,\n _baseFundingCycle.configuration,\n _start\n );\n }\n\n // Set the project's latest funding cycle configuration.\n latestConfigurationOf[_projectId] = _configuration;\n\n emit Init(_configuration, _projectId, _baseFundingCycle.configuration);\n }\n\n /**\n @notice \n Efficiently stores a funding cycle's provided intrinsic properties.\n\n @param _configuration The configuration of the funding cycle to pack and store.\n @param _projectId The ID of the project to which the funding cycle belongs.\n @param _number The number of the funding cycle.\n @param _weight The weight of the funding cycle.\n @param _basedOn The configuration of the base funding cycle.\n @param _start The start time of this funding cycle.\n */\n function _packAndStoreIntrinsicPropertiesOf(\n uint256 _configuration,\n uint256 _projectId,\n uint256 _number,\n uint256 _weight,\n uint256 _basedOn,\n uint256 _start\n ) private {\n // weight in bits 0-87.\n uint256 packed = _weight;\n\n // basedOn in bits 88-143.\n packed |= _basedOn << 88;\n\n // start in bits 144-199.\n packed |= _start << 144;\n\n // number in bits 200-255.\n packed |= _number << 200;\n\n // Store the packed value.\n _packedIntrinsicPropertiesOf[_projectId][_configuration] = packed;\n }\n\n /**\n @notice \n The project's stored funding cycle that hasn't yet started and should be used next, if one exists.\n\n @dev\n A value of 0 is returned if no funding cycle was found.\n\n @dev\n Assumes the project has a latest configuration.\n \n @param _projectId The ID of a project to look through for a standby cycle.\n\n @return configuration The configuration of the standby funding cycle if one exists, or 0 if one doesn't exist.\n */\n function _standbyOf(uint256 _projectId) private view returns (uint256 configuration) {\n // Get a reference to the project's latest funding cycle.\n configuration = latestConfigurationOf[_projectId];\n\n // Get the necessary properties for the latest funding cycle.\n JBFundingCycle memory _fundingCycle = _getStructFor(_projectId, configuration);\n\n // There is no upcoming funding cycle if the latest funding cycle has already started.\n if (block.timestamp >= _fundingCycle.start) return 0;\n\n // If this is the first funding cycle, it is queued.\n if (_fundingCycle.number == 1) return configuration;\n\n // Get the necessary properties for the base funding cycle.\n JBFundingCycle memory _baseFundingCycle = _getStructFor(_projectId, _fundingCycle.basedOn);\n\n // If the latest configuration doesn't start until after another base cycle, return 0.\n if (\n _baseFundingCycle.duration > 0 &&\n block.timestamp < _fundingCycle.start - _baseFundingCycle.duration\n ) return 0;\n }\n\n /**\n @notice \n The project's stored funding cycle that has started and hasn't yet expired.\n \n @dev\n A value of 0 is returned if no funding cycle was found.\n\n @dev\n Assumes the project has a latest configuration.\n\n @param _projectId The ID of the project to look through.\n\n @return configuration The configuration of an eligible funding cycle if one exists, or 0 if one doesn't exist.\n */\n function _eligibleOf(uint256 _projectId) private view returns (uint256 configuration) {\n // Get a reference to the project's latest funding cycle.\n configuration = latestConfigurationOf[_projectId];\n\n // Get the latest funding cycle.\n JBFundingCycle memory _fundingCycle = _getStructFor(_projectId, configuration);\n\n // If the latest is expired, return an empty funding cycle.\n // A duration of 0 cannot be expired.\n if (\n _fundingCycle.duration > 0 && block.timestamp >= _fundingCycle.start + _fundingCycle.duration\n ) return 0;\n\n // Return the funding cycle's configuration if it has started.\n if (block.timestamp >= _fundingCycle.start) return _fundingCycle.configuration;\n\n // Get a reference to the cycle's base configuration.\n JBFundingCycle memory _baseFundingCycle = _getStructFor(_projectId, _fundingCycle.basedOn);\n\n // If the base cycle isn't eligible, the project has no eligible cycle.\n // A duration of 0 is always eligible.\n if (\n _baseFundingCycle.duration > 0 &&\n block.timestamp >= _baseFundingCycle.start + _baseFundingCycle.duration\n ) return 0;\n\n // Return the configuration that the latest funding cycle is based on.\n configuration = _fundingCycle.basedOn;\n }\n\n /** \n @notice \n A view of the funding cycle that would be created based on the provided one if the project doesn't make a reconfiguration.\n\n @dev\n Returns an empty funding cycle if there can't be a mock funding cycle based on the provided one.\n\n @dev\n Assumes a funding cycle with a duration of 0 will never be asked to be the base of a mock.\n\n @param _baseFundingCycle The funding cycle that the resulting funding cycle should follow.\n @param _allowMidCycle A flag indicating if the mocked funding cycle is allowed to already be mid cycle.\n\n @return A mock of what the next funding cycle will be.\n */\n function _mockFundingCycleBasedOn(JBFundingCycle memory _baseFundingCycle, bool _allowMidCycle)\n private\n view\n returns (JBFundingCycle memory)\n {\n // Get the distance of the current time to the start of the next possible funding cycle.\n // If the returned mock cycle must not yet have started, the start time of the mock must be in the future.\n uint256 _mustStartAtOrAfter = !_allowMidCycle\n ? block.timestamp + 1\n : block.timestamp - _baseFundingCycle.duration + 1;\n\n // Derive what the start time should be.\n uint256 _start = _deriveStartFrom(_baseFundingCycle, _mustStartAtOrAfter);\n\n // Derive what the number should be.\n uint256 _number = _deriveNumberFrom(_baseFundingCycle, _start);\n\n return\n JBFundingCycle(\n _number,\n _baseFundingCycle.configuration,\n _baseFundingCycle.basedOn,\n _start,\n _baseFundingCycle.duration,\n _deriveWeightFrom(_baseFundingCycle, _start),\n _baseFundingCycle.discountRate,\n _baseFundingCycle.ballot,\n _baseFundingCycle.metadata\n );\n }\n\n /** \n @notice \n The date that is the nearest multiple of the specified funding cycle's duration from its end.\n\n @param _baseFundingCycle The funding cycle to base the calculation on.\n @param _mustStartAtOrAfter A date that the derived start must be on or come after.\n\n @return start The next start time.\n */\n function _deriveStartFrom(JBFundingCycle memory _baseFundingCycle, uint256 _mustStartAtOrAfter)\n private\n pure\n returns (uint256 start)\n {\n // A subsequent cycle to one with a duration of 0 should start as soon as possible.\n if (_baseFundingCycle.duration == 0) return _mustStartAtOrAfter;\n\n // The time when the funding cycle immediately after the specified funding cycle starts.\n uint256 _nextImmediateStart = _baseFundingCycle.start + _baseFundingCycle.duration;\n\n // If the next immediate start is now or in the future, return it.\n if (_nextImmediateStart >= _mustStartAtOrAfter) return _nextImmediateStart;\n\n // The amount of seconds since the `_mustStartAtOrAfter` time which results in a start time that might satisfy the specified constraints.\n uint256 _timeFromImmediateStartMultiple = (_mustStartAtOrAfter - _nextImmediateStart) %\n _baseFundingCycle.duration;\n\n // A reference to the first possible start timestamp.\n start = _mustStartAtOrAfter - _timeFromImmediateStartMultiple;\n\n // Add increments of duration as necessary to satisfy the threshold.\n while (_mustStartAtOrAfter > start) start = start + _baseFundingCycle.duration;\n }\n\n /** \n @notice \n The accumulated weight change since the specified funding cycle.\n\n @param _baseFundingCycle The funding cycle to base the calculation on.\n @param _start The start time of the funding cycle to derive a number for.\n\n @return weight The derived weight, as a fixed point number with 18 decimals.\n */\n function _deriveWeightFrom(JBFundingCycle memory _baseFundingCycle, uint256 _start)\n private\n pure\n returns (uint256 weight)\n {\n // A subsequent cycle to one with a duration of 0 should have the next possible weight.\n if (_baseFundingCycle.duration == 0)\n return\n PRBMath.mulDiv(\n _baseFundingCycle.weight,\n JBConstants.MAX_DISCOUNT_RATE - _baseFundingCycle.discountRate,\n JBConstants.MAX_DISCOUNT_RATE\n );\n\n // The weight should be based off the base funding cycle's weight.\n weight = _baseFundingCycle.weight;\n\n // If the discount is 0, the weight doesn't change.\n if (_baseFundingCycle.discountRate == 0) return weight;\n\n // The difference between the start of the base funding cycle and the proposed start.\n uint256 _startDistance = _start - _baseFundingCycle.start;\n\n // Apply the base funding cycle's discount rate for each cycle that has passed.\n uint256 _discountMultiple = _startDistance / _baseFundingCycle.duration;\n\n for (uint256 i = 0; i < _discountMultiple; i++) {\n // The number of times to apply the discount rate.\n // Base the new weight on the specified funding cycle's weight.\n weight = PRBMath.mulDiv(\n weight,\n JBConstants.MAX_DISCOUNT_RATE - _baseFundingCycle.discountRate,\n JBConstants.MAX_DISCOUNT_RATE\n );\n // The calculation doesn't need to continue if the weight is 0.\n if (weight == 0) break;\n }\n }\n\n /** \n @notice \n The number of the next funding cycle given the specified funding cycle.\n\n @param _baseFundingCycle The funding cycle to base the calculation on.\n @param _start The start time of the funding cycle to derive a number for.\n\n @return The funding cycle number.\n */\n function _deriveNumberFrom(JBFundingCycle memory _baseFundingCycle, uint256 _start)\n private\n pure\n returns (uint256)\n {\n // A subsequent cycle to one with a duration of 0 should be the next number.\n if (_baseFundingCycle.duration == 0) return _baseFundingCycle.number + 1;\n\n // The difference between the start of the base funding cycle and the proposed start.\n uint256 _startDistance = _start - _baseFundingCycle.start;\n\n // Find the number of base cycles that fit in the start distance.\n return _baseFundingCycle.number + (_startDistance / _baseFundingCycle.duration);\n }\n\n /** \n @notice \n Checks to see if the provided funding cycle is approved according to the correct ballot.\n\n @param _projectId The ID of the project to which the funding cycle belongs. \n @param _fundingCycle The funding cycle to get an approval flag for.\n\n @return The approval flag.\n */\n function _isApproved(uint256 _projectId, JBFundingCycle memory _fundingCycle)\n private\n view\n returns (bool)\n {\n return\n _ballotStateOf(\n _projectId,\n _fundingCycle.configuration,\n _fundingCycle.start,\n _fundingCycle.basedOn\n ) == JBBallotState.Approved;\n }\n\n /**\n @notice \n A project's latest funding cycle configuration approval status.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n @param _configuration The funding cycle configuration to get the ballot state of.\n @param _start The start time of the funding cycle configuration to get the ballot state of.\n @param _ballotFundingCycleConfiguration The configuration of the funding cycle which is configured with the ballot that should be used.\n\n @return The ballot state of the project.\n */\n function _ballotStateOf(\n uint256 _projectId,\n uint256 _configuration,\n uint256 _start,\n uint256 _ballotFundingCycleConfiguration\n ) private view returns (JBBallotState) {\n // If there is no ballot funding cycle, implicitly approve.\n if (_ballotFundingCycleConfiguration == 0) return JBBallotState.Approved;\n\n // Get the ballot funding cycle.\n JBFundingCycle memory _ballotFundingCycle = _getStructFor(\n _projectId,\n _ballotFundingCycleConfiguration\n );\n\n // If there is no ballot, the ID is auto approved.\n // Otherwise if the ballot's duration hasn't passed, its still active.\n // Otherwise, return the ballot's state.\n if (_ballotFundingCycle.ballot == IJBFundingCycleBallot(address(0)))\n return JBBallotState.Approved;\n else if (_ballotFundingCycle.ballot.duration() >= block.timestamp - _configuration)\n return JBBallotState.Active;\n else return _ballotFundingCycle.ballot.stateOf(_projectId, _configuration, _start);\n }\n\n /**\n @notice \n Unpack a funding cycle's packed stored values into an easy-to-work-with funding cycle struct.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n @param _configuration The funding cycle configuration to get the full struct for.\n\n @return fundingCycle A funding cycle struct.\n */\n function _getStructFor(uint256 _projectId, uint256 _configuration)\n private\n view\n returns (JBFundingCycle memory fundingCycle)\n {\n // Return an empty funding cycle if the configuration specified is 0.\n if (_configuration == 0) return fundingCycle;\n\n fundingCycle.configuration = _configuration;\n\n uint256 _packedIntrinsicProperties = _packedIntrinsicPropertiesOf[_projectId][_configuration];\n\n // weight in bits 0-87 bits.\n fundingCycle.weight = uint256(uint88(_packedIntrinsicProperties));\n // basedOn in bits 88-143 bits.\n fundingCycle.basedOn = uint256(uint56(_packedIntrinsicProperties >> 88));\n // start in bits 144-199 bits.\n fundingCycle.start = uint256(uint56(_packedIntrinsicProperties >> 144));\n // number in bits 200-255 bits.\n fundingCycle.number = uint256(uint56(_packedIntrinsicProperties >> 200));\n\n uint256 _packedUserProperties = _packedUserPropertiesOf[_projectId][_configuration];\n\n // ballot in bits 0-159 bits.\n fundingCycle.ballot = IJBFundingCycleBallot(address(uint160(_packedUserProperties)));\n // duration in bits 160-223 bits.\n fundingCycle.duration = uint256(uint64(_packedUserProperties >> 160));\n // discountRate in bits 224-255 bits.\n fundingCycle.discountRate = uint256(uint32(_packedUserProperties >> 224));\n\n fundingCycle.metadata = _metadataOf[_projectId][_configuration];\n }\n}\n" @@ -170,7 +170,7 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './../interfaces/IJBSplitAllocator.sol';\n\n/** \n @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.\n @member preferAddToBalance A flag indicating if a distribution to a project should prefer triggering it's addToBalance function instead of its pay function.\n @member percent The percent of the whole group that this split occupies. This number is out of `JBConstants.SPLITS_TOTAL_PERCENT`.\n @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.\n @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.\n @member lockedUntil Specifies if the split should be unchangeable until the specified time, with the exception of extending the locked period.\n @member allocator If an allocator is specified, funds will be sent to the allocator contract along with all properties of this split.\n*/\nstruct JBSplit {\n bool preferClaimed;\n bool preferAddToBalance;\n uint256 percent;\n uint256 projectId;\n address payable beneficiary;\n uint256 lockedUntil;\n IJBSplitAllocator allocator;\n}\n" }, "contracts/system_tests/helpers/AccessJBLib.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '../../libraries/JBCurrencies.sol';\nimport '../../libraries/JBConstants.sol';\nimport '../../libraries/JBTokens.sol';\n\ncontract AccessJBLib {\n function ETH() external pure returns (uint256) {\n return JBCurrencies.ETH;\n }\n\n function USD() external pure returns (uint256) {\n return JBCurrencies.USD;\n }\n\n function ETHToken() external pure returns (address) {\n return JBTokens.ETH;\n }\n\n function MAX_FEE() external pure returns (uint256) {\n return JBConstants.MAX_FEE;\n }\n\n function MAX_RESERVED_RATE() external pure returns (uint256) {\n return JBConstants.MAX_RESERVED_RATE;\n }\n\n function MAX_REDEMPTION_RATE() external pure returns (uint256) {\n return JBConstants.MAX_REDEMPTION_RATE;\n }\n\n function MAX_DISCOUNT_RATE() external pure returns (uint256) {\n return JBConstants.MAX_DISCOUNT_RATE;\n }\n\n function SPLITS_TOTAL_PERCENT() external pure returns (uint256) {\n return JBConstants.SPLITS_TOTAL_PERCENT;\n }\n\n function MAX_FEE_DISCOUNT() external pure returns (uint256) {\n return JBConstants.MAX_FEE_DISCOUNT;\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '../../libraries/JBCurrencies.sol';\nimport '../../libraries/JBConstants.sol';\nimport '../../libraries/JBTokens.sol';\n\ncontract AccessJBLib {\n function ETH() external pure returns (uint256) {\n return JBCurrencies.GAS_CURRENCY;\n }\n\n function USD() external pure returns (uint256) {\n return JBCurrencies.USD;\n }\n\n function ETHToken() external pure returns (address) {\n return JBTokens.GAS_TOKEN;\n }\n\n function MAX_FEE() external pure returns (uint256) {\n return JBConstants.MAX_FEE;\n }\n\n function MAX_RESERVED_RATE() external pure returns (uint256) {\n return JBConstants.MAX_RESERVED_RATE;\n }\n\n function MAX_REDEMPTION_RATE() external pure returns (uint256) {\n return JBConstants.MAX_REDEMPTION_RATE;\n }\n\n function MAX_DISCOUNT_RATE() external pure returns (uint256) {\n return JBConstants.MAX_DISCOUNT_RATE;\n }\n\n function SPLITS_TOTAL_PERCENT() external pure returns (uint256) {\n return JBConstants.SPLITS_TOTAL_PERCENT;\n }\n\n function MAX_FEE_DISCOUNT() external pure returns (uint256) {\n return JBConstants.MAX_FEE_DISCOUNT;\n }\n}\n" }, "@paulrberg/contracts/math/PRBMath.sol": { "content": "// SPDX-License-Identifier: Unlicense\npragma solidity >=0.8.4;\n\nimport \"prb-math/contracts/PRBMath.sol\";\n" @@ -227,7 +227,7 @@ "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" }, "contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBSplitsGroups.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal is\n IJBPayoutRedemptionPaymentTerminal,\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n ReentrancyGuard\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The protocol project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _PROTOCOL_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.ETH)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.ETH, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.ETH) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i = 0; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @dev\n If the fee gauge reverts when called upon while a project is attempting to distribute its funds, a project's funds will be locked. This is a known risk.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual;\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual;\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegate` only used within scope.\n {\n IJBRedemptionDelegate _delegate;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegate, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If a delegate was returned by the data source, issue a callback to it.\n if (_delegate != IJBRedemptionDelegate(address(0))) {\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _beneficiary,\n _memo,\n _metadata\n );\n _delegate.didRedeem(_data);\n emit DelegateDidRedeem(_delegate, _data, msg.sender);\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convinience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n\n // Take the fee.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || _feeEligibleDistributionAmount == 0\n ? 0\n : _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n );\n\n // Get a reference to how much to distribute to the project owner, which is the leftover amount minus any fees.\n\n unchecked {\n netLeftoverDistributionAmount = _leftoverDistributionAmount == 0\n ? 0\n : _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n }\n\n // Transfer any remaining balance to the project owner.\n if (netLeftoverDistributionAmount > 0)\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convinience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i = 0; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount;\n\n if (_payoutAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (isFeelessAddress[address(_split.allocator)])\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _netPayoutAmount : 0;\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n _netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // Save gas if this contract is being used as the terminal.\n if (_terminal == this) {\n // This distribution does not incur a fee.\n _netPayoutAmount = _payoutAmount;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\n else\n _pay(\n _netPayoutAmount,\n address(this),\n _split.projectId,\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n } else {\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (isFeelessAddress[address(_terminal)])\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _netPayoutAmount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _terminal.addToBalanceOf{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n '',\n _projectMetadata\n );\n else\n _terminal.pay{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n }\n } else {\n unchecked {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(\n address(this),\n _split.beneficiary != address(0) ? _split.beneficiary : payable(msg.sender),\n _netPayoutAmount\n );\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _PROTOCOL_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n */\n function _processFee(uint256 _amount, address _beneficiary) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_PROTOCOL_PROJECT_ID, token);\n\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\n if (_terminal == this)\n _pay(_amount, address(this), _PROTOCOL_PROJECT_ID, _beneficiary, 0, false, '', bytes('')); // Use the local pay call.\n else {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _amount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _amount : 0;\n\n // Send the payment.\n _terminal.pay{value: _payableValue}(\n _PROTOCOL_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the external pay call of the correct terminal.\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegate` and `_tokenCount` only used within scope.\n {\n IJBPayDelegate _delegate;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegate, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If a delegate was returned by the data source, issue a callback to it.\n if (_delegate != IJBPayDelegate(address(0))) {\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n _delegate.didPay(_data);\n emit DelegateDidPay(_delegate, _data, msg.sender);\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i = 0; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n unchecked {\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256 feeDiscount) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (directory.primaryTerminalOf(_PROTOCOL_PROJECT_ID, token) == IJBPaymentTerminal(address(0)))\n return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge == IJBFeeGauge(address(0)))\n feeDiscount = 0;\n // If the guage reverts, set the discount to 0.\n else\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n feeDiscount = discount;\n } catch {\n feeDiscount = 0;\n }\n\n // If the fee discount is greater than the max, nullify the discount.\n if (feeDiscount > JBConstants.MAX_FEE_DISCOUNT) feeDiscount = 0;\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBSplitsGroups.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal is\n IJBPayoutRedemptionPaymentTerminal,\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n ReentrancyGuard\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The protocol project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _PROTOCOL_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.GAS_CURRENCY)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.GAS_CURRENCY, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.GAS_TOKEN) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i = 0; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @dev\n If the fee gauge reverts when called upon while a project is attempting to distribute its funds, a project's funds will be locked. This is a known risk.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual;\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual;\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegate` only used within scope.\n {\n IJBRedemptionDelegate _delegate;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegate, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If a delegate was returned by the data source, issue a callback to it.\n if (_delegate != IJBRedemptionDelegate(address(0))) {\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _beneficiary,\n _memo,\n _metadata\n );\n _delegate.didRedeem(_data);\n emit DelegateDidRedeem(_delegate, _data, msg.sender);\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convinience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n\n // Take the fee.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || _feeEligibleDistributionAmount == 0\n ? 0\n : _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n );\n\n // Get a reference to how much to distribute to the project owner, which is the leftover amount minus any fees.\n\n unchecked {\n netLeftoverDistributionAmount = _leftoverDistributionAmount == 0\n ? 0\n : _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n }\n\n // Transfer any remaining balance to the project owner.\n if (netLeftoverDistributionAmount > 0)\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convinience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i = 0; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount;\n\n if (_payoutAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (isFeelessAddress[address(_split.allocator)])\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0;\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n _netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // Save gas if this contract is being used as the terminal.\n if (_terminal == this) {\n // This distribution does not incur a fee.\n _netPayoutAmount = _payoutAmount;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\n else\n _pay(\n _netPayoutAmount,\n address(this),\n _split.projectId,\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n } else {\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (isFeelessAddress[address(_terminal)])\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _terminal.addToBalanceOf{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n '',\n _projectMetadata\n );\n else\n _terminal.pay{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n }\n } else {\n unchecked {\n _netPayoutAmount = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? _payoutAmount\n : _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(\n address(this),\n _split.beneficiary != address(0) ? _split.beneficiary : payable(msg.sender),\n _netPayoutAmount\n );\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _PROTOCOL_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n */\n function _processFee(uint256 _amount, address _beneficiary) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_PROTOCOL_PROJECT_ID, token);\n\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\n if (_terminal == this)\n _pay(_amount, address(this), _PROTOCOL_PROJECT_ID, _beneficiary, 0, false, '', bytes('')); // Use the local pay call.\n else {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _amount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send the payment.\n _terminal.pay{value: _payableValue}(\n _PROTOCOL_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the external pay call of the correct terminal.\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegate` and `_tokenCount` only used within scope.\n {\n IJBPayDelegate _delegate;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegate, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If a delegate was returned by the data source, issue a callback to it.\n if (_delegate != IJBPayDelegate(address(0))) {\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n _delegate.didPay(_data);\n emit DelegateDidPay(_delegate, _data, msg.sender);\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i = 0; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n unchecked {\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256 feeDiscount) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (directory.primaryTerminalOf(_PROTOCOL_PROJECT_ID, token) == IJBPaymentTerminal(address(0)))\n return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge == IJBFeeGauge(address(0)))\n feeDiscount = 0;\n // If the guage reverts, set the discount to 0.\n else\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n feeDiscount = discount;\n } catch {\n feeDiscount = 0;\n }\n\n // If the fee discount is greater than the max, nullify the discount.\n if (feeDiscount > JBConstants.MAX_FEE_DISCOUNT) feeDiscount = 0;\n }\n}\n" }, "@openzeppelin/contracts/security/ReentrancyGuard.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n constructor() {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n // On the first call to nonReentrant, _notEntered will be true\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n\n _;\n\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n}\n" @@ -311,31 +311,31 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './IJBFundingCycleBallot.sol';\n\ninterface IJBReconfigurationBufferBallot is IJBFundingCycleBallot {\n event Finalize(\n uint256 indexed projectId,\n uint256 indexed configuration,\n JBBallotState indexed ballotState,\n address caller\n );\n\n function finalState(uint256 _projectId, uint256 _configuration)\n external\n view\n returns (JBBallotState);\n\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\n\n function finalize(uint256 _projectId, uint256 _configured) external returns (JBBallotState);\n}\n" }, "contracts/system_tests/TestEIP165.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './helpers/TestBaseWorkflow.sol';\nimport '../JBReconfigurationBufferBallot.sol';\nimport '../JBETHERC20SplitsPayer.sol';\n\ncontract TestEIP165 is TestBaseWorkflow {\n bytes4 constant notSupportedInterface = 0xffffffff;\n\n uint256 constant projectId = 2;\n uint256 constant splitsProjectID = 3;\n address payable constant splitsBeneficiary = payable(address(420));\n uint256 constant splitsDomain = 1;\n uint256 constant splitsGroup = 1;\n bool constant splitsPreferClaimedTokens = false;\n string constant splitsMemo = '';\n bytes constant splitsMetadata = '';\n bool constant splitsPreferAddToBalance = true;\n address constant splitsOwner = address(420);\n\n function testJBController() public {\n JBController controller = jbController();\n\n // Should support these interfaces\n assertTrue(controller.supportsInterface(type(IERC165).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBController).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBMigratable).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!controller.supportsInterface(notSupportedInterface));\n }\n\n function testJBERC20PaymentTerminal() public {\n JBERC20PaymentTerminal terminal = new JBERC20PaymentTerminal(\n jbToken(),\n jbLibraries().USD(), // currency\n jbLibraries().ETH(), // base weight currency\n 1, // JBSplitsGroupe\n jbOperatorStore(),\n jbProjects(),\n jbDirectory(),\n jbSplitsStore(),\n jbPrices(),\n jbPaymentTerminalStore(),\n multisig()\n );\n\n // Should support these interfaces\n assertTrue(terminal.supportsInterface(type(IERC165).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBRedemptionTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBSingleTokenPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!terminal.supportsInterface(notSupportedInterface));\n }\n\n function testJBETHPaymentTerminal() public {\n JBETHPaymentTerminal terminal = jbETHPaymentTerminal();\n\n // Should support these interfaces\n assertTrue(terminal.supportsInterface(type(IERC165).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBRedemptionTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBSingleTokenPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!terminal.supportsInterface(notSupportedInterface));\n }\n\n function testJBProjects() public {\n JBProjects projects = jbProjects();\n\n // Should support these interfaces\n assertTrue(projects.supportsInterface(type(IERC165).interfaceId));\n assertTrue(projects.supportsInterface(type(IERC721).interfaceId));\n assertTrue(projects.supportsInterface(type(IERC721Metadata).interfaceId));\n assertTrue(projects.supportsInterface(type(IJBProjects).interfaceId));\n assertTrue(projects.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!projects.supportsInterface(notSupportedInterface));\n }\n\n function testJBReconfigurationBufferBallot() public {\n JBReconfigurationBufferBallot ballot = new JBReconfigurationBufferBallot(\n 3000,\n jbFundingCycleStore()\n );\n\n // Should support these interfaces\n assertTrue(ballot.supportsInterface(type(IERC165).interfaceId));\n assertTrue(ballot.supportsInterface(type(IJBReconfigurationBufferBallot).interfaceId));\n assertTrue(ballot.supportsInterface(type(IJBFundingCycleBallot).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!ballot.supportsInterface(notSupportedInterface));\n }\n\n function testJBETHERC20SplitsPayer() public {\n JBETHERC20SplitsPayer splitsPayer = new JBETHERC20SplitsPayer(\n splitsProjectID,\n splitsDomain,\n splitsGroup,\n jbSplitsStore(),\n projectId,\n splitsBeneficiary,\n splitsPreferClaimedTokens,\n splitsMemo,\n splitsMetadata,\n splitsPreferAddToBalance,\n splitsOwner\n );\n\n // Should support these interfaces\n assertTrue(splitsPayer.supportsInterface(type(IERC165).interfaceId));\n assertTrue(splitsPayer.supportsInterface(type(IJBSplitsPayer).interfaceId));\n assertTrue(splitsPayer.supportsInterface(type(IJBProjectPayer).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!splitsPayer.supportsInterface(notSupportedInterface));\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './helpers/TestBaseWorkflow.sol';\nimport '../JBReconfigurationBufferBallot.sol';\nimport '../JBGasTokenERC20SplitsPayer.sol';\n\ncontract TestEIP165 is TestBaseWorkflow {\n bytes4 constant notSupportedInterface = 0xffffffff;\n\n uint256 constant projectId = 2;\n uint256 constant splitsProjectID = 3;\n address payable constant splitsBeneficiary = payable(address(420));\n uint256 constant splitsDomain = 1;\n uint256 constant splitsGroup = 1;\n bool constant splitsPreferClaimedTokens = false;\n string constant splitsMemo = '';\n bytes constant splitsMetadata = '';\n bool constant splitsPreferAddToBalance = true;\n address constant splitsOwner = address(420);\n\n function testJBController() public {\n JBController controller = jbController();\n\n // Should support these interfaces\n assertTrue(controller.supportsInterface(type(IERC165).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBController).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBMigratable).interfaceId));\n assertTrue(controller.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!controller.supportsInterface(notSupportedInterface));\n }\n\n function testJBERC20PaymentTerminal() public {\n JBERC20PaymentTerminal terminal = new JBERC20PaymentTerminal(\n jbToken(),\n jbLibraries().USD(), // currency\n jbLibraries().ETH(), // base weight currency\n 1, // JBSplitsGroupe\n jbOperatorStore(),\n jbProjects(),\n jbDirectory(),\n jbSplitsStore(),\n jbPrices(),\n jbPaymentTerminalStore(),\n multisig()\n );\n\n // Should support these interfaces\n assertTrue(terminal.supportsInterface(type(IERC165).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBRedemptionTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBSingleTokenPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!terminal.supportsInterface(notSupportedInterface));\n }\n\n function testJBETHPaymentTerminal() public {\n JBETHPaymentTerminal terminal = jbETHPaymentTerminal();\n\n // Should support these interfaces\n assertTrue(terminal.supportsInterface(type(IERC165).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBRedemptionTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBSingleTokenPaymentTerminal).interfaceId));\n assertTrue(terminal.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!terminal.supportsInterface(notSupportedInterface));\n }\n\n function testJBProjects() public {\n JBProjects projects = jbProjects();\n\n // Should support these interfaces\n assertTrue(projects.supportsInterface(type(IERC165).interfaceId));\n assertTrue(projects.supportsInterface(type(IERC721).interfaceId));\n assertTrue(projects.supportsInterface(type(IERC721Metadata).interfaceId));\n assertTrue(projects.supportsInterface(type(IJBProjects).interfaceId));\n assertTrue(projects.supportsInterface(type(IJBOperatable).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!projects.supportsInterface(notSupportedInterface));\n }\n\n function testJBReconfigurationBufferBallot() public {\n JBReconfigurationBufferBallot ballot = new JBReconfigurationBufferBallot(\n 3000,\n jbFundingCycleStore()\n );\n\n // Should support these interfaces\n assertTrue(ballot.supportsInterface(type(IERC165).interfaceId));\n assertTrue(ballot.supportsInterface(type(IJBReconfigurationBufferBallot).interfaceId));\n assertTrue(ballot.supportsInterface(type(IJBFundingCycleBallot).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!ballot.supportsInterface(notSupportedInterface));\n }\n\n function testJBGasTokenERC20SplitsPayer() public {\n JBGasTokenERC20SplitsPayer splitsPayer = new JBGasTokenERC20SplitsPayer(\n splitsProjectID,\n splitsDomain,\n splitsGroup,\n jbSplitsStore(),\n projectId,\n splitsBeneficiary,\n splitsPreferClaimedTokens,\n splitsMemo,\n splitsMetadata,\n splitsPreferAddToBalance,\n splitsOwner\n );\n\n // Should support these interfaces\n assertTrue(splitsPayer.supportsInterface(type(IERC165).interfaceId));\n assertTrue(splitsPayer.supportsInterface(type(IJBSplitsPayer).interfaceId));\n assertTrue(splitsPayer.supportsInterface(type(IJBProjectPayer).interfaceId));\n\n // Make sure it doesn't always return true\n assertTrue(!splitsPayer.supportsInterface(notSupportedInterface));\n }\n}\n" }, - "contracts/JBETHERC20SplitsPayer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBSplitsPayer.sol';\nimport './interfaces/IJBSplitsStore.sol';\nimport './libraries/JBConstants.sol';\nimport './JBETHERC20ProjectPayer.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\n\n @dev\n Adheres to -\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBETHERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBETHERC20SplitsPayer is IJBSplitsPayer, JBETHERC20ProjectPayer, ReentrancyGuard {\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The ID of project for which the default splits are stored. \n */\n uint256 public override defaultSplitsProjectId;\n\n /**\n @notice\n The domain within which the default splits are stored. \n */\n uint256 public override defaultSplitsDomain;\n\n /**\n @notice\n The group within which the default splits are stored. \n */\n uint256 public override defaultSplitsGroup;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBETHERC20ProjectPayer, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n )\n JBETHERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _preferAddToBalance,\n _splitsStore.directory(),\n _owner\n )\n {\n defaultSplitsProjectId = _defaultSplitsProjectId;\n defaultSplitsDomain = _defaultSplitsDomain;\n defaultSplitsGroup = _defaultSplitsGroup;\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default split group using the stored default properties.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override nonReentrant {\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n JBTokens.ETH,\n address(this).balance,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender\n );\n\n // If there is no leftover amount, nothing left to pay.\n if (_leftoverAmount == 0) return;\n\n // If there's a default project ID, try to pay it.\n if (defaultProjectId != 0)\n if (defaultPreferAddToBalance)\n // Pay the project by adding to its balance if prefered.\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.ETH,\n _leftoverAmount,\n 18, // decimals.\n defaultMemo,\n defaultMetadata\n );\n // Otherwise, issue a payment to the project.\n else\n _pay(\n defaultProjectId,\n JBTokens.ETH,\n _leftoverAmount,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n 0, // min returned tokens.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n // If no project was specified, send the funds directly to the beneficiary or the msg.sender.\n else\n Address.sendValue(\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(msg.sender),\n _leftoverAmount\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the location of the splits that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n */\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) external virtual override onlyOwner {\n // Set the default splits project ID if it's changing.\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\n\n // Set the default splits domain if it's changing.\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\n\n // Set the default splits group if it's changing.\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\n\n emit SetDefaultSplits(_projectId, _domain, _group, msg.sender);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender\n );\n\n // Pay any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to pay it.\n if (_projectId != 0) {\n _pay(\n _projectId,\n _token,\n _leftoverAmount,\n _decimals,\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n // If no project was specified, send the funds directly to the beneficiary or the msg.sender.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _beneficiary != address(0) ? payable(_beneficiary) : payable(msg.sender),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).transfer(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _leftoverAmount\n );\n }\n }\n\n emit Pay(\n _projectId,\n _beneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event. \n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender\n );\n\n // Distribute any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to add to its balance.\n if (_projectId != 0)\n // Add to the project's balance.\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\n\n // Otherwise, send a payment to the beneficiary.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(msg.sender),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).transfer(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _leftoverAmount\n );\n }\n }\n\n emit AddToBalance(\n _projectId,\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splitsProjectId The ID of the project to which the splits belong.\n @param _splitsDomain The splits domain to which the group belongs.\n @param _splitsGroup The splits group to pay.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payToSplits(\n uint256 _splitsProjectId,\n uint256 _splitsDomain,\n uint256 _splitsGroup,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Pay the splits.\n leftoverAmount = _payTo(\n splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup),\n _token,\n _amount,\n _decimals,\n _defaultBeneficiary\n );\n emit DistributeToSplitGroup(_splitsProjectId, _splitsDomain, _splitsGroup, msg.sender);\n }\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splits The splits.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payTo(\n JBSplit[] memory _splits,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Set the leftover amount to the initial balance.\n leftoverAmount = _amount;\n\n // Settle between all splits.\n for (uint256 i = 0; i < _splits.length; i++) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[i];\n\n // The amount to send towards the split.\n uint256 _splitAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n if (_splitAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n _token,\n _splitAmount,\n _decimals,\n defaultProjectId,\n 0,\n _split\n );\n\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\n if (_token != JBTokens.ETH)\n IERC20(_token).approve(address(_split.allocator), _splitAmount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _splitAmount : 0;\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n if (_split.preferAddToBalance)\n _addToBalanceOf(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n 0,\n _split.preferClaimed,\n defaultMemo,\n defaultMetadata\n );\n } else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : payable(_defaultBeneficiary),\n _splitAmount\n );\n // Or, transfer the ERC20.\n else {\n IERC20(_token).transfer(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n _splitAmount\n );\n }\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _splitAmount;\n }\n\n emit DistributeToSplit(_split, _splitAmount, _defaultBeneficiary, msg.sender);\n }\n }\n}\n" + "contracts/JBGasTokenERC20SplitsPayer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBSplitsPayer.sol';\nimport './interfaces/IJBSplitsStore.sol';\nimport './libraries/JBConstants.sol';\nimport './JBGasTokenERC20ProjectPayer.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\n\n @dev\n Adheres to -\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBGasTokenERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBGasTokenERC20SplitsPayer is IJBSplitsPayer, JBGasTokenERC20ProjectPayer, ReentrancyGuard {\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The ID of project for which the default splits are stored. \n */\n uint256 public override defaultSplitsProjectId;\n\n /**\n @notice\n The domain within which the default splits are stored. \n */\n uint256 public override defaultSplitsDomain;\n\n /**\n @notice\n The group within which the default splits are stored. \n */\n uint256 public override defaultSplitsGroup;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBGasTokenERC20ProjectPayer, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n )\n JBGasTokenERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _preferAddToBalance,\n _splitsStore.directory(),\n _owner\n )\n {\n defaultSplitsProjectId = _defaultSplitsProjectId;\n defaultSplitsDomain = _defaultSplitsDomain;\n defaultSplitsGroup = _defaultSplitsGroup;\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default split group using the stored default properties.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override nonReentrant {\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender\n );\n\n // If there is no leftover amount, nothing left to pay.\n if (_leftoverAmount == 0) return;\n\n // If there's a default project ID, try to pay it.\n if (defaultProjectId != 0)\n if (defaultPreferAddToBalance)\n // Pay the project by adding to its balance if prefered.\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n _leftoverAmount,\n 18, // decimals.\n defaultMemo,\n defaultMetadata\n );\n // Otherwise, issue a payment to the project.\n else\n _pay(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n _leftoverAmount,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n 0, // min returned tokens.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n // If no project was specified, send the funds directly to the beneficiary or the msg.sender.\n else\n Address.sendValue(\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(msg.sender),\n _leftoverAmount\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the location of the splits that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n */\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) external virtual override onlyOwner {\n // Set the default splits project ID if it's changing.\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\n\n // Set the default splits domain if it's changing.\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\n\n // Set the default splits group if it's changing.\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\n\n emit SetDefaultSplits(_projectId, _domain, _group, msg.sender);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender\n );\n\n // Pay any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to pay it.\n if (_projectId != 0) {\n _pay(\n _projectId,\n _token,\n _leftoverAmount,\n _decimals,\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n // If no project was specified, send the funds directly to the beneficiary or the msg.sender.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _beneficiary != address(0) ? payable(_beneficiary) : payable(msg.sender),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).transfer(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _leftoverAmount\n );\n }\n }\n\n emit Pay(\n _projectId,\n _beneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event. \n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender\n );\n\n // Distribute any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to add to its balance.\n if (_projectId != 0)\n // Add to the project's balance.\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\n\n // Otherwise, send a payment to the beneficiary.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(msg.sender),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).transfer(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _leftoverAmount\n );\n }\n }\n\n emit AddToBalance(\n _projectId,\n defaultBeneficiary != address(0) ? defaultBeneficiary : msg.sender,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splitsProjectId The ID of the project to which the splits belong.\n @param _splitsDomain The splits domain to which the group belongs.\n @param _splitsGroup The splits group to pay.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payToSplits(\n uint256 _splitsProjectId,\n uint256 _splitsDomain,\n uint256 _splitsGroup,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Pay the splits.\n leftoverAmount = _payTo(\n splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup),\n _token,\n _amount,\n _decimals,\n _defaultBeneficiary\n );\n emit DistributeToSplitGroup(_splitsProjectId, _splitsDomain, _splitsGroup, msg.sender);\n }\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splits The splits.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payTo(\n JBSplit[] memory _splits,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Set the leftover amount to the initial balance.\n leftoverAmount = _amount;\n\n // Settle between all splits.\n for (uint256 i = 0; i < _splits.length; i++) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[i];\n\n // The amount to send towards the split.\n uint256 _splitAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n if (_splitAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n _token,\n _splitAmount,\n _decimals,\n defaultProjectId,\n 0,\n _split\n );\n\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN)\n IERC20(_token).approve(address(_split.allocator), _splitAmount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _splitAmount : 0;\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n if (_split.preferAddToBalance)\n _addToBalanceOf(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n 0,\n _split.preferClaimed,\n defaultMemo,\n defaultMetadata\n );\n } else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : payable(_defaultBeneficiary),\n _splitAmount\n );\n // Or, transfer the ERC20.\n else {\n IERC20(_token).transfer(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n _splitAmount\n );\n }\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _splitAmount;\n }\n\n emit DistributeToSplit(_split, _splitAmount, _defaultBeneficiary, msg.sender);\n }\n }\n}\n" }, "contracts/interfaces/IJBSplitsPayer.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './../structs/JBSplit.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBSplitsPayer is IERC165 {\n event SetDefaultSplits(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n address caller\n );\n event Pay(\n uint256 indexed projectId,\n address beneficiary,\n address token,\n uint256 amount,\n uint256 decimals,\n uint256 leftoverAmount,\n uint256 minReturnedTokens,\n bool preferClaimedTokens,\n string memo,\n bytes metadata,\n address caller\n );\n\n event AddToBalance(\n uint256 indexed projectId,\n address beneficiary,\n address token,\n uint256 amount,\n uint256 decimals,\n uint256 leftoverAmount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DistributeToSplitGroup(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n address caller\n );\n\n event DistributeToSplit(\n JBSplit split,\n uint256 amount,\n address defaultBeneficiary,\n address caller\n );\n\n function defaultSplitsProjectId() external view returns (uint256);\n\n function defaultSplitsDomain() external view returns (uint256);\n\n function defaultSplitsGroup() external view returns (uint256);\n\n function splitsStore() external view returns (IJBSplitsStore);\n\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) external;\n}\n" }, - "contracts/JBETHERC20ProjectPayer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport './interfaces/IJBProjectPayer.sol';\nimport './libraries/JBTokens.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ERC165: Introspection on interface adherance. \n*/\ncontract JBETHERC20ProjectPayer is IJBProjectPayer, Ownable, ERC165 {\n //*********************************************************************//\n // -------------------------- custom errors -------------------------- //\n //*********************************************************************//\n error INCORRECT_DECIMAL_AMOUNT();\n error NO_MSG_VALUE_ALLOWED();\n error TERMINAL_NOT_FOUND();\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice \n A contract storing directories of terminals and controllers for each project.\n */\n IJBDirectory public immutable override directory;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The ID of the project that should be used to forward this contract's received payments.\n */\n uint256 public override defaultProjectId;\n\n /** \n @notice \n The beneficiary that should be used in the payment made when this contract receives payments.\n */\n address payable public override defaultBeneficiary;\n\n /** \n @notice \n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\n */\n bool public override defaultPreferClaimedTokens;\n\n /** \n @notice \n The memo that should be used in the payment made when this contract receives payments.\n */\n string public override defaultMemo;\n\n /** \n @notice \n The metadata that should be used in the payment made when this contract receives payments.\n */\n bytes public override defaultMetadata;\n\n /**\n @notice \n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n bool public override defaultPreferAddToBalance;\n\n //*********************************************************************//\n // ------------------------- public views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) {\n defaultProjectId = _defaultProjectId;\n defaultBeneficiary = _defaultBeneficiary;\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\n defaultMemo = _defaultMemo;\n defaultMetadata = _defaultMetadata;\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n directory = _directory;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default project ID using the stored default properties.\n\n @dev\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override {\n if (defaultPreferAddToBalance)\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.ETH,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n defaultProjectId,\n JBTokens.ETH,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultBeneficiary == address(0) ? msg.sender : defaultBeneficiary,\n 0, // Can't determine expectation of returned tokens ahead of time.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\n\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _beneficiary The address that'll receive the project's tokens. \n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _memo The memo that'll be used. \n @param _metadata The metadata that'll be sent. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external virtual override onlyOwner {\n // Set the default project ID if it has changed.\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\n\n // Set the default beneficiary if it has changed.\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\n\n // Set the default claimed token preference if it has changed.\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\n defaultPreferClaimedTokens = _preferClaimedTokens;\n\n // Set the default memo if it has changed.\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\n defaultMemo = _memo;\n\n // Set the default metadata if it has changed.\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\n defaultMetadata = _metadata;\n\n // Set the add to balance preference if it has changed.\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n\n emit SetDefaultValues(\n _projectId,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata,\n _defaultPreferAddToBalance,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _pay(\n _projectId,\n _token,\n _amount,\n _decimals,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. \n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source and delegate, if provided.\n */\n function _pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.ETH) IERC20(_token).approve(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\n\n // Send funds to the terminal.\n // If the token is ETH, send it in msg.value.\n _terminal.pay{value: _payableValue}(\n _projectId,\n _amount, // ignored if the token is JBTokens.ETH.\n _token,\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.ETH) IERC20(_token).approve(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\n\n // Add to balance so tokens don't get issued.\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\n }\n}\n" + "contracts/JBGasTokenERC20ProjectPayer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport './interfaces/IJBProjectPayer.sol';\nimport './libraries/JBTokens.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ERC165: Introspection on interface adherance. \n*/\ncontract JBGasTokenERC20ProjectPayer is IJBProjectPayer, Ownable, ERC165 {\n //*********************************************************************//\n // -------------------------- custom errors -------------------------- //\n //*********************************************************************//\n error INCORRECT_DECIMAL_AMOUNT();\n error NO_MSG_VALUE_ALLOWED();\n error TERMINAL_NOT_FOUND();\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice \n A contract storing directories of terminals and controllers for each project.\n */\n IJBDirectory public immutable override directory;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The ID of the project that should be used to forward this contract's received payments.\n */\n uint256 public override defaultProjectId;\n\n /** \n @notice \n The beneficiary that should be used in the payment made when this contract receives payments.\n */\n address payable public override defaultBeneficiary;\n\n /** \n @notice \n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\n */\n bool public override defaultPreferClaimedTokens;\n\n /** \n @notice \n The memo that should be used in the payment made when this contract receives payments.\n */\n string public override defaultMemo;\n\n /** \n @notice \n The metadata that should be used in the payment made when this contract receives payments.\n */\n bytes public override defaultMetadata;\n\n /**\n @notice \n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n bool public override defaultPreferAddToBalance;\n\n //*********************************************************************//\n // ------------------------- public views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) {\n defaultProjectId = _defaultProjectId;\n defaultBeneficiary = _defaultBeneficiary;\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\n defaultMemo = _defaultMemo;\n defaultMetadata = _defaultMetadata;\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n directory = _directory;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default project ID using the stored default properties.\n\n @dev\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override {\n if (defaultPreferAddToBalance)\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultBeneficiary == address(0) ? msg.sender : defaultBeneficiary,\n 0, // Can't determine expectation of returned tokens ahead of time.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\n\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _beneficiary The address that'll receive the project's tokens. \n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _memo The memo that'll be used. \n @param _metadata The metadata that'll be sent. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external virtual override onlyOwner {\n // Set the default project ID if it has changed.\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\n\n // Set the default beneficiary if it has changed.\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\n\n // Set the default claimed token preference if it has changed.\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\n defaultPreferClaimedTokens = _preferClaimedTokens;\n\n // Set the default memo if it has changed.\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\n defaultMemo = _memo;\n\n // Set the default metadata if it has changed.\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\n defaultMetadata = _metadata;\n\n // Set the add to balance preference if it has changed.\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n\n emit SetDefaultValues(\n _projectId,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata,\n _defaultPreferAddToBalance,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _pay(\n _projectId,\n _token,\n _amount,\n _decimals,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).transferFrom(msg.sender, address(this), _amount);\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. \n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source and delegate, if provided.\n */\n function _pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).approve(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send funds to the terminal.\n // If the token is ETH, send it in msg.value.\n _terminal.pay{value: _payableValue}(\n _projectId,\n _amount, // ignored if the token is JBTokens.GAS_TOKEN.\n _token,\n _beneficiary != address(0) ? _beneficiary : msg.sender,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).approve(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Add to balance so tokens don't get issued.\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\n }\n}\n" }, "contracts/interfaces/IJBProjectPayer.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './IJBDirectory.sol';\n\ninterface IJBProjectPayer is IERC165 {\n event SetDefaultValues(\n uint256 indexed projectId,\n address indexed beneficiary,\n bool preferClaimedTokens,\n string memo,\n bytes metadata,\n bool preferAddToBalance,\n address caller\n );\n\n function directory() external view returns (IJBDirectory);\n\n function defaultProjectId() external view returns (uint256);\n\n function defaultBeneficiary() external view returns (address payable);\n\n function defaultPreferClaimedTokens() external view returns (bool);\n\n function defaultMemo() external view returns (string memory);\n\n function defaultMetadata() external view returns (bytes memory);\n\n function defaultPreferAddToBalance() external view returns (bool);\n\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external;\n\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) external payable;\n\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) external payable;\n\n receive() external payable;\n}\n" }, - "contracts/JBETHERC20SplitsPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './interfaces/IJBETHERC20SplitsPayerDeployer.sol';\nimport './JBETHERC20SplitsPayer.sol';\n\n/** \n @notice \n Deploys splits payer contracts.\n\n @dev\n Adheres to -\n IJBETHERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBETHERC20SplitsPayerDeployer is IJBETHERC20SplitsPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBSplitsPayer splitsPayer) {\n // Deploy the splits payer.\n splitsPayer = new JBETHERC20SplitsPayer(\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeploySplitsPayer(\n splitsPayer,\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner,\n msg.sender\n );\n }\n}\n" + "contracts/JBGasTokenERC20SplitsPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './interfaces/IJBGasTokenERC20SplitsPayerDeployer.sol';\nimport './JBGasTokenERC20SplitsPayer.sol';\n\n/** \n @notice \n Deploys splits payer contracts.\n\n @dev\n Adheres to -\n IJBGasTokenERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBGasTokenERC20SplitsPayerDeployer is IJBGasTokenERC20SplitsPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBSplitsPayer splitsPayer) {\n // Deploy the splits payer.\n splitsPayer = new JBGasTokenERC20SplitsPayer(\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeploySplitsPayer(\n splitsPayer,\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner,\n msg.sender\n );\n }\n}\n" }, - "contracts/interfaces/IJBETHERC20SplitsPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './IJBSplitsPayer.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBETHERC20SplitsPayerDeployer {\n event DeploySplitsPayer(\n IJBSplitsPayer indexed splitsPayer,\n uint256 defaultSplitsProjectId,\n uint256 defaultSplitsDomain,\n uint256 defaultSplitsGroup,\n IJBSplitsStore splitsStore,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n address owner,\n address caller\n );\n\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string calldata _defaultMemo,\n bytes calldata _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n}\n" + "contracts/interfaces/IJBGasTokenERC20SplitsPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './IJBSplitsPayer.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBGasTokenERC20SplitsPayerDeployer {\n event DeploySplitsPayer(\n IJBSplitsPayer indexed splitsPayer,\n uint256 defaultSplitsProjectId,\n uint256 defaultSplitsDomain,\n uint256 defaultSplitsGroup,\n IJBSplitsStore splitsStore,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n address owner,\n address caller\n );\n\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string calldata _defaultMemo,\n bytes calldata _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n}\n" }, - "contracts/JBETHERC20ProjectPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './interfaces/IJBETHERC20ProjectPayerDeployer.sol';\nimport './JBETHERC20ProjectPayer.sol';\n\n/** \n @notice \n Deploys project payer contracts.\n\n @dev\n Adheres to -\n IJBETHERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBETHERC20ProjectPayerDeployer is IJBETHERC20ProjectPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new project payer contract.\n\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the project payer contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the project payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the project payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the project payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the project payer.\n\n @return projectPayer The project payer contract.\n */\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external override returns (IJBProjectPayer projectPayer) {\n // Deploy the project payer.\n projectPayer = new JBETHERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner\n );\n\n emit DeployProjectPayer(\n projectPayer,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner,\n msg.sender\n );\n }\n}\n" + "contracts/JBGasTokenERC20ProjectPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './interfaces/IJBGasTokenERC20ProjectPayerDeployer.sol';\nimport './JBGasTokenERC20ProjectPayer.sol';\n\n/** \n @notice \n Deploys project payer contracts.\n\n @dev\n Adheres to -\n IJBGasTokenERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBGasTokenERC20ProjectPayerDeployer is IJBGasTokenERC20ProjectPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new project payer contract.\n\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the project payer contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the project payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the project payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the project payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the project payer.\n\n @return projectPayer The project payer contract.\n */\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external override returns (IJBProjectPayer projectPayer) {\n // Deploy the project payer.\n projectPayer = new JBGasTokenERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner\n );\n\n emit DeployProjectPayer(\n projectPayer,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner,\n msg.sender\n );\n }\n}\n" }, - "contracts/interfaces/IJBETHERC20ProjectPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './IJBDirectory.sol';\nimport './IJBProjectPayer.sol';\n\ninterface IJBETHERC20ProjectPayerDeployer {\n event DeployProjectPayer(\n IJBProjectPayer indexed projectPayer,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n IJBDirectory directory,\n address owner,\n address caller\n );\n\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external returns (IJBProjectPayer projectPayer);\n}\n" + "contracts/interfaces/IJBGasTokenERC20ProjectPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport './IJBDirectory.sol';\nimport './IJBProjectPayer.sol';\n\ninterface IJBGasTokenERC20ProjectPayerDeployer {\n event DeployProjectPayer(\n IJBProjectPayer indexed projectPayer,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n IJBDirectory directory,\n address owner,\n address caller\n );\n\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external returns (IJBProjectPayer projectPayer);\n}\n" }, "contracts/system_tests/TestPayBurnRedeemFlow.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.6;\n\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport '@paulrberg/contracts/math/PRBMathUD60x18.sol';\n\nimport './helpers/TestBaseWorkflow.sol';\n\n/**\n * This system test file verifies the following flow:\n * launch project → issue token → pay project (claimed tokens) → burn some of the claimed tokens → redeem rest of tokens\n */\ncontract TestPayBurnRedeemFlow is TestBaseWorkflow {\n JBController private _controller;\n JBETHPaymentTerminal private _terminal;\n JBTokenStore private _tokenStore;\n\n JBProjectMetadata private _projectMetadata;\n JBFundingCycleData private _data;\n JBFundingCycleMetadata private _metadata;\n JBGroupedSplits[] private _groupedSplits; // Default empty\n JBFundAccessConstraints[] private _fundAccessConstraints; // Default empty\n IJBPaymentTerminal[] private _terminals; // Default empty\n\n uint256 private _projectId;\n address private _projectOwner;\n uint256 private _weight = 1000 * 10**18;\n uint256 private _targetInWei = 10 * 10**18;\n\n function setUp() public override {\n super.setUp();\n\n _controller = jbController();\n _terminal = jbETHPaymentTerminal();\n _tokenStore = jbTokenStore();\n\n _projectMetadata = JBProjectMetadata({content: 'myIPFSHash', domain: 1});\n\n _data = JBFundingCycleData({\n duration: 14,\n weight: _weight,\n discountRate: 450000000,\n ballot: IJBFundingCycleBallot(address(0))\n });\n\n _metadata = JBFundingCycleMetadata({\n global: JBGlobalFundingCycleMetadata({allowSetTerminals: false, allowSetController: false}),\n reservedRate: 0,\n redemptionRate: 10000, //100%\n ballotRedemptionRate: 0,\n pausePay: false,\n pauseDistributions: false,\n pauseRedeem: false,\n pauseBurn: false,\n allowMinting: false,\n allowChangeToken: false,\n allowTerminalMigration: false,\n allowControllerMigration: false,\n holdFees: false,\n useTotalOverflowForRedemptions: false,\n useDataSourceForPay: false,\n useDataSourceForRedeem: false,\n dataSource: address(0)\n });\n\n _terminals.push(_terminal);\n\n _fundAccessConstraints.push(\n JBFundAccessConstraints({\n terminal: _terminal,\n token: jbLibraries().ETHToken(),\n distributionLimit: _targetInWei, // 10 ETH target\n overflowAllowance: 5 ether,\n distributionLimitCurrency: 1, // Currency = ETH\n overflowAllowanceCurrency: 1\n })\n );\n\n _projectOwner = multisig();\n\n _projectId = _controller.launchProjectFor(\n _projectOwner,\n _projectMetadata,\n _data,\n _metadata,\n block.timestamp,\n _groupedSplits,\n _fundAccessConstraints,\n _terminals,\n ''\n );\n }\n\n function testFuzzPayBurnRedeemFlow(\n bool payPreferClaimed, //false\n bool burnPreferClaimed, //false\n uint96 payAmountInWei, // 1\n uint256 burnTokenAmount, // 0\n uint256 redeemTokenAmount // 0\n ) external {\n // issue an ERC-20 token for project\n evm.prank(_projectOwner);\n _controller.issueTokenFor(_projectId, 'TestName', 'TestSymbol');\n\n address _userWallet = address(1234);\n\n // pay terminal\n _terminal.pay{value: payAmountInWei}(\n _projectId,\n payAmountInWei,\n address(0),\n _userWallet,\n /* _minReturnedTokens */\n 0,\n /* _preferClaimedTokens */\n payPreferClaimed,\n /* _memo */\n 'Take my money!',\n /* _delegateMetadata */\n new bytes(0)\n );\n\n // verify: beneficiary should have a balance of JBTokens\n uint256 _userTokenBalance = PRBMathUD60x18.mul(payAmountInWei, _weight);\n assertEq(_tokenStore.balanceOf(_userWallet, _projectId), _userTokenBalance);\n\n // verify: ETH balance in terminal should be up to date\n uint256 _terminalBalanceInWei = payAmountInWei;\n assertEq(jbPaymentTerminalStore().balanceOf(_terminal, _projectId), _terminalBalanceInWei);\n\n // burn tokens from beneficiary addr\n if (burnTokenAmount == 0) evm.expectRevert(abi.encodeWithSignature('NO_BURNABLE_TOKENS()'));\n else if (burnTokenAmount > _userTokenBalance)\n evm.expectRevert(abi.encodeWithSignature('INSUFFICIENT_FUNDS()'));\n else if (burnTokenAmount > uint256(type(int256).max))\n evm.expectRevert(abi.encodeWithSignature('Panic(uint256)', 0x11));\n else _userTokenBalance = _userTokenBalance - burnTokenAmount;\n\n evm.prank(_userWallet);\n _controller.burnTokensOf(\n _userWallet,\n _projectId,\n /* _tokenCount */\n burnTokenAmount,\n /* _memo */\n 'I hate tokens!',\n /* _preferClaimedTokens */\n burnPreferClaimed\n );\n\n // verify: beneficiary should have a new balance of JBTokens\n assertEq(_tokenStore.balanceOf(_userWallet, _projectId), _userTokenBalance);\n\n // redeem tokens\n if (redeemTokenAmount > _userTokenBalance)\n evm.expectRevert(abi.encodeWithSignature('INSUFFICIENT_TOKENS()'));\n else _userTokenBalance = _userTokenBalance - redeemTokenAmount;\n\n evm.prank(_userWallet);\n uint256 _reclaimAmtInWei = _terminal.redeemTokensOf(\n /* _holder */\n _userWallet,\n /* _projectId */\n _projectId,\n /* _tokenCount */\n redeemTokenAmount,\n /* token (unused) */\n address(0),\n /* _minReturnedWei */\n 0,\n /* _beneficiary */\n payable(_userWallet),\n /* _memo */\n 'Refund me now!',\n /* _delegateMetadata */\n new bytes(0)\n );\n\n // verify: beneficiary should have a new balance of JBTokens\n assertEq(_tokenStore.balanceOf(_userWallet, _projectId), _userTokenBalance);\n\n // verify: ETH balance in terminal should be up to date\n assertEq(\n jbPaymentTerminalStore().balanceOf(_terminal, _projectId),\n _terminalBalanceInWei - _reclaimAmtInWei\n );\n }\n}\n" diff --git a/deployments/mainnet/solcInputs/c01efb3c94c1f18d90d0889134c73f7b.json b/deployments/mainnet/solcInputs/c01efb3c94c1f18d90d0889134c73f7b.json index 5d7cb2121..8d5ecbf08 100644 --- a/deployments/mainnet/solcInputs/c01efb3c94c1f18d90d0889134c73f7b.json +++ b/deployments/mainnet/solcInputs/c01efb3c94c1f18d90d0889134c73f7b.json @@ -161,7 +161,7 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './../structs/JBFundAccessConstraints.sol';\nimport './../structs/JBFundingCycleData.sol';\nimport './../structs/JBFundingCycleMetadata.sol';\nimport './../structs/JBGroupedSplits.sol';\nimport './../structs/JBProjectMetadata.sol';\nimport './IJBDirectory.sol';\nimport './IJBFundingCycleStore.sol';\nimport './IJBMigratable.sol';\nimport './IJBPaymentTerminal.sol';\nimport './IJBSplitsStore.sol';\nimport './IJBTokenStore.sol';\n\ninterface IJBController is IERC165 {\n event LaunchProject(uint256 configuration, uint256 projectId, string memo, address caller);\n\n event LaunchFundingCycles(uint256 configuration, uint256 projectId, string memo, address caller);\n\n event ReconfigureFundingCycles(\n uint256 configuration,\n uint256 projectId,\n string memo,\n address caller\n );\n\n event SetFundAccessConstraints(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n JBFundAccessConstraints constraints,\n address caller\n );\n\n event DistributeReservedTokens(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address beneficiary,\n uint256 tokenCount,\n uint256 beneficiaryTokenCount,\n string memo,\n address caller\n );\n\n event DistributeToReservedTokenSplit(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n JBSplit split,\n uint256 tokenCount,\n address caller\n );\n\n event MintTokens(\n address indexed beneficiary,\n uint256 indexed projectId,\n uint256 tokenCount,\n uint256 beneficiaryTokenCount,\n string memo,\n uint256 reservedRate,\n address caller\n );\n\n event BurnTokens(\n address indexed holder,\n uint256 indexed projectId,\n uint256 tokenCount,\n string memo,\n address caller\n );\n\n event Migrate(uint256 indexed projectId, IJBMigratable to, address caller);\n\n event PrepMigration(uint256 indexed projectId, address from, address caller);\n\n function projects() external view returns (IJBProjects);\n\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\n\n function tokenStore() external view returns (IJBTokenStore);\n\n function splitsStore() external view returns (IJBSplitsStore);\n\n function directory() external view returns (IJBDirectory);\n\n function reservedTokenBalanceOf(uint256 _projectId, uint256 _reservedRate)\n external\n view\n returns (uint256);\n\n function distributionLimitOf(\n uint256 _projectId,\n uint256 _configuration,\n IJBPaymentTerminal _terminal,\n address _token\n ) external view returns (uint256 distributionLimit, uint256 distributionLimitCurrency);\n\n function overflowAllowanceOf(\n uint256 _projectId,\n uint256 _configuration,\n IJBPaymentTerminal _terminal,\n address _token\n ) external view returns (uint256 overflowAllowance, uint256 overflowAllowanceCurrency);\n\n function totalOutstandingTokensOf(uint256 _projectId, uint256 _reservedRate)\n external\n view\n returns (uint256);\n\n function getFundingCycleOf(uint256 _projectId, uint256 _configuration)\n external\n view\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\n\n function latestConfiguredFundingCycleOf(uint256 _projectId)\n external\n view\n returns (\n JBFundingCycle memory,\n JBFundingCycleMetadata memory metadata,\n JBBallotState\n );\n\n function currentFundingCycleOf(uint256 _projectId)\n external\n view\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\n\n function queuedFundingCycleOf(uint256 _projectId)\n external\n view\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\n\n function launchProjectFor(\n address _owner,\n JBProjectMetadata calldata _projectMetadata,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] memory _groupedSplits,\n JBFundAccessConstraints[] memory _fundAccessConstraints,\n IJBPaymentTerminal[] memory _terminals,\n string calldata _memo\n ) external returns (uint256 projectId);\n\n function launchFundingCyclesFor(\n uint256 _projectId,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] memory _groupedSplits,\n JBFundAccessConstraints[] memory _fundAccessConstraints,\n IJBPaymentTerminal[] memory _terminals,\n string calldata _memo\n ) external returns (uint256 configuration);\n\n function reconfigureFundingCyclesOf(\n uint256 _projectId,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] memory _groupedSplits,\n JBFundAccessConstraints[] memory _fundAccessConstraints,\n string calldata _memo\n ) external returns (uint256);\n\n function mintTokensOf(\n uint256 _projectId,\n uint256 _tokenCount,\n address _beneficiary,\n string calldata _memo,\n bool _preferClaimedTokens,\n bool _useReservedRate\n ) external returns (uint256 beneficiaryTokenCount);\n\n function burnTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string calldata _memo,\n bool _preferClaimedTokens\n ) external;\n\n function distributeReservedTokensOf(uint256 _projectId, string memory _memo)\n external\n returns (uint256);\n\n function migrate(uint256 _projectId, IJBMigratable _to) external;\n}\n" }, "contracts/JBSingleTokenPaymentTerminalStore3_1.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController3_1.sol';\nimport './interfaces/IJBFundingCycleDataSource.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './structs/JBPayDelegateAllocation.sol';\nimport './structs/JBPayParamsData.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n\n @dev\n This Store expects a project's controller to be an IJBController3_1. This is the only difference between this version and the original.\n*/\ncontract JBSingleTokenPaymentTerminalStore3_1 is\n ReentrancyGuard,\n IJBSingleTokenPaymentTerminalStore\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId);\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n JBPayDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .payParams(_data);\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\n {\n // Keep a reference to the amount that should be added to the project's balance.\n uint256 _balanceDiff = _amount.value;\n\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\n if (delegateAllocations.length != 0) {\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0) {\n // Can't delegate more than was paid.\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\n\n // Decrement the total amount being added to the balance.\n _balanceDiff = _balanceDiff - _delegatedAmount;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Add the correct balance difference to the token balance of the project.\n if (_balanceDiff != 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _balanceDiff;\n }\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId);\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow != 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\n {\n // Get a reference to the ballot state.\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\n\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n _state == JBBallotState.Active\n ? fundingCycle.ballotRedemptionRate()\n : fundingCycle.redemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\n fundingCycle.dataSource()\n ).redeemParams(_data);\n }\n } else {\n memo = _memo;\n }\n }\n\n // Keep a reference to the amount that should be subtracted from the project's balance.\n uint256 _balanceDiff = reclaimAmount;\n\n if (delegateAllocations.length != 0) {\n // Validate all delegated amounts.\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0)\n // Increment the total amount being subtracted from the balance.\n _balanceDiff = _balanceDiff + _delegatedAmount;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (_balanceDiff != 0) {\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n _balanceDiff;\n }\n }\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n unchecked {\n return\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i; _i < _terminals.length; ) {\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n unchecked {\n ++_i;\n }\n }\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.ETH\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.ETH, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController3_1.sol';\nimport './interfaces/IJBFundingCycleDataSource.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './structs/JBPayDelegateAllocation.sol';\nimport './structs/JBPayParamsData.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n\n @dev\n This Store expects a project's controller to be an IJBController3_1. This is the only difference between this version and the original.\n*/\ncontract JBSingleTokenPaymentTerminalStore3_1 is\n ReentrancyGuard,\n IJBSingleTokenPaymentTerminalStore\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId);\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n JBPayDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .payParams(_data);\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\n {\n // Keep a reference to the amount that should be added to the project's balance.\n uint256 _balanceDiff = _amount.value;\n\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\n if (delegateAllocations.length != 0) {\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0) {\n // Can't delegate more than was paid.\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\n\n // Decrement the total amount being added to the balance.\n _balanceDiff = _balanceDiff - _delegatedAmount;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Add the correct balance difference to the token balance of the project.\n if (_balanceDiff != 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _balanceDiff;\n }\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId);\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow != 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\n {\n // Get a reference to the ballot state.\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\n\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n _state == JBBallotState.Active\n ? fundingCycle.ballotRedemptionRate()\n : fundingCycle.redemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\n fundingCycle.dataSource()\n ).redeemParams(_data);\n }\n } else {\n memo = _memo;\n }\n }\n\n // Keep a reference to the amount that should be subtracted from the project's balance.\n uint256 _balanceDiff = reclaimAmount;\n\n if (delegateAllocations.length != 0) {\n // Validate all delegated amounts.\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0)\n // Increment the total amount being subtracted from the balance.\n _balanceDiff = _balanceDiff + _delegatedAmount;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (_balanceDiff != 0) {\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n _balanceDiff;\n }\n }\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n unchecked {\n return\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i; _i < _terminals.length; ) {\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n unchecked {\n ++_i;\n }\n }\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.GAS_CURRENCY\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.GAS_CURRENCY, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" }, "@openzeppelin/contracts/security/ReentrancyGuard.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n constructor() {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n // On the first call to nonReentrant, _notEntered will be true\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n\n _;\n\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n}\n" @@ -221,7 +221,7 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IJBPriceFeed {\n function currentPrice(uint256 _targetDecimals) external view returns (uint256);\n}\n" }, "contracts/JBSingleTokenPaymentTerminalStore.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController.sol';\nimport './interfaces/IJBFundingCycleDataSource.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './structs/JBPayDelegateAllocation.sol';\nimport './structs/JBPayParamsData.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBSingleTokenPaymentTerminalStore is ReentrancyGuard, IJBSingleTokenPaymentTerminalStore {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n JBPayDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .payParams(_data);\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\n {\n // Keep a reference to the amount that should be added to the project's balance.\n uint256 _balanceDiff = _amount.value;\n\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\n if (delegateAllocations.length != 0) {\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0) {\n // Can't delegate more than was paid.\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\n\n // Decrement the total amount being added to the balance.\n _balanceDiff = _balanceDiff - _delegatedAmount;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Add the correct balance difference to the token balance of the project.\n if (_balanceDiff != 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _balanceDiff;\n }\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\n _projectId,\n fundingCycle.reservedRate()\n );\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow != 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\n {\n // Get a reference to the ballot state.\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\n\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n _state == JBBallotState.Active\n ? fundingCycle.ballotRedemptionRate()\n : fundingCycle.redemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\n fundingCycle.dataSource()\n ).redeemParams(_data);\n }\n } else {\n memo = _memo;\n }\n }\n\n // Keep a reference to the amount that should be subtracted from the project's balance.\n uint256 _balanceDiff = reclaimAmount;\n\n if (delegateAllocations.length != 0) {\n // Validate all delegated amounts.\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0)\n // Increment the total amount being subtracted from the balance.\n _balanceDiff = _balanceDiff + _delegatedAmount;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (_balanceDiff != 0) {\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n _balanceDiff;\n }\n }\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n unchecked {\n return\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i; _i < _terminals.length; ) {\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n unchecked {\n ++_i;\n }\n }\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.ETH\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.ETH, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController.sol';\nimport './interfaces/IJBFundingCycleDataSource.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './structs/JBPayDelegateAllocation.sol';\nimport './structs/JBPayParamsData.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBSingleTokenPaymentTerminalStore is ReentrancyGuard, IJBSingleTokenPaymentTerminalStore {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n JBPayDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .payParams(_data);\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\n {\n // Keep a reference to the amount that should be added to the project's balance.\n uint256 _balanceDiff = _amount.value;\n\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\n if (delegateAllocations.length != 0) {\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0) {\n // Can't delegate more than was paid.\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\n\n // Decrement the total amount being added to the balance.\n _balanceDiff = _balanceDiff - _delegatedAmount;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Add the correct balance difference to the token balance of the project.\n if (_balanceDiff != 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _balanceDiff;\n }\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\n _projectId,\n fundingCycle.reservedRate()\n );\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow != 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\n {\n // Get a reference to the ballot state.\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\n\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n _state == JBBallotState.Active\n ? fundingCycle.ballotRedemptionRate()\n : fundingCycle.redemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\n fundingCycle.dataSource()\n ).redeemParams(_data);\n }\n } else {\n memo = _memo;\n }\n }\n\n // Keep a reference to the amount that should be subtracted from the project's balance.\n uint256 _balanceDiff = reclaimAmount;\n\n if (delegateAllocations.length != 0) {\n // Validate all delegated amounts.\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0)\n // Increment the total amount being subtracted from the balance.\n _balanceDiff = _balanceDiff + _delegatedAmount;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (_balanceDiff != 0) {\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n _balanceDiff;\n }\n }\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n unchecked {\n return\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i; _i < _terminals.length; ) {\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n unchecked {\n ++_i;\n }\n }\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.GAS_CURRENCY\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.GAS_CURRENCY, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" }, "contracts/JBController3_1.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport '@openzeppelin/contracts/utils/math/SafeCast.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './abstract/JBOperatable.sol';\nimport './interfaces/IJBController3_1.sol';\nimport './interfaces/IJBMigratable.sol';\nimport './interfaces/IJBOperatorStore.sol';\nimport './interfaces/IJBPaymentTerminal.sol';\nimport './interfaces/IJBProjects.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './libraries/JBOperations.sol';\nimport './libraries/JBSplitsGroups.sol';\n\n/**\n @notice\n Stitches together funding cycles and project tokens, making sure all activity is accounted for and correct.\n\n @dev\n Adheres to -\n IJBController3_1: General interface for the generic controller methods in this contract that interacts with funding cycles and tokens according to the protocol's rules.\n IJBMigratable: Allows migrating to this contract, with a hook called to prepare for the migration.\n\n @dev\n Inherits from -\n JBOperatable: Several functions in this contract can only be accessed by a project owner, or an address that has been preconfifigured to be an operator of the project.\n ERC165: Introspection on interface adherance. \n\n @dev\n This Controller has the same functionality as JBController3_1, except it is not backwards compatible with the original IJBController view methods.\n*/\ncontract JBController3_1 is JBOperatable, ERC165, IJBController3_1, IJBMigratable {\n // A library that parses the packed funding cycle metadata into a more friendly format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error BURN_PAUSED_AND_SENDER_NOT_VALID_TERMINAL_DELEGATE();\n error CANT_MIGRATE_TO_CURRENT_CONTROLLER();\n error FUNDING_CYCLE_ALREADY_LAUNCHED();\n error INVALID_BALLOT_REDEMPTION_RATE();\n error INVALID_DISTRIBUTION_LIMIT();\n error INVALID_DISTRIBUTION_LIMIT_CURRENCY();\n error INVALID_OVERFLOW_ALLOWANCE();\n error INVALID_OVERFLOW_ALLOWANCE_CURRENCY();\n error INVALID_REDEMPTION_RATE();\n error INVALID_RESERVED_RATE();\n error MIGRATION_NOT_ALLOWED();\n error MINT_NOT_ALLOWED_AND_NOT_TERMINAL_DELEGATE();\n error NO_BURNABLE_TOKENS();\n error NOT_CURRENT_CONTROLLER();\n error OVERFLOW_ALERT();\n error ZERO_TOKENS_TO_MINT();\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Data regarding the distribution limit of a project during a configuration.\n\n @dev\n bits 0-231: The amount of token that a project can distribute per funding cycle.\n\n @dev\n bits 232-255: The currency of amount that a project can distribute.\n\n _projectId The ID of the project to get the packed distribution limit data of.\n _configuration The configuration during which the packed distribution limit data applies.\n _terminal The terminal from which distributions are being limited.\n _token The token for which distributions are being limited.\n */\n mapping(uint256 => mapping(uint256 => mapping(IJBPaymentTerminal => mapping(address => uint256))))\n internal _packedDistributionLimitDataOf;\n\n /**\n @notice\n Data regarding the overflow allowance of a project during a configuration.\n\n @dev\n bits 0-231: The amount of overflow that a project is allowed to tap into on-demand throughout the configuration.\n\n @dev\n bits 232-255: The currency of the amount of overflow that a project is allowed to tap.\n\n _projectId The ID of the project to get the packed overflow allowance data of.\n _configuration The configuration during which the packed overflow allowance data applies.\n _terminal The terminal managing the overflow.\n _token The token for which overflow is being allowed.\n */\n mapping(uint256 => mapping(uint256 => mapping(IJBPaymentTerminal => mapping(address => uint256))))\n internal _packedOverflowAllowanceDataOf;\n\n //*********************************************************************//\n // --------------- public immutable stored properties ---------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that manages token minting and burning.\n */\n IJBTokenStore public immutable override tokenStore;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The current undistributed reserved token balance of.\n\n _projectId The ID of the project to get a reserved token balance of.\n */\n mapping(uint256 => uint256) public override reservedTokenBalanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of token that a project can distribute per funding cycle, and the currency it's in terms of.\n\n @dev\n The number of decimals in the returned fixed point amount is the same as that of the specified terminal. \n\n @param _projectId The ID of the project to get the distribution limit of.\n @param _configuration The configuration during which the distribution limit applies.\n @param _terminal The terminal from which distributions are being limited.\n @param _token The token for which the distribution limit applies.\n\n @return The distribution limit, as a fixed point number with the same number of decimals as the provided terminal.\n @return The currency of the distribution limit.\n */\n function distributionLimitOf(\n uint256 _projectId,\n uint256 _configuration,\n IJBPaymentTerminal _terminal,\n address _token\n ) external view override returns (uint256, uint256) {\n // Get a reference to the packed data.\n uint256 _data = _packedDistributionLimitDataOf[_projectId][_configuration][_terminal][_token];\n\n // The limit is in bits 0-231. The currency is in bits 232-255.\n return (uint256(uint232(_data)), _data >> 232);\n }\n\n /**\n @notice\n The amount of overflow that a project is allowed to tap into on-demand throughout a configuration, and the currency it's in terms of.\n\n @dev\n The number of decimals in the returned fixed point amount is the same as that of the specified terminal. \n\n @param _projectId The ID of the project to get the overflow allowance of.\n @param _configuration The configuration of the during which the allowance applies.\n @param _terminal The terminal managing the overflow.\n @param _token The token for which the overflow allowance applies.\n\n @return The overflow allowance, as a fixed point number with the same number of decimals as the provided terminal.\n @return The currency of the overflow allowance.\n */\n function overflowAllowanceOf(\n uint256 _projectId,\n uint256 _configuration,\n IJBPaymentTerminal _terminal,\n address _token\n ) external view override returns (uint256, uint256) {\n // Get a reference to the packed data.\n uint256 _data = _packedOverflowAllowanceDataOf[_projectId][_configuration][_terminal][_token];\n\n // The allowance is in bits 0-231. The currency is in bits 232-255.\n return (uint256(uint232(_data)), _data >> 232);\n }\n\n /** \n @notice\n A project's funding cycle for the specified configuration along with its metadata.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n \n @return fundingCycle The funding cycle.\n @return metadata The funding cycle's metadata.\n */\n function getFundingCycleOf(uint256 _projectId, uint256 _configuration)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata)\n {\n fundingCycle = fundingCycleStore.get(_projectId, _configuration);\n metadata = fundingCycle.expandMetadata();\n }\n\n /** \n @notice\n A project's latest configured funding cycle along with its metadata and the ballot state of the configuration.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n \n @return fundingCycle The latest configured funding cycle.\n @return metadata The latest configured funding cycle's metadata.\n @return ballotState The state of the configuration.\n */\n function latestConfiguredFundingCycleOf(uint256 _projectId)\n external\n view\n override\n returns (\n JBFundingCycle memory fundingCycle,\n JBFundingCycleMetadata memory metadata,\n JBBallotState ballotState\n )\n {\n (fundingCycle, ballotState) = fundingCycleStore.latestConfiguredOf(_projectId);\n metadata = fundingCycle.expandMetadata();\n }\n\n /** \n @notice\n A project's current funding cycle along with its metadata.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n \n @return fundingCycle The current funding cycle.\n @return metadata The current funding cycle's metadata.\n */\n function currentFundingCycleOf(uint256 _projectId)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata)\n {\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n metadata = fundingCycle.expandMetadata();\n }\n\n /** \n @notice\n A project's queued funding cycle along with its metadata.\n\n @param _projectId The ID of the project to which the funding cycle belongs.\n \n @return fundingCycle The queued funding cycle.\n @return metadata The queued funding cycle's metadata.\n */\n function queuedFundingCycleOf(uint256 _projectId)\n external\n view\n override\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata)\n {\n fundingCycle = fundingCycleStore.queuedOf(_projectId);\n metadata = fundingCycle.expandMetadata();\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current total amount of outstanding tokens for a project.\n\n @param _projectId The ID of the project to get total outstanding tokens of.\n\n @return The current total amount of outstanding tokens for the project.\n */\n function totalOutstandingTokensOf(uint256 _projectId) public view override returns (uint256) {\n // Add the reserved tokens to the total supply.\n return tokenStore.totalSupplyOf(_projectId) + reservedTokenBalanceOf[_projectId];\n }\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBController3_1).interfaceId ||\n _interfaceId == type(IJBController3_0_1).interfaceId ||\n _interfaceId == type(IJBMigratable).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // ---------------------------- constructor -------------------------- //\n //*********************************************************************//\n\n /**\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _tokenStore A contract that manages token minting and burning.\n @param _splitsStore A contract that stores splits for each project.\n */\n constructor(\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBTokenStore _tokenStore,\n IJBSplitsStore _splitsStore\n ) JBOperatable(_operatorStore) {\n projects = _projects;\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n tokenStore = _tokenStore;\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // --------------------- external transactions ----------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Creates a project. This will mint an ERC-721 into the specified owner's account, configure a first funding cycle, and set up any splits.\n\n @dev\n Each operation within this transaction can be done in sequence separately.\n\n @dev\n Anyone can deploy a project on an owner's behalf.\n\n @param _owner The address to set as the owner of the project. The project ERC-721 will be owned by this address.\n @param _projectMetadata Metadata to associate with the project within a particular domain. This can be updated any time by the owner of the project.\n @param _data Data that defines the project's first funding cycle. These properties will remain fixed for the duration of the funding cycle.\n @param _metadata Metadata specifying the controller specific params that a funding cycle can have. These properties will remain fixed for the duration of the funding cycle.\n @param _mustStartAtOrAfter The time before which the configured funding cycle cannot start.\n @param _groupedSplits An array of splits to set for any number of groups. \n @param _fundAccessConstraints An array containing amounts that a project can use from its treasury for each payment terminal. Amounts are fixed point numbers using the same number of decimals as the accompanying terminal. The `_distributionLimit` and `_overflowAllowance` parameters must fit in a `uint232`.\n @param _terminals Payment terminals to add for the project.\n @param _memo A memo to pass along to the emitted event.\n\n @return projectId The ID of the project.\n */\n function launchProjectFor(\n address _owner,\n JBProjectMetadata calldata _projectMetadata,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] calldata _groupedSplits,\n JBFundAccessConstraints[] calldata _fundAccessConstraints,\n IJBPaymentTerminal[] memory _terminals,\n string memory _memo\n ) external virtual override returns (uint256 projectId) {\n // Keep a reference to the directory.\n IJBDirectory _directory = directory;\n\n // Mint the project into the wallet of the owner.\n projectId = projects.createFor(_owner, _projectMetadata);\n\n // Set this contract as the project's controller in the directory.\n _directory.setControllerOf(projectId, address(this));\n\n // Configure the first funding cycle.\n uint256 _configuration = _configure(\n projectId,\n _data,\n _metadata,\n _mustStartAtOrAfter,\n _groupedSplits,\n _fundAccessConstraints\n );\n\n // Add the provided terminals to the list of terminals.\n if (_terminals.length > 0) _directory.setTerminalsOf(projectId, _terminals);\n\n emit LaunchProject(_configuration, projectId, _memo, msg.sender);\n }\n\n /**\n @notice\n Creates a funding cycle for an already existing project ERC-721.\n\n @dev\n Each operation within this transaction can be done in sequence separately.\n\n @dev\n Only a project owner or operator can launch its funding cycles.\n\n @param _projectId The ID of the project to launch funding cycles for.\n @param _data Data that defines the project's first funding cycle. These properties will remain fixed for the duration of the funding cycle.\n @param _metadata Metadata specifying the controller specific params that a funding cycle can have. These properties will remain fixed for the duration of the funding cycle.\n @param _mustStartAtOrAfter The time before which the configured funding cycle cannot start.\n @param _groupedSplits An array of splits to set for any number of groups. \n @param _fundAccessConstraints An array containing amounts that a project can use from its treasury for each payment terminal. Amounts are fixed point numbers using the same number of decimals as the accompanying terminal. The `_distributionLimit` and `_overflowAllowance` parameters must fit in a `uint232`.\n @param _terminals Payment terminals to add for the project.\n @param _memo A memo to pass along to the emitted event.\n\n @return configuration The configuration of the funding cycle that was successfully created.\n */\n function launchFundingCyclesFor(\n uint256 _projectId,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] calldata _groupedSplits,\n JBFundAccessConstraints[] memory _fundAccessConstraints,\n IJBPaymentTerminal[] memory _terminals,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.RECONFIGURE)\n returns (uint256 configuration)\n {\n // If there is a previous configuration, reconfigureFundingCyclesOf should be called instead\n if (fundingCycleStore.latestConfigurationOf(_projectId) > 0)\n revert FUNDING_CYCLE_ALREADY_LAUNCHED();\n\n // Set this contract as the project's controller in the directory.\n directory.setControllerOf(_projectId, address(this));\n\n // Configure the first funding cycle.\n configuration = _configure(\n _projectId,\n _data,\n _metadata,\n _mustStartAtOrAfter,\n _groupedSplits,\n _fundAccessConstraints\n );\n\n // Add the provided terminals to the list of terminals.\n if (_terminals.length > 0) directory.setTerminalsOf(_projectId, _terminals);\n\n emit LaunchFundingCycles(configuration, _projectId, _memo, msg.sender);\n }\n\n /**\n @notice\n Proposes a configuration of a subsequent funding cycle that will take effect once the current one expires if it is approved by the current funding cycle's ballot.\n\n @dev\n Only a project's owner or a designated operator can configure its funding cycles.\n\n @param _projectId The ID of the project whose funding cycles are being reconfigured.\n @param _data Data that defines the funding cycle. These properties will remain fixed for the duration of the funding cycle.\n @param _metadata Metadata specifying the controller specific params that a funding cycle can have. These properties will remain fixed for the duration of the funding cycle.\n @param _mustStartAtOrAfter The time before which the configured funding cycle cannot start.\n @param _groupedSplits An array of splits to set for any number of groups. \n @param _fundAccessConstraints An array containing amounts that a project can use from its treasury for each payment terminal. Amounts are fixed point numbers using the same number of decimals as the accompanying terminal. The `_distributionLimit` and `_overflowAllowance` parameters must fit in a `uint232`.\n @param _memo A memo to pass along to the emitted event.\n\n @return configuration The configuration of the funding cycle that was successfully reconfigured.\n */\n function reconfigureFundingCyclesOf(\n uint256 _projectId,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] calldata _groupedSplits,\n JBFundAccessConstraints[] calldata _fundAccessConstraints,\n string calldata _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.RECONFIGURE)\n returns (uint256 configuration)\n {\n // Configure the next funding cycle.\n configuration = _configure(\n _projectId,\n _data,\n _metadata,\n _mustStartAtOrAfter,\n _groupedSplits,\n _fundAccessConstraints\n );\n\n emit ReconfigureFundingCycles(configuration, _projectId, _memo, msg.sender);\n }\n\n /**\n @notice\n Mint new token supply into an account, and optionally reserve a supply to be distributed according to the project's current funding cycle configuration.\n\n @dev\n Only a project's owner, a designated operator, one of its terminals, or the current data source can mint its tokens.\n\n @param _projectId The ID of the project to which the tokens being minted belong.\n @param _tokenCount The amount of tokens to mint in total, counting however many should be reserved.\n @param _beneficiary The account that the tokens are being minted for.\n @param _memo A memo to pass along to the emitted event.\n @param _preferClaimedTokens A flag indicating whether a project's attached token contract should be minted if they have been issued.\n @param _useReservedRate Whether to use the current funding cycle's reserved rate in the mint calculation.\n\n @return beneficiaryTokenCount The amount of tokens minted for the beneficiary.\n */\n function mintTokensOf(\n uint256 _projectId,\n uint256 _tokenCount,\n address _beneficiary,\n string calldata _memo,\n bool _preferClaimedTokens,\n bool _useReservedRate\n ) external virtual override returns (uint256 beneficiaryTokenCount) {\n // There should be tokens to mint.\n if (_tokenCount == 0) revert ZERO_TOKENS_TO_MINT();\n\n // Define variables that will be needed outside scoped section below.\n // Keep a reference to the reserved rate to use\n uint256 _reservedRate;\n\n // Scoped section prevents stack too deep. `_fundingCycle` only used within scope.\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Minting limited to: project owner, authorized callers, project terminal and current funding cycle data source\n _requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.MINT,\n directory.isTerminalOf(_projectId, IJBPaymentTerminal(msg.sender)) ||\n msg.sender == address(_fundingCycle.dataSource())\n );\n\n // If the message sender is not a terminal or a datasource, the current funding cycle must allow minting.\n if (\n !_fundingCycle.mintingAllowed() &&\n !directory.isTerminalOf(_projectId, IJBPaymentTerminal(msg.sender)) &&\n msg.sender != address(_fundingCycle.dataSource())\n ) revert MINT_NOT_ALLOWED_AND_NOT_TERMINAL_DELEGATE();\n\n // Determine the reserved rate to use.\n _reservedRate = _useReservedRate ? _fundingCycle.reservedRate() : 0;\n\n // Override the claimed token preference with the funding cycle value.\n _preferClaimedTokens = _preferClaimedTokens == true\n ? _preferClaimedTokens\n : _fundingCycle.preferClaimedTokenOverride();\n }\n\n if (_reservedRate != JBConstants.MAX_RESERVED_RATE) {\n // The unreserved token count that will be minted for the beneficiary.\n beneficiaryTokenCount = PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_RESERVED_RATE - _reservedRate,\n JBConstants.MAX_RESERVED_RATE\n );\n\n // Mint the tokens.\n tokenStore.mintFor(_beneficiary, _projectId, beneficiaryTokenCount, _preferClaimedTokens);\n }\n\n // Add reserved tokens if needed\n if (_reservedRate > 0)\n reservedTokenBalanceOf[_projectId] += _tokenCount - beneficiaryTokenCount;\n\n emit MintTokens(\n _beneficiary,\n _projectId,\n _tokenCount,\n beneficiaryTokenCount,\n _memo,\n _reservedRate,\n msg.sender\n );\n }\n\n /**\n @notice\n Burns a token holder's supply.\n\n @dev\n Only a token's holder, a designated operator, or a project's terminal can burn it.\n\n @param _holder The account that is having its tokens burned.\n @param _projectId The ID of the project to which the tokens being burned belong.\n @param _tokenCount The number of tokens to burn.\n @param _memo A memo to pass along to the emitted event.\n @param _preferClaimedTokens A flag indicating whether a project's attached token contract should be burned first if they have been issued.\n */\n function burnTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string calldata _memo,\n bool _preferClaimedTokens\n )\n external\n virtual\n override\n requirePermissionAllowingOverride(\n _holder,\n _projectId,\n JBOperations.BURN,\n directory.isTerminalOf(_projectId, IJBPaymentTerminal(msg.sender))\n )\n {\n // There should be tokens to burn\n if (_tokenCount == 0) revert NO_BURNABLE_TOKENS();\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // If the message sender is a terminal, the current funding cycle must not be paused.\n if (\n _fundingCycle.burnPaused() &&\n !directory.isTerminalOf(_projectId, IJBPaymentTerminal(msg.sender))\n ) revert BURN_PAUSED_AND_SENDER_NOT_VALID_TERMINAL_DELEGATE();\n\n // Burn the tokens.\n tokenStore.burnFrom(_holder, _projectId, _tokenCount, _preferClaimedTokens);\n\n emit BurnTokens(_holder, _projectId, _tokenCount, _memo, msg.sender);\n }\n\n /**\n @notice\n Distributes all outstanding reserved tokens for a project.\n\n @param _projectId The ID of the project to which the reserved tokens belong.\n @param _memo A memo to pass along to the emitted event.\n\n @return The amount of minted reserved tokens.\n */\n function distributeReservedTokensOf(uint256 _projectId, string calldata _memo)\n external\n virtual\n override\n returns (uint256)\n {\n return _distributeReservedTokensOf(_projectId, _memo);\n }\n\n /**\n @notice\n Allows other controllers to signal to this one that a migration is expected for the specified project.\n\n @dev\n This controller should not yet be the project's controller.\n\n @param _projectId The ID of the project that will be migrated to this controller.\n @param _from The controller being migrated from.\n */\n function prepForMigrationOf(uint256 _projectId, address _from) external virtual override {\n _projectId; // Prevents unused var compiler and natspec complaints.\n _from; // Prevents unused var compiler and natspec complaints.\n }\n\n /**\n @notice\n Allows a project to migrate from this controller to another.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project that will be migrated from this controller.\n @param _to The controller to which the project is migrating.\n */\n function migrate(uint256 _projectId, IJBMigratable _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_CONTROLLER)\n {\n // Keep a reference to the directory.\n IJBDirectory _directory = directory;\n\n // This controller must be the project's current controller.\n if (_directory.controllerOf(_projectId) != address(this)) revert NOT_CURRENT_CONTROLLER();\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.controllerMigrationAllowed()) revert MIGRATION_NOT_ALLOWED();\n\n // All reserved tokens must be minted before migrating.\n if (reservedTokenBalanceOf[_projectId] != 0) _distributeReservedTokensOf(_projectId, '');\n\n // Make sure the new controller is prepped for the migration.\n _to.prepForMigrationOf(_projectId, address(this));\n\n // Set the new controller.\n _directory.setControllerOf(_projectId, address(_to));\n\n emit Migrate(_projectId, _to, msg.sender);\n }\n\n //*********************************************************************//\n // ------------------------ internal functions ----------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Distributes all outstanding reserved tokens for a project.\n\n @param _projectId The ID of the project to which the reserved tokens belong.\n @param _memo A memo to pass along to the emitted event.\n\n @return tokenCount The amount of minted reserved tokens.\n */\n function _distributeReservedTokensOf(uint256 _projectId, string memory _memo)\n internal\n returns (uint256 tokenCount)\n {\n // Keep a reference to the token store.\n IJBTokenStore _tokenStore = tokenStore;\n\n // Get the current funding cycle to read the reserved rate from.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the number of tokens that need to be minted.\n tokenCount = reservedTokenBalanceOf[_projectId];\n\n // Reset the reserved token balance\n reservedTokenBalanceOf[_projectId] = 0;\n\n // Get a reference to the project owner.\n address _owner = projects.ownerOf(_projectId);\n\n // Distribute tokens to splits and get a reference to the leftover amount to mint after all splits have gotten their share.\n uint256 _leftoverTokenCount = tokenCount == 0\n ? 0\n : _distributeToReservedTokenSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n JBSplitsGroups.RESERVED_TOKENS,\n tokenCount\n );\n\n // Mint any leftover tokens to the project owner.\n if (_leftoverTokenCount > 0)\n _tokenStore.mintFor(_owner, _projectId, _leftoverTokenCount, false);\n\n emit DistributeReservedTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _owner,\n tokenCount,\n _leftoverTokenCount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Distribute tokens to the splits according to the specified funding cycle configuration.\n\n @param _projectId The ID of the project for which reserved token splits are being distributed.\n @param _domain The domain of the splits to distribute the reserved tokens between.\n @param _group The group of the splits to distribute the reserved tokens between.\n @param _amount The total amount of tokens to mint.\n\n @return leftoverAmount If the splits percents dont add up to 100%, the leftover amount is returned.\n */\n function _distributeToReservedTokenSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount\n ) internal returns (uint256 leftoverAmount) {\n // Keep a reference to the token store.\n IJBTokenStore _tokenStore = tokenStore;\n\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n\n // Get a reference to the project's reserved token splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n //Transfer between all splits.\n for (uint256 _i; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _tokenCount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n // Mints tokens for the split if needed.\n if (_tokenCount > 0) {\n _tokenStore.mintFor(\n // If an allocator is set in the splits, set it as the beneficiary.\n // Otherwise if a projectId is set in the split, set the project's owner as the beneficiary.\n // If the split has a beneficiary send to the split's beneficiary. Otherwise send to the msg.sender.\n _split.allocator != IJBSplitAllocator(address(0))\n ? address(_split.allocator)\n : _split.projectId != 0\n ? projects.ownerOf(_split.projectId)\n : _split.beneficiary != address(0)\n ? _split.beneficiary\n : msg.sender,\n _projectId,\n _tokenCount,\n _split.preferClaimed\n );\n\n // If there's an allocator set, trigger its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0)))\n _split.allocator.allocate(\n JBSplitAllocationData(\n address(_tokenStore.tokenOf(_projectId)),\n _tokenCount,\n 18,\n _projectId,\n _group,\n _split\n )\n );\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _tokenCount;\n }\n\n emit DistributeToReservedTokenSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _tokenCount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Configures a funding cycle and stores information pertinent to the configuration.\n\n @param _projectId The ID of the project whose funding cycles are being reconfigured.\n @param _data Data that defines the funding cycle. These properties will remain fixed for the duration of the funding cycle.\n @param _metadata Metadata specifying the controller specific params that a funding cycle can have. These properties will remain fixed for the duration of the funding cycle.\n @param _mustStartAtOrAfter The time before which the configured funding cycle cannot start.\n @param _groupedSplits An array of splits to set for any number of groups. \n @param _fundAccessConstraints An array containing amounts that a project can use from its treasury for each payment terminal. Amounts are fixed point numbers using the same number of decimals as the accompanying terminal.\n\n @return configuration The configuration of the funding cycle that was successfully reconfigured.\n */\n function _configure(\n uint256 _projectId,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] memory _groupedSplits,\n JBFundAccessConstraints[] memory _fundAccessConstraints\n ) internal returns (uint256) {\n // Make sure the provided reserved rate is valid.\n if (_metadata.reservedRate > JBConstants.MAX_RESERVED_RATE) revert INVALID_RESERVED_RATE();\n\n // Make sure the provided redemption rate is valid.\n if (_metadata.redemptionRate > JBConstants.MAX_REDEMPTION_RATE)\n revert INVALID_REDEMPTION_RATE();\n\n // Make sure the provided ballot redemption rate is valid.\n if (_metadata.ballotRedemptionRate > JBConstants.MAX_REDEMPTION_RATE)\n revert INVALID_BALLOT_REDEMPTION_RATE();\n\n // Configure the funding cycle's properties.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.configureFor(\n _projectId,\n _data,\n JBFundingCycleMetadataResolver.packFundingCycleMetadata(_metadata),\n _mustStartAtOrAfter\n );\n\n // Set splits for the group.\n splitsStore.set(_projectId, _fundingCycle.configuration, _groupedSplits);\n\n // Set distribution limits if there are any.\n for (uint256 _i; _i < _fundAccessConstraints.length; ) {\n JBFundAccessConstraints memory _constraints = _fundAccessConstraints[_i];\n\n // If distribution limit value is larger than 232 bits, revert.\n if (_constraints.distributionLimit > type(uint232).max) revert INVALID_DISTRIBUTION_LIMIT();\n\n // If distribution limit currency value is larger than 24 bits, revert.\n if (_constraints.distributionLimitCurrency > type(uint24).max)\n revert INVALID_DISTRIBUTION_LIMIT_CURRENCY();\n\n // If overflow allowance value is larger than 232 bits, revert.\n if (_constraints.overflowAllowance > type(uint232).max) revert INVALID_OVERFLOW_ALLOWANCE();\n\n // If overflow allowance currency value is larger than 24 bits, revert.\n if (_constraints.overflowAllowanceCurrency > type(uint24).max)\n revert INVALID_OVERFLOW_ALLOWANCE_CURRENCY();\n\n // Set the distribution limit if there is one.\n if (_constraints.distributionLimit > 0)\n _packedDistributionLimitDataOf[_projectId][_fundingCycle.configuration][\n _constraints.terminal\n ][_constraints.token] =\n _constraints.distributionLimit |\n (_constraints.distributionLimitCurrency << 232);\n\n // Set the overflow allowance if there is one.\n if (_constraints.overflowAllowance > 0)\n _packedOverflowAllowanceDataOf[_projectId][_fundingCycle.configuration][\n _constraints.terminal\n ][_constraints.token] =\n _constraints.overflowAllowance |\n (_constraints.overflowAllowanceCurrency << 232);\n\n emit SetFundAccessConstraints(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _constraints,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n\n return _fundingCycle.configuration;\n }\n}\n" @@ -233,13 +233,13 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nlibrary JBSplitsGroups {\n uint256 public constant ETH_PAYOUT = 1;\n uint256 public constant RESERVED_TOKENS = 2;\n}\n" }, "contracts/JBETHPaymentTerminal.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\nimport './libraries/JBSplitsGroups.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return address(this).balance;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n JBTokens.ETH,\n 18, // 18 decimals.\n JBCurrencies.ETH,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\nimport './libraries/JBSplitsGroups.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return address(this).balance;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n JBTokens.GAS_TOKEN,\n 18, // 18 decimals.\n JBCurrencies.GAS_CURRENCY,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n}\n" }, "@openzeppelin/contracts/utils/Address.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" }, "contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBPayDelegateAllocation.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal is\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n IJBPayoutRedemptionPaymentTerminal\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n @dev\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.ETH)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.ETH, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance.\n */\n function _balance() internal view virtual returns (uint256);\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.ETH) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual {\n _from; // Prevents unused var compiler and natspec complaints.\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\n {\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\n\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _forwardedAmount,\n _beneficiary,\n _memo,\n _metadata\n );\n\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\n\n emit DelegateDidRedeem(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n }\n\n // Take the fee.\n _fee = _feeEligibleDistributionAmount != 0\n ? _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n )\n : 0;\n\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\n if (_leftoverDistributionAmount != 0) {\n // Subtract the fee from the net leftover amount.\n netLeftoverDistributionAmount =\n _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n\n // Transfer the amount to the project owner.\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n // The total percentage available to split\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = _split.percent == leftoverPercentage\n ? leftoverAmount\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\n\n // Decrement the leftover percentage.\n leftoverPercentage -= _split.percent;\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount;\n\n if (_payoutAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\n isFeelessAddress[address(_split.allocator)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n _netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n // If this terminal's token is ETH, send it in msg.value.\n _split.allocator.allocate{value: token == JBTokens.ETH ? _netPayoutAmount : 0}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // Save gas if this contract is being used as the terminal.\n if (_terminal == this) {\n // This distribution does not incur a fee.\n _netPayoutAmount = _payoutAmount;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\n else\n _pay(\n _netPayoutAmount,\n address(this),\n _split.projectId,\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n } else {\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_terminal)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _netPayoutAmount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _terminal.addToBalanceOf{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n '',\n _projectMetadata\n );\n else\n _terminal.pay{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n }\n } else {\n // Keep a reference to the beneficiary.\n address payable _beneficiary = _split.beneficiary != address(0)\n ? _split.beneficiary\n : payable(msg.sender);\n\n // If there's a full discount, this distribution is not eligible for a fee.\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(address(this), _beneficiary, _netPayoutAmount);\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n */\n function _processFee(uint256 _amount, address _beneficiary) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\n\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\n if (_terminal == this)\n _pay(\n _amount,\n address(this),\n _FEE_BENEFICIARY_PROJECT_ID,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the local pay call.\n else {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _amount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _amount : 0;\n\n // Send the payment.\n _terminal.pay{value: _payableValue}(\n _FEE_BENEFICIARY_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the external pay call of the correct terminal.\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\n {\n JBPayDelegateAllocation[] memory _delegateAllocations;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n _forwardedAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n // Get a reference to the number of delegates to allocate to.\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\n\n emit DelegateDidPay(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n unchecked {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\n IJBPaymentTerminal(address(0))\n ) return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge != IJBFeeGauge(address(0)))\n // If the guage reverts, keep the discount at 0.\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n // If the fee discount is greater than the max, we ignore the return value\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\n } catch {\n return 0;\n }\n\n return 0;\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBPayDelegateAllocation.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal is\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n IJBPayoutRedemptionPaymentTerminal\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n @dev\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.GAS_CURRENCY)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.GAS_CURRENCY, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance.\n */\n function _balance() internal view virtual returns (uint256);\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.GAS_TOKEN) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual {\n _from; // Prevents unused var compiler and natspec complaints.\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\n {\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\n\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _forwardedAmount,\n _beneficiary,\n _memo,\n _metadata\n );\n\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\n\n emit DelegateDidRedeem(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n }\n\n // Take the fee.\n _fee = _feeEligibleDistributionAmount != 0\n ? _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n )\n : 0;\n\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\n if (_leftoverDistributionAmount != 0) {\n // Subtract the fee from the net leftover amount.\n netLeftoverDistributionAmount =\n _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n\n // Transfer the amount to the project owner.\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n // The total percentage available to split\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = _split.percent == leftoverPercentage\n ? leftoverAmount\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\n\n // Decrement the leftover percentage.\n leftoverPercentage -= _split.percent;\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount;\n\n if (_payoutAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\n isFeelessAddress[address(_split.allocator)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n _netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n // If this terminal's token is ETH, send it in msg.value.\n _split.allocator.allocate{value: token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // Save gas if this contract is being used as the terminal.\n if (_terminal == this) {\n // This distribution does not incur a fee.\n _netPayoutAmount = _payoutAmount;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\n else\n _pay(\n _netPayoutAmount,\n address(this),\n _split.projectId,\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n } else {\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_terminal)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _terminal.addToBalanceOf{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n '',\n _projectMetadata\n );\n else\n _terminal.pay{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n }\n } else {\n // Keep a reference to the beneficiary.\n address payable _beneficiary = _split.beneficiary != address(0)\n ? _split.beneficiary\n : payable(msg.sender);\n\n // If there's a full discount, this distribution is not eligible for a fee.\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(address(this), _beneficiary, _netPayoutAmount);\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n */\n function _processFee(uint256 _amount, address _beneficiary) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\n\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\n if (_terminal == this)\n _pay(\n _amount,\n address(this),\n _FEE_BENEFICIARY_PROJECT_ID,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the local pay call.\n else {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _amount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send the payment.\n _terminal.pay{value: _payableValue}(\n _FEE_BENEFICIARY_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the external pay call of the correct terminal.\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\n {\n JBPayDelegateAllocation[] memory _delegateAllocations;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n _forwardedAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n // Get a reference to the number of delegates to allocate to.\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\n\n emit DelegateDidPay(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n unchecked {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\n IJBPaymentTerminal(address(0))\n ) return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge != IJBFeeGauge(address(0)))\n // If the guage reverts, keep the discount at 0.\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n // If the fee discount is greater than the max, we ignore the return value\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\n } catch {\n return 0;\n }\n\n return 0;\n }\n}\n" }, "contracts/interfaces/IJBPayoutRedemptionPaymentTerminal.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './../structs/JBFee.sol';\nimport './IJBAllowanceTerminal.sol';\nimport './IJBDirectory.sol';\nimport './IJBFeeGauge.sol';\nimport './IJBPayDelegate.sol';\nimport './IJBPaymentTerminal.sol';\nimport './IJBPayoutTerminal.sol';\nimport './IJBPrices.sol';\nimport './IJBProjects.sol';\nimport './IJBRedemptionDelegate.sol';\nimport './IJBRedemptionTerminal.sol';\nimport './IJBSingleTokenPaymentTerminalStore.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBPayoutRedemptionPaymentTerminal is\n IJBPaymentTerminal,\n IJBPayoutTerminal,\n IJBAllowanceTerminal,\n IJBRedemptionTerminal\n{\n event AddToBalance(\n uint256 indexed projectId,\n uint256 amount,\n uint256 refundedFees,\n string memo,\n bytes metadata,\n address caller\n );\n\n event Migrate(\n uint256 indexed projectId,\n IJBPaymentTerminal indexed to,\n uint256 amount,\n address caller\n );\n\n event DistributePayouts(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address beneficiary,\n uint256 amount,\n uint256 distributedAmount,\n uint256 fee,\n uint256 beneficiaryDistributionAmount,\n string memo,\n address caller\n );\n\n event UseAllowance(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address beneficiary,\n uint256 amount,\n uint256 distributedAmount,\n uint256 netDistributedamount,\n string memo,\n address caller\n );\n\n event HoldFee(\n uint256 indexed projectId,\n uint256 indexed amount,\n uint256 indexed fee,\n uint256 feeDiscount,\n address beneficiary,\n address caller\n );\n\n event ProcessFee(\n uint256 indexed projectId,\n uint256 indexed amount,\n bool indexed wasHeld,\n address beneficiary,\n address caller\n );\n\n event RefundHeldFees(\n uint256 indexed projectId,\n uint256 indexed amount,\n uint256 indexed refundedFees,\n uint256 leftoverAmount,\n address caller\n );\n\n event Pay(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address payer,\n address beneficiary,\n uint256 amount,\n uint256 beneficiaryTokenCount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DelegateDidPay(\n IJBPayDelegate indexed delegate,\n JBDidPayData data,\n uint256 delegatedAmount,\n address caller\n );\n\n event RedeemTokens(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address holder,\n address beneficiary,\n uint256 tokenCount,\n uint256 reclaimedAmount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DelegateDidRedeem(\n IJBRedemptionDelegate indexed delegate,\n JBDidRedeemData data,\n uint256 delegatedAmount,\n address caller\n );\n\n event DistributeToPayoutSplit(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n JBSplit split,\n uint256 amount,\n address caller\n );\n\n event SetFee(uint256 fee, address caller);\n\n event SetFeeGauge(IJBFeeGauge indexed feeGauge, address caller);\n\n event SetFeelessAddress(address indexed addrs, bool indexed flag, address caller);\n\n function projects() external view returns (IJBProjects);\n\n function splitsStore() external view returns (IJBSplitsStore);\n\n function directory() external view returns (IJBDirectory);\n\n function prices() external view returns (IJBPrices);\n\n function store() external view returns (IJBSingleTokenPaymentTerminalStore);\n\n function baseWeightCurrency() external view returns (uint256);\n\n function payoutSplitsGroup() external view returns (uint256);\n\n function heldFeesOf(uint256 _projectId) external view returns (JBFee[] memory);\n\n function fee() external view returns (uint256);\n\n function feeGauge() external view returns (IJBFeeGauge);\n\n function isFeelessAddress(address _contract) external view returns (bool);\n\n function migrate(uint256 _projectId, IJBPaymentTerminal _to) external returns (uint256 balance);\n\n function processFees(uint256 _projectId) external;\n\n function setFee(uint256 _fee) external;\n\n function setFeeGauge(IJBFeeGauge _feeGauge) external;\n\n function setFeelessAddress(address _contract, bool _flag) external;\n}\n" @@ -271,23 +271,23 @@ "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n function safeTransfer(\n IERC20 token,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(\n IERC20 token,\n address from,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n uint256 newAllowance = token.allowance(address(this), spender) + value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n uint256 newAllowance = oldAllowance - value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) {\n // Return data is optional\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" }, - "contracts/JBETHERC20SplitsPayer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBSplitsPayer.sol';\nimport './interfaces/IJBSplitsStore.sol';\nimport './libraries/JBConstants.sol';\nimport './JBETHERC20ProjectPayer.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\n\n @dev\n Adheres to -\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBETHERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBETHERC20SplitsPayer is JBETHERC20ProjectPayer, ReentrancyGuard, IJBSplitsPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The ID of project for which the default splits are stored. \n */\n uint256 public override defaultSplitsProjectId;\n\n /**\n @notice\n The domain within which the default splits are stored. \n */\n uint256 public override defaultSplitsDomain;\n\n /**\n @notice\n The group within which the default splits are stored. \n */\n uint256 public override defaultSplitsGroup;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBETHERC20ProjectPayer, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n )\n JBETHERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _preferAddToBalance,\n _splitsStore.directory(),\n _owner\n )\n {\n defaultSplitsProjectId = _defaultSplitsProjectId;\n defaultSplitsDomain = _defaultSplitsDomain;\n defaultSplitsGroup = _defaultSplitsGroup;\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default split group using the stored default properties.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override nonReentrant {\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n JBTokens.ETH,\n address(this).balance,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // If there is no leftover amount, nothing left to pay.\n if (_leftoverAmount == 0) return;\n\n // If there's a default project ID, try to pay it.\n if (defaultProjectId != 0)\n if (defaultPreferAddToBalance)\n // Pay the project by adding to its balance if prefered.\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.ETH,\n _leftoverAmount,\n 18, // decimals.\n defaultMemo,\n defaultMetadata\n );\n // Otherwise, issue a payment to the project.\n else\n _pay(\n defaultProjectId,\n JBTokens.ETH,\n _leftoverAmount,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n 0, // min returned tokens.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else\n Address.sendValue(\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(tx.origin),\n _leftoverAmount\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the splits in the splits store that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n @param _groupedSplits The split groups to set.\n */\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n JBGroupedSplits[] memory _groupedSplits\n ) external virtual override onlyOwner {\n // Set the splits in the store.\n splitsStore.set(_projectId, _domain, _groupedSplits);\n\n // Set the splits reference.\n setDefaultSplitsReference(_projectId, _domain, _group);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the location of the splits that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n */\n function setDefaultSplitsReference(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) public virtual override onlyOwner {\n // Set the default splits project ID if it's changing.\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\n\n // Set the default splits domain if it's changing.\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\n\n // Set the default splits group if it's changing.\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\n\n emit SetDefaultSplitsReference(_projectId, _domain, _group, msg.sender);\n }\n\n /** \n @notice \n Make a payment to the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Pay any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to pay it.\n if (_projectId != 0) {\n _pay(\n _projectId,\n _token,\n _leftoverAmount,\n _decimals,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? payable(_beneficiary) : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit Pay(\n _projectId,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event. \n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Distribute any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to add to its balance.\n if (_projectId != 0)\n // Add to the project's balance.\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\n\n // Otherwise, send a payment to the beneficiary.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit AddToBalance(\n _projectId,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splitsProjectId The ID of the project to which the splits belong.\n @param _splitsDomain The splits domain to which the group belongs.\n @param _splitsGroup The splits group to pay.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payToSplits(\n uint256 _splitsProjectId,\n uint256 _splitsDomain,\n uint256 _splitsGroup,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Pay the splits.\n leftoverAmount = _payTo(\n splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup),\n _token,\n _amount,\n _decimals,\n _defaultBeneficiary\n );\n emit DistributeToSplitGroup(_splitsProjectId, _splitsDomain, _splitsGroup, msg.sender);\n }\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splits The splits.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payTo(\n JBSplit[] memory _splits,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Set the leftover amount to the initial balance.\n leftoverAmount = _amount;\n\n // Settle between all splits.\n for (uint256 i; i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[i];\n\n // The amount to send towards the split.\n uint256 _splitAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n if (_splitAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n _token,\n _splitAmount,\n _decimals,\n defaultProjectId,\n 0,\n _split\n );\n\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\n if (_token != JBTokens.ETH)\n IERC20(_token).safeApprove(address(_split.allocator), _splitAmount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _splitAmount : 0;\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n if (_split.preferAddToBalance)\n _addToBalanceOf(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n 0,\n _split.preferClaimed,\n defaultMemo,\n defaultMetadata\n );\n } else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : payable(_defaultBeneficiary),\n _splitAmount\n );\n // Or, transfer the ERC20.\n else {\n IERC20(_token).safeTransfer(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n _splitAmount\n );\n }\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _splitAmount;\n }\n\n emit DistributeToSplit(_split, _splitAmount, _defaultBeneficiary, msg.sender);\n\n unchecked {\n ++i;\n }\n }\n }\n}\n" + "contracts/JBGasTokenERC20SplitsPayer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBSplitsPayer.sol';\nimport './interfaces/IJBSplitsStore.sol';\nimport './libraries/JBConstants.sol';\nimport './JBGasTokenERC20ProjectPayer.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\n\n @dev\n Adheres to -\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBGasTokenERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBGasTokenERC20SplitsPayer is JBGasTokenERC20ProjectPayer, ReentrancyGuard, IJBSplitsPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The ID of project for which the default splits are stored. \n */\n uint256 public override defaultSplitsProjectId;\n\n /**\n @notice\n The domain within which the default splits are stored. \n */\n uint256 public override defaultSplitsDomain;\n\n /**\n @notice\n The group within which the default splits are stored. \n */\n uint256 public override defaultSplitsGroup;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBGasTokenERC20ProjectPayer, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n )\n JBGasTokenERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _preferAddToBalance,\n _splitsStore.directory(),\n _owner\n )\n {\n defaultSplitsProjectId = _defaultSplitsProjectId;\n defaultSplitsDomain = _defaultSplitsDomain;\n defaultSplitsGroup = _defaultSplitsGroup;\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default split group using the stored default properties.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override nonReentrant {\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // If there is no leftover amount, nothing left to pay.\n if (_leftoverAmount == 0) return;\n\n // If there's a default project ID, try to pay it.\n if (defaultProjectId != 0)\n if (defaultPreferAddToBalance)\n // Pay the project by adding to its balance if prefered.\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n _leftoverAmount,\n 18, // decimals.\n defaultMemo,\n defaultMetadata\n );\n // Otherwise, issue a payment to the project.\n else\n _pay(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n _leftoverAmount,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n 0, // min returned tokens.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else\n Address.sendValue(\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(tx.origin),\n _leftoverAmount\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the splits in the splits store that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n @param _groupedSplits The split groups to set.\n */\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n JBGroupedSplits[] memory _groupedSplits\n ) external virtual override onlyOwner {\n // Set the splits in the store.\n splitsStore.set(_projectId, _domain, _groupedSplits);\n\n // Set the splits reference.\n setDefaultSplitsReference(_projectId, _domain, _group);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the location of the splits that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n */\n function setDefaultSplitsReference(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) public virtual override onlyOwner {\n // Set the default splits project ID if it's changing.\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\n\n // Set the default splits domain if it's changing.\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\n\n // Set the default splits group if it's changing.\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\n\n emit SetDefaultSplitsReference(_projectId, _domain, _group, msg.sender);\n }\n\n /** \n @notice \n Make a payment to the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Pay any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to pay it.\n if (_projectId != 0) {\n _pay(\n _projectId,\n _token,\n _leftoverAmount,\n _decimals,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? payable(_beneficiary) : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit Pay(\n _projectId,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event. \n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Distribute any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to add to its balance.\n if (_projectId != 0)\n // Add to the project's balance.\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\n\n // Otherwise, send a payment to the beneficiary.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit AddToBalance(\n _projectId,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splitsProjectId The ID of the project to which the splits belong.\n @param _splitsDomain The splits domain to which the group belongs.\n @param _splitsGroup The splits group to pay.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payToSplits(\n uint256 _splitsProjectId,\n uint256 _splitsDomain,\n uint256 _splitsGroup,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Pay the splits.\n leftoverAmount = _payTo(\n splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup),\n _token,\n _amount,\n _decimals,\n _defaultBeneficiary\n );\n emit DistributeToSplitGroup(_splitsProjectId, _splitsDomain, _splitsGroup, msg.sender);\n }\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splits The splits.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payTo(\n JBSplit[] memory _splits,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Set the leftover amount to the initial balance.\n leftoverAmount = _amount;\n\n // Settle between all splits.\n for (uint256 i; i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[i];\n\n // The amount to send towards the split.\n uint256 _splitAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n if (_splitAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n _token,\n _splitAmount,\n _decimals,\n defaultProjectId,\n 0,\n _split\n );\n\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN)\n IERC20(_token).safeApprove(address(_split.allocator), _splitAmount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _splitAmount : 0;\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n if (_split.preferAddToBalance)\n _addToBalanceOf(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n 0,\n _split.preferClaimed,\n defaultMemo,\n defaultMetadata\n );\n } else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : payable(_defaultBeneficiary),\n _splitAmount\n );\n // Or, transfer the ERC20.\n else {\n IERC20(_token).safeTransfer(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n _splitAmount\n );\n }\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _splitAmount;\n }\n\n emit DistributeToSplit(_split, _splitAmount, _defaultBeneficiary, msg.sender);\n\n unchecked {\n ++i;\n }\n }\n }\n}\n" }, "contracts/interfaces/IJBSplitsPayer.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './../structs/JBSplit.sol';\nimport './../structs/JBGroupedSplits.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBSplitsPayer is IERC165 {\n event SetDefaultSplitsReference(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n address caller\n );\n event Pay(\n uint256 indexed projectId,\n address beneficiary,\n address token,\n uint256 amount,\n uint256 decimals,\n uint256 leftoverAmount,\n uint256 minReturnedTokens,\n bool preferClaimedTokens,\n string memo,\n bytes metadata,\n address caller\n );\n\n event AddToBalance(\n uint256 indexed projectId,\n address beneficiary,\n address token,\n uint256 amount,\n uint256 decimals,\n uint256 leftoverAmount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DistributeToSplitGroup(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n address caller\n );\n\n event DistributeToSplit(\n JBSplit split,\n uint256 amount,\n address defaultBeneficiary,\n address caller\n );\n\n function defaultSplitsProjectId() external view returns (uint256);\n\n function defaultSplitsDomain() external view returns (uint256);\n\n function defaultSplitsGroup() external view returns (uint256);\n\n function splitsStore() external view returns (IJBSplitsStore);\n\n function setDefaultSplitsReference(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) external;\n\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n JBGroupedSplits[] memory _splitsGroup\n ) external;\n}\n" }, - "contracts/JBETHERC20ProjectPayer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport './interfaces/IJBProjectPayer.sol';\nimport './libraries/JBTokens.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ERC165: Introspection on interface adherance. \n*/\ncontract JBETHERC20ProjectPayer is Ownable, ERC165, IJBProjectPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // -------------------------- custom errors -------------------------- //\n //*********************************************************************//\n error INCORRECT_DECIMAL_AMOUNT();\n error NO_MSG_VALUE_ALLOWED();\n error TERMINAL_NOT_FOUND();\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice \n A contract storing directories of terminals and controllers for each project.\n */\n IJBDirectory public immutable override directory;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The ID of the project that should be used to forward this contract's received payments.\n */\n uint256 public override defaultProjectId;\n\n /** \n @notice \n The beneficiary that should be used in the payment made when this contract receives payments.\n */\n address payable public override defaultBeneficiary;\n\n /** \n @notice \n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\n */\n bool public override defaultPreferClaimedTokens;\n\n /** \n @notice \n The memo that should be used in the payment made when this contract receives payments.\n */\n string public override defaultMemo;\n\n /** \n @notice \n The metadata that should be used in the payment made when this contract receives payments.\n */\n bytes public override defaultMetadata;\n\n /**\n @notice \n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n bool public override defaultPreferAddToBalance;\n\n //*********************************************************************//\n // ------------------------- public views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) {\n defaultProjectId = _defaultProjectId;\n defaultBeneficiary = _defaultBeneficiary;\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\n defaultMemo = _defaultMemo;\n defaultMetadata = _defaultMetadata;\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n directory = _directory;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default project ID using the stored default properties.\n\n @dev\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override {\n if (defaultPreferAddToBalance)\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.ETH,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n defaultProjectId,\n JBTokens.ETH,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultBeneficiary == address(0) ? tx.origin : defaultBeneficiary,\n 0, // Can't determine expectation of returned tokens ahead of time.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\n\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _beneficiary The address that'll receive the project's tokens. \n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _memo The memo that'll be used. \n @param _metadata The metadata that'll be sent. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external virtual override onlyOwner {\n // Set the default project ID if it has changed.\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\n\n // Set the default beneficiary if it has changed.\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\n\n // Set the default claimed token preference if it has changed.\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\n defaultPreferClaimedTokens = _preferClaimedTokens;\n\n // Set the default memo if it has changed.\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\n defaultMemo = _memo;\n\n // Set the default metadata if it has changed.\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\n defaultMetadata = _metadata;\n\n // Set the add to balance preference if it has changed.\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n\n emit SetDefaultValues(\n _projectId,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata,\n _defaultPreferAddToBalance,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _pay(\n _projectId,\n _token,\n _amount,\n _decimals,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. \n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source and delegate, if provided.\n */\n function _pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.ETH) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\n\n // Send funds to the terminal.\n // If the token is ETH, send it in msg.value.\n _terminal.pay{value: _payableValue}(\n _projectId,\n _amount, // ignored if the token is JBTokens.ETH.\n _token,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.ETH) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\n\n // Add to balance so tokens don't get issued.\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\n }\n}\n" + "contracts/JBGasTokenERC20ProjectPayer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport './interfaces/IJBProjectPayer.sol';\nimport './libraries/JBTokens.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ERC165: Introspection on interface adherance. \n*/\ncontract JBGasTokenERC20ProjectPayer is Ownable, ERC165, IJBProjectPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // -------------------------- custom errors -------------------------- //\n //*********************************************************************//\n error INCORRECT_DECIMAL_AMOUNT();\n error NO_MSG_VALUE_ALLOWED();\n error TERMINAL_NOT_FOUND();\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice \n A contract storing directories of terminals and controllers for each project.\n */\n IJBDirectory public immutable override directory;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The ID of the project that should be used to forward this contract's received payments.\n */\n uint256 public override defaultProjectId;\n\n /** \n @notice \n The beneficiary that should be used in the payment made when this contract receives payments.\n */\n address payable public override defaultBeneficiary;\n\n /** \n @notice \n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\n */\n bool public override defaultPreferClaimedTokens;\n\n /** \n @notice \n The memo that should be used in the payment made when this contract receives payments.\n */\n string public override defaultMemo;\n\n /** \n @notice \n The metadata that should be used in the payment made when this contract receives payments.\n */\n bytes public override defaultMetadata;\n\n /**\n @notice \n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n bool public override defaultPreferAddToBalance;\n\n //*********************************************************************//\n // ------------------------- public views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) {\n defaultProjectId = _defaultProjectId;\n defaultBeneficiary = _defaultBeneficiary;\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\n defaultMemo = _defaultMemo;\n defaultMetadata = _defaultMetadata;\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n directory = _directory;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default project ID using the stored default properties.\n\n @dev\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override {\n if (defaultPreferAddToBalance)\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultBeneficiary == address(0) ? tx.origin : defaultBeneficiary,\n 0, // Can't determine expectation of returned tokens ahead of time.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\n\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _beneficiary The address that'll receive the project's tokens. \n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _memo The memo that'll be used. \n @param _metadata The metadata that'll be sent. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external virtual override onlyOwner {\n // Set the default project ID if it has changed.\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\n\n // Set the default beneficiary if it has changed.\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\n\n // Set the default claimed token preference if it has changed.\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\n defaultPreferClaimedTokens = _preferClaimedTokens;\n\n // Set the default memo if it has changed.\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\n defaultMemo = _memo;\n\n // Set the default metadata if it has changed.\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\n defaultMetadata = _metadata;\n\n // Set the add to balance preference if it has changed.\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n\n emit SetDefaultValues(\n _projectId,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata,\n _defaultPreferAddToBalance,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _pay(\n _projectId,\n _token,\n _amount,\n _decimals,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. \n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source and delegate, if provided.\n */\n function _pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send funds to the terminal.\n // If the token is ETH, send it in msg.value.\n _terminal.pay{value: _payableValue}(\n _projectId,\n _amount, // ignored if the token is JBTokens.GAS_TOKEN.\n _token,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Add to balance so tokens don't get issued.\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\n }\n}\n" }, "contracts/interfaces/IJBProjectPayer.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './IJBDirectory.sol';\n\ninterface IJBProjectPayer is IERC165 {\n event SetDefaultValues(\n uint256 indexed projectId,\n address indexed beneficiary,\n bool preferClaimedTokens,\n string memo,\n bytes metadata,\n bool preferAddToBalance,\n address caller\n );\n\n function directory() external view returns (IJBDirectory);\n\n function defaultProjectId() external view returns (uint256);\n\n function defaultBeneficiary() external view returns (address payable);\n\n function defaultPreferClaimedTokens() external view returns (bool);\n\n function defaultMemo() external view returns (string memory);\n\n function defaultMetadata() external view returns (bytes memory);\n\n function defaultPreferAddToBalance() external view returns (bool);\n\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external;\n\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) external payable;\n\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) external payable;\n\n receive() external payable;\n}\n" }, - "contracts/JBETHERC20SplitsPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './interfaces/IJBETHERC20SplitsPayerDeployer.sol';\nimport './structs/JBSplit.sol';\nimport './structs/JBGroupedSplits.sol';\nimport './JBETHERC20SplitsPayer.sol';\n\n/** \n @notice \n Deploys splits payer contracts.\n\n @dev\n Adheres to -\n IJBETHERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBETHERC20SplitsPayerDeployer is IJBETHERC20SplitsPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @dev\n This contract must have Operator permissions over the SET_SPLITS permission of the specified `_defaultSplitsProjectId`.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplits The splits to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBSplitsPayer splitsPayer) {\n // Use this contract's address as the domain.\n uint256 _domain = uint256(uint160(address(this)));\n\n // Create the random hash using data unique to this instance that'll be used as the storage domain.\n uint256 _group = uint256(keccak256(abi.encodePacked(msg.sender, block.number)));\n\n // Set the splits in the store.\n JBGroupedSplits[] memory _groupedSplits;\n _groupedSplits = new JBGroupedSplits[](1);\n _groupedSplits[0] = JBGroupedSplits(_group, _defaultSplits);\n _splitsStore.set(_defaultSplitsProjectId, _domain, _groupedSplits);\n\n return\n deploySplitsPayer(\n _defaultSplitsProjectId,\n _domain,\n _group,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n }\n\n //*********************************************************************//\n // ---------------------- public transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) public override returns (IJBSplitsPayer splitsPayer) {\n // Deploy the splits payer.\n splitsPayer = new JBETHERC20SplitsPayer(\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeploySplitsPayer(\n splitsPayer,\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner,\n msg.sender\n );\n }\n}\n" + "contracts/JBGasTokenERC20SplitsPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './interfaces/IJBGasTokenERC20SplitsPayerDeployer.sol';\nimport './structs/JBSplit.sol';\nimport './structs/JBGroupedSplits.sol';\nimport './JBGasTokenERC20SplitsPayer.sol';\n\n/** \n @notice \n Deploys splits payer contracts.\n\n @dev\n Adheres to -\n IJBGasTokenERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBGasTokenERC20SplitsPayerDeployer is IJBGasTokenERC20SplitsPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @dev\n This contract must have Operator permissions over the SET_SPLITS permission of the specified `_defaultSplitsProjectId`.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplits The splits to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBSplitsPayer splitsPayer) {\n // Use this contract's address as the domain.\n uint256 _domain = uint256(uint160(address(this)));\n\n // Create the random hash using data unique to this instance that'll be used as the storage domain.\n uint256 _group = uint256(keccak256(abi.encodePacked(msg.sender, block.number)));\n\n // Set the splits in the store.\n JBGroupedSplits[] memory _groupedSplits;\n _groupedSplits = new JBGroupedSplits[](1);\n _groupedSplits[0] = JBGroupedSplits(_group, _defaultSplits);\n _splitsStore.set(_defaultSplitsProjectId, _domain, _groupedSplits);\n\n return\n deploySplitsPayer(\n _defaultSplitsProjectId,\n _domain,\n _group,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n }\n\n //*********************************************************************//\n // ---------------------- public transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) public override returns (IJBSplitsPayer splitsPayer) {\n // Deploy the splits payer.\n splitsPayer = new JBGasTokenERC20SplitsPayer(\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeploySplitsPayer(\n splitsPayer,\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner,\n msg.sender\n );\n }\n}\n" }, - "contracts/interfaces/IJBETHERC20SplitsPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBSplitsPayer.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBETHERC20SplitsPayerDeployer {\n event DeploySplitsPayer(\n IJBSplitsPayer indexed splitsPayer,\n uint256 defaultSplitsProjectId,\n uint256 defaultSplitsDomain,\n uint256 defaultSplitsGroup,\n IJBSplitsStore splitsStore,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n address owner,\n address caller\n );\n\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string calldata _defaultMemo,\n bytes calldata _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n}\n" + "contracts/interfaces/IJBGasTokenERC20SplitsPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBSplitsPayer.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBGasTokenERC20SplitsPayerDeployer {\n event DeploySplitsPayer(\n IJBSplitsPayer indexed splitsPayer,\n uint256 defaultSplitsProjectId,\n uint256 defaultSplitsDomain,\n uint256 defaultSplitsGroup,\n IJBSplitsStore splitsStore,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n address owner,\n address caller\n );\n\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string calldata _defaultMemo,\n bytes calldata _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n}\n" }, "contracts/JBSplitsStore.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './abstract/JBOperatable.sol';\nimport './interfaces/IJBDirectory.sol';\nimport './interfaces/IJBSplitsStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBOperations.sol';\n\n/**\n @notice\n Stores splits for each project.\n\n @dev\n Adheres to -\n IJBSplitsStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\ncontract JBSplitsStore is JBOperatable, IJBSplitsStore {\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_LOCKED_UNTIL();\n error INVALID_PROJECT_ID();\n error INVALID_SPLIT_PERCENT();\n error INVALID_TOTAL_PERCENT();\n error PREVIOUS_LOCKED_SPLITS_NOT_INCLUDED();\n\n //*********************************************************************//\n // --------------------- private stored properties ------------------- //\n //*********************************************************************//\n\n /** \n @notice\n The number of splits currently set for each project ID's configurations.\n\n _projectId The ID of the project to get the split count for.\n _domain An identifier within which the returned splits should be considered active.\n _group The identifying group of the splits.\n */\n mapping(uint256 => mapping(uint256 => mapping(uint256 => uint256))) private _splitCountOf;\n\n /** \n @notice\n Packed data of splits for each project ID's configurations.\n\n _projectId The ID of the project to get packed splits data for.\n _domain An identifier within which the returned splits should be considered active.\n _group The identifying group of the splits.\n _index The indexed order that the split was set at.\n */\n mapping(uint256 => mapping(uint256 => mapping(uint256 => mapping(uint256 => uint256))))\n private _packedSplitParts1Of;\n\n /** \n @notice\n More packed data of splits for each project ID's configurations.\n\n @dev\n This packed data is often 0.\n\n _projectId The ID of the project to get packed splits data for.\n _domain An identifier within which the returned splits should be considered active.\n _group The identifying group of the splits.\n _index The indexed order that the split was set at.\n */\n mapping(uint256 => mapping(uint256 => mapping(uint256 => mapping(uint256 => uint256))))\n private _packedSplitParts2Of;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /** \n @notice \n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /** \n @notice \n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice \n Get all splits for the specified project ID, within the specified domain, for the specified group.\n\n @param _projectId The ID of the project to get splits for.\n @param _domain An identifier within which the returned splits should be considered active.\n @param _group The identifying group of the splits.\n\n @return An array of all splits for the project.\n*/\n function splitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) external view override returns (JBSplit[] memory) {\n return _getStructsFor(_projectId, _domain, _group);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n */\n constructor(\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory\n ) JBOperatable(_operatorStore) {\n projects = _projects;\n directory = _directory;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets a project's splits.\n\n @dev\n Only the owner or operator of a project, or the current controller contract of the project, can set its splits.\n\n @dev\n The new splits must include any currently set splits that are locked.\n\n @param _projectId The ID of the project for which splits are being added.\n @param _domain An identifier within which the splits should be considered active.\n @param _groupedSplits An array of splits to set for any number of groups. \n */\n function set(\n uint256 _projectId,\n uint256 _domain,\n JBGroupedSplits[] calldata _groupedSplits\n )\n external\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.SET_SPLITS,\n address(directory.controllerOf(_projectId)) == msg.sender\n )\n {\n // Push array length in stack\n uint256 _groupedSplitsLength = _groupedSplits.length;\n\n // Set each grouped splits.\n for (uint256 _i; _i < _groupedSplitsLength; ) {\n // Get a reference to the grouped split being iterated on.\n JBGroupedSplits memory _groupedSplit = _groupedSplits[_i];\n\n // Set the splits for the group.\n _set(_projectId, _domain, _groupedSplit.group, _groupedSplit.splits);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets a project's splits.\n\n @dev\n The new splits must include any currently set splits that are locked.\n\n @param _projectId The ID of the project for which splits are being added.\n @param _domain An identifier within which the splits should be considered active.\n @param _group An identifier between of splits being set. All splits within this _group must add up to within 100%.\n @param _splits The splits to set.\n */\n function _set(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n JBSplit[] memory _splits\n ) internal {\n // Get a reference to the project's current splits.\n JBSplit[] memory _currentSplits = _getStructsFor(_projectId, _domain, _group);\n\n // Keep a reference to the number of splits.\n uint256 _currentSplitsLength = _currentSplits.length;\n\n // Check to see if all locked splits are included.\n for (uint256 _i; _i < _currentSplitsLength; ) {\n // If not locked, continue.\n if (\n block.timestamp < _currentSplits[_i].lockedUntil &&\n !_includesLocked(_splits, _currentSplits[_i])\n ) revert PREVIOUS_LOCKED_SPLITS_NOT_INCLUDED();\n\n unchecked {\n ++_i;\n }\n }\n\n // Add up all the percents to make sure they cumulatively are under 100%.\n uint256 _percentTotal;\n\n // Keep a reference to the number of splits.\n uint256 _splitsLength = _splits.length;\n\n for (uint256 _i; _i < _splitsLength; ) {\n // The percent should be greater than 0.\n if (_splits[_i].percent == 0) revert INVALID_SPLIT_PERCENT();\n\n // ProjectId should be within a uint56\n if (_splits[_i].projectId > type(uint56).max) revert INVALID_PROJECT_ID();\n\n // Add to the total percents.\n _percentTotal = _percentTotal + _splits[_i].percent;\n\n // Validate the total does not exceed the expected value.\n if (_percentTotal > JBConstants.SPLITS_TOTAL_PERCENT) revert INVALID_TOTAL_PERCENT();\n\n uint256 _packedSplitParts1;\n\n // prefer claimed in bit 0.\n if (_splits[_i].preferClaimed) _packedSplitParts1 = 1;\n // prefer add to balance in bit 1.\n if (_splits[_i].preferAddToBalance) _packedSplitParts1 |= 1 << 1;\n // percent in bits 2-33.\n _packedSplitParts1 |= _splits[_i].percent << 2;\n // projectId in bits 32-89.\n _packedSplitParts1 |= _splits[_i].projectId << 34;\n // beneficiary in bits 90-249.\n _packedSplitParts1 |= uint256(uint160(address(_splits[_i].beneficiary))) << 90;\n\n // Store the first split part.\n _packedSplitParts1Of[_projectId][_domain][_group][_i] = _packedSplitParts1;\n\n // If there's data to store in the second packed split part, pack and store.\n if (_splits[_i].lockedUntil > 0 || _splits[_i].allocator != IJBSplitAllocator(address(0))) {\n // Locked until should be within a uint48\n if (_splits[_i].lockedUntil > type(uint48).max) revert INVALID_LOCKED_UNTIL();\n\n // lockedUntil in bits 0-47.\n uint256 _packedSplitParts2 = uint48(_splits[_i].lockedUntil);\n // allocator in bits 48-207.\n _packedSplitParts2 |= uint256(uint160(address(_splits[_i].allocator))) << 48;\n\n // Store the second split part.\n _packedSplitParts2Of[_projectId][_domain][_group][_i] = _packedSplitParts2;\n\n // Otherwise if there's a value stored in the indexed position, delete it.\n } else if (_packedSplitParts2Of[_projectId][_domain][_group][_i] > 0)\n delete _packedSplitParts2Of[_projectId][_domain][_group][_i];\n\n emit SetSplit(_projectId, _domain, _group, _splits[_i], msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n\n // Set the new length of the splits.\n _splitCountOf[_projectId][_domain][_group] = _splitsLength;\n }\n\n /** \n @notice\n A flag indiciating if the provided splits array includes the locked split. \n\n @param _splits The array of splits to check within.\n @param _lockedSplit The locked split.\n\n @return A flag indicating if the `_lockedSplit` is contained in the `_splits`.\n */\n function _includesLocked(JBSplit[] memory _splits, JBSplit memory _lockedSplit)\n private\n pure\n returns (bool)\n {\n // Keep a reference to the number of splits.\n uint256 _numberOfSplits = _splits.length;\n\n for (uint256 _i; _i < _numberOfSplits; ) {\n // Check for sameness.\n if (\n _splits[_i].percent == _lockedSplit.percent &&\n _splits[_i].beneficiary == _lockedSplit.beneficiary &&\n _splits[_i].allocator == _lockedSplit.allocator &&\n _splits[_i].projectId == _lockedSplit.projectId &&\n _splits[_i].preferClaimed == _lockedSplit.preferClaimed &&\n _splits[_i].preferAddToBalance == _lockedSplit.preferAddToBalance &&\n // Allow lock extention.\n _splits[_i].lockedUntil >= _lockedSplit.lockedUntil\n ) return true;\n\n unchecked {\n ++_i;\n }\n }\n\n return false;\n }\n\n /**\n @notice \n Unpack splits' packed stored values into easy-to-work-with split structs.\n\n @param _projectId The ID of the project to which the split belongs.\n @param _domain The identifier within which the returned splits should be considered active.\n @param _group The identifying group of the splits.\n\n @return splits The split structs.\n */\n function _getStructsFor(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) private view returns (JBSplit[] memory) {\n // Get a reference to the number of splits that need to be added to the returned array.\n uint256 _splitCount = _splitCountOf[_projectId][_domain][_group];\n\n // Initialize an array to be returned that has the set length.\n JBSplit[] memory _splits = new JBSplit[](_splitCount);\n\n // Loop through each split and unpack the values into structs.\n for (uint256 _i; _i < _splitCount; ) {\n // Get a reference to the fist packed data.\n uint256 _packedSplitPart1 = _packedSplitParts1Of[_projectId][_domain][_group][_i];\n\n // Populate the split struct.\n JBSplit memory _split;\n\n // prefer claimed in bit 0.\n _split.preferClaimed = _packedSplitPart1 & 1 == 1;\n // prefer add to balance in bit 1.\n _split.preferAddToBalance = (_packedSplitPart1 >> 1) & 1 == 1;\n // percent in bits 2-33.\n _split.percent = uint256(uint32(_packedSplitPart1 >> 2));\n // projectId in bits 32-89.\n _split.projectId = uint256(uint56(_packedSplitPart1 >> 34));\n // beneficiary in bits 90-249.\n _split.beneficiary = payable(address(uint160(_packedSplitPart1 >> 90)));\n\n // Get a reference to the second packed data.\n uint256 _packedSplitPart2 = _packedSplitParts2Of[_projectId][_domain][_group][_i];\n\n // If there's anything in it, unpack.\n if (_packedSplitPart2 > 0) {\n // lockedUntil in bits 0-47.\n _split.lockedUntil = uint256(uint48(_packedSplitPart2));\n // allocator in bits 48-207.\n _split.allocator = IJBSplitAllocator(address(uint160(_packedSplitPart2 >> 48)));\n }\n\n // Add the split to the value being returned.\n _splits[_i] = _split;\n\n unchecked {\n ++_i;\n }\n }\n\n return _splits;\n }\n}\n" @@ -322,11 +322,11 @@ "contracts/interfaces/IJBTerminalUtility.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBDirectory.sol';\n\ninterface IJBPaymentTerminalUtility {\n function directory() external view returns (IJBDirectory);\n}\n" }, - "contracts/JBETHERC20ProjectPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './interfaces/IJBETHERC20ProjectPayerDeployer.sol';\nimport './JBETHERC20ProjectPayer.sol';\n\n/** \n @notice \n Deploys project payer contracts.\n\n @dev\n Adheres to -\n IJBETHERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBETHERC20ProjectPayerDeployer is IJBETHERC20ProjectPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new project payer contract.\n\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the project payer contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the project payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the project payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the project payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the project payer.\n\n @return projectPayer The project payer contract.\n */\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external override returns (IJBProjectPayer projectPayer) {\n // Deploy the project payer.\n projectPayer = new JBETHERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner\n );\n\n emit DeployProjectPayer(\n projectPayer,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner,\n msg.sender\n );\n }\n}\n" + "contracts/JBGasTokenERC20ProjectPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './interfaces/IJBGasTokenERC20ProjectPayerDeployer.sol';\nimport './JBGasTokenERC20ProjectPayer.sol';\n\n/** \n @notice \n Deploys project payer contracts.\n\n @dev\n Adheres to -\n IJBGasTokenERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBGasTokenERC20ProjectPayerDeployer is IJBGasTokenERC20ProjectPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new project payer contract.\n\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the project payer contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the project payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the project payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the project payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the project payer.\n\n @return projectPayer The project payer contract.\n */\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external override returns (IJBProjectPayer projectPayer) {\n // Deploy the project payer.\n projectPayer = new JBGasTokenERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner\n );\n\n emit DeployProjectPayer(\n projectPayer,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner,\n msg.sender\n );\n }\n}\n" }, - "contracts/interfaces/IJBETHERC20ProjectPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBDirectory.sol';\nimport './IJBProjectPayer.sol';\n\ninterface IJBETHERC20ProjectPayerDeployer {\n event DeployProjectPayer(\n IJBProjectPayer indexed projectPayer,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n IJBDirectory directory,\n address owner,\n address caller\n );\n\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external returns (IJBProjectPayer projectPayer);\n}\n" + "contracts/interfaces/IJBGasTokenERC20ProjectPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBDirectory.sol';\nimport './IJBProjectPayer.sol';\n\ninterface IJBGasTokenERC20ProjectPayerDeployer {\n event DeployProjectPayer(\n IJBProjectPayer indexed projectPayer,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n IJBDirectory directory,\n address owner,\n address caller\n );\n\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external returns (IJBProjectPayer projectPayer);\n}\n" }, "contracts/JBReconfigurationBufferBallot.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport './interfaces/IJBFundingCycleBallot.sol';\nimport './structs/JBFundingCycle.sol';\n\n/** \n @notice \n Manages approving funding cycle reconfigurations automatically after a buffer period.\n\n @dev\n Adheres to -\n IJBFundingCycleBallot: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ERC165: Introspection on interface adherance. \n*/\ncontract JBReconfigurationBufferBallot is ERC165, IJBFundingCycleBallot {\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice \n The number of seconds that must pass for a funding cycle reconfiguration to become either `Approved` or `Failed`.\n */\n uint256 public immutable override duration;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice \n The approval state of a particular funding cycle.\n\n @param _projectId The ID of the project to which the funding cycle being checked belongs.\n @param _configured The configuration of the funding cycle to check the state of.\n @param _start The start timestamp of the funding cycle to check the state of.\n\n @return The state of the provided ballot. \n */\n function stateOf(\n uint256 _projectId,\n uint256 _configured,\n uint256 _start\n ) public view override returns (JBBallotState) {\n _projectId; // Prevents unused var compiler and natspec complaints.\n\n // If the provided configured timestamp is after the start timestamp, the ballot is Failed.\n if (_configured > _start) return JBBallotState.Failed;\n\n unchecked {\n // If there was sufficient time between configuration and the start of the cycle, it is approved. Otherwise, it is failed.\n return (_start - _configured < duration) ? JBBallotState.Failed : JBBallotState.Approved;\n }\n }\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBFundingCycleBallot).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _duration The number of seconds to wait until a reconfiguration can be either `Approved` or `Failed`.\n */\n constructor(uint256 _duration) {\n duration = _duration;\n }\n}\n" diff --git a/deployments/mainnet/solcInputs/e74c031977287ddc5a2bef1107c54b87.json b/deployments/mainnet/solcInputs/e74c031977287ddc5a2bef1107c54b87.json index 9ffa522cc..92d34a363 100644 --- a/deployments/mainnet/solcInputs/e74c031977287ddc5a2bef1107c54b87.json +++ b/deployments/mainnet/solcInputs/e74c031977287ddc5a2bef1107c54b87.json @@ -155,7 +155,7 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './JBSplit.sol';\n\n/** \n @member token The token being sent to the split allocator.\n @member amount The amount being sent to the split allocator, as a fixed point number.\n @member decimals The number of decimals in the amount.\n @member projectId The project to which the split belongs.\n @member group The group to which the split belongs.\n @member split The split that caused the allocation.\n*/\nstruct JBSplitAllocationData {\n address token;\n uint256 amount;\n uint256 decimals;\n uint256 projectId;\n uint256 group;\n JBSplit split;\n}\n" }, "contracts/JBSingleTokenPaymentTerminalStore3_1.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController3_1.sol';\nimport './interfaces/IJBFundingCycleDataSource.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './structs/JBPayDelegateAllocation.sol';\nimport './structs/JBPayParamsData.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n\n @dev\n This Store expects a project's controller to be an IJBController3_1. This is the only difference between this version and the original.\n*/\ncontract JBSingleTokenPaymentTerminalStore3_1 is\n ReentrancyGuard,\n IJBSingleTokenPaymentTerminalStore\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId);\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n JBPayDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .payParams(_data);\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\n {\n // Keep a reference to the amount that should be added to the project's balance.\n uint256 _balanceDiff = _amount.value;\n\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\n if (delegateAllocations.length != 0) {\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0) {\n // Can't delegate more than was paid.\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\n\n // Decrement the total amount being added to the balance.\n _balanceDiff = _balanceDiff - _delegatedAmount;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Add the correct balance difference to the token balance of the project.\n if (_balanceDiff != 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _balanceDiff;\n }\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId);\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow != 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\n {\n // Get a reference to the ballot state.\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\n\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n _state == JBBallotState.Active\n ? fundingCycle.ballotRedemptionRate()\n : fundingCycle.redemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\n fundingCycle.dataSource()\n ).redeemParams(_data);\n }\n } else {\n memo = _memo;\n }\n }\n\n // Keep a reference to the amount that should be subtracted from the project's balance.\n uint256 _balanceDiff = reclaimAmount;\n\n if (delegateAllocations.length != 0) {\n // Validate all delegated amounts.\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0)\n // Increment the total amount being subtracted from the balance.\n _balanceDiff = _balanceDiff + _delegatedAmount;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (_balanceDiff != 0) {\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n _balanceDiff;\n }\n }\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n unchecked {\n return\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i; _i < _terminals.length; ) {\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n unchecked {\n ++_i;\n }\n }\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.ETH\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.ETH, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController3_1.sol';\nimport './interfaces/IJBFundingCycleDataSource.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './structs/JBPayDelegateAllocation.sol';\nimport './structs/JBPayParamsData.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n\n @dev\n This Store expects a project's controller to be an IJBController3_1. This is the only difference between this version and the original.\n*/\ncontract JBSingleTokenPaymentTerminalStore3_1 is\n ReentrancyGuard,\n IJBSingleTokenPaymentTerminalStore\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId);\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n JBPayDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .payParams(_data);\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\n {\n // Keep a reference to the amount that should be added to the project's balance.\n uint256 _balanceDiff = _amount.value;\n\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\n if (delegateAllocations.length != 0) {\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0) {\n // Can't delegate more than was paid.\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\n\n // Decrement the total amount being added to the balance.\n _balanceDiff = _balanceDiff - _delegatedAmount;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Add the correct balance difference to the token balance of the project.\n if (_balanceDiff != 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _balanceDiff;\n }\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId);\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow != 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\n {\n // Get a reference to the ballot state.\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\n\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n _state == JBBallotState.Active\n ? fundingCycle.ballotRedemptionRate()\n : fundingCycle.redemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\n fundingCycle.dataSource()\n ).redeemParams(_data);\n }\n } else {\n memo = _memo;\n }\n }\n\n // Keep a reference to the amount that should be subtracted from the project's balance.\n uint256 _balanceDiff = reclaimAmount;\n\n if (delegateAllocations.length != 0) {\n // Validate all delegated amounts.\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0)\n // Increment the total amount being subtracted from the balance.\n _balanceDiff = _balanceDiff + _delegatedAmount;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (_balanceDiff != 0) {\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n _balanceDiff;\n }\n }\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n unchecked {\n return\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i; _i < _terminals.length; ) {\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n unchecked {\n ++_i;\n }\n }\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.GAS_CURRENCY\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.GAS_CURRENCY, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" }, "@openzeppelin/contracts/security/ReentrancyGuard.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n constructor() {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n // On the first call to nonReentrant, _notEntered will be true\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n\n _;\n\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n}\n" @@ -215,7 +215,7 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IJBPriceFeed {\n function currentPrice(uint256 _targetDecimals) external view returns (uint256);\n}\n" }, "contracts/JBSingleTokenPaymentTerminalStore.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController.sol';\nimport './interfaces/IJBFundingCycleDataSource.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './structs/JBPayDelegateAllocation.sol';\nimport './structs/JBPayParamsData.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBSingleTokenPaymentTerminalStore is ReentrancyGuard, IJBSingleTokenPaymentTerminalStore {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n JBPayDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .payParams(_data);\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\n {\n // Keep a reference to the amount that should be added to the project's balance.\n uint256 _balanceDiff = _amount.value;\n\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\n if (delegateAllocations.length != 0) {\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0) {\n // Can't delegate more than was paid.\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\n\n // Decrement the total amount being added to the balance.\n _balanceDiff = _balanceDiff - _delegatedAmount;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Add the correct balance difference to the token balance of the project.\n if (_balanceDiff != 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _balanceDiff;\n }\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\n _projectId,\n fundingCycle.reservedRate()\n );\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow != 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\n {\n // Get a reference to the ballot state.\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\n\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n _state == JBBallotState.Active\n ? fundingCycle.ballotRedemptionRate()\n : fundingCycle.redemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\n fundingCycle.dataSource()\n ).redeemParams(_data);\n }\n } else {\n memo = _memo;\n }\n }\n\n // Keep a reference to the amount that should be subtracted from the project's balance.\n uint256 _balanceDiff = reclaimAmount;\n\n if (delegateAllocations.length != 0) {\n // Validate all delegated amounts.\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0)\n // Increment the total amount being subtracted from the balance.\n _balanceDiff = _balanceDiff + _delegatedAmount;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (_balanceDiff != 0) {\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n _balanceDiff;\n }\n }\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n unchecked {\n return\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i; _i < _terminals.length; ) {\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n unchecked {\n ++_i;\n }\n }\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.ETH\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.ETH, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController.sol';\nimport './interfaces/IJBFundingCycleDataSource.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './structs/JBPayDelegateAllocation.sol';\nimport './structs/JBPayParamsData.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBSingleTokenPaymentTerminalStore is ReentrancyGuard, IJBSingleTokenPaymentTerminalStore {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n JBPayDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .payParams(_data);\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\n {\n // Keep a reference to the amount that should be added to the project's balance.\n uint256 _balanceDiff = _amount.value;\n\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\n if (delegateAllocations.length != 0) {\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0) {\n // Can't delegate more than was paid.\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\n\n // Decrement the total amount being added to the balance.\n _balanceDiff = _balanceDiff - _delegatedAmount;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Add the correct balance difference to the token balance of the project.\n if (_balanceDiff != 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _balanceDiff;\n }\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\n _projectId,\n fundingCycle.reservedRate()\n );\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow != 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\n {\n // Get a reference to the ballot state.\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\n\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n _state == JBBallotState.Active\n ? fundingCycle.ballotRedemptionRate()\n : fundingCycle.redemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\n fundingCycle.dataSource()\n ).redeemParams(_data);\n }\n } else {\n memo = _memo;\n }\n }\n\n // Keep a reference to the amount that should be subtracted from the project's balance.\n uint256 _balanceDiff = reclaimAmount;\n\n if (delegateAllocations.length != 0) {\n // Validate all delegated amounts.\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0)\n // Increment the total amount being subtracted from the balance.\n _balanceDiff = _balanceDiff + _delegatedAmount;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (_balanceDiff != 0) {\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n _balanceDiff;\n }\n }\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n unchecked {\n return\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i; _i < _terminals.length; ) {\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n unchecked {\n ++_i;\n }\n }\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.GAS_CURRENCY\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.GAS_CURRENCY, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" }, "contracts/interfaces/IJBController.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './../structs/JBFundAccessConstraints.sol';\nimport './../structs/JBFundingCycleData.sol';\nimport './../structs/JBFundingCycleMetadata.sol';\nimport './../structs/JBGroupedSplits.sol';\nimport './../structs/JBProjectMetadata.sol';\nimport './IJBDirectory.sol';\nimport './IJBFundingCycleStore.sol';\nimport './IJBMigratable.sol';\nimport './IJBPaymentTerminal.sol';\nimport './IJBSplitsStore.sol';\nimport './IJBTokenStore.sol';\n\ninterface IJBController is IERC165 {\n event LaunchProject(uint256 configuration, uint256 projectId, string memo, address caller);\n\n event LaunchFundingCycles(uint256 configuration, uint256 projectId, string memo, address caller);\n\n event ReconfigureFundingCycles(\n uint256 configuration,\n uint256 projectId,\n string memo,\n address caller\n );\n\n event SetFundAccessConstraints(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n JBFundAccessConstraints constraints,\n address caller\n );\n\n event DistributeReservedTokens(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address beneficiary,\n uint256 tokenCount,\n uint256 beneficiaryTokenCount,\n string memo,\n address caller\n );\n\n event DistributeToReservedTokenSplit(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n JBSplit split,\n uint256 tokenCount,\n address caller\n );\n\n event MintTokens(\n address indexed beneficiary,\n uint256 indexed projectId,\n uint256 tokenCount,\n uint256 beneficiaryTokenCount,\n string memo,\n uint256 reservedRate,\n address caller\n );\n\n event BurnTokens(\n address indexed holder,\n uint256 indexed projectId,\n uint256 tokenCount,\n string memo,\n address caller\n );\n\n event Migrate(uint256 indexed projectId, IJBMigratable to, address caller);\n\n event PrepMigration(uint256 indexed projectId, address from, address caller);\n\n function projects() external view returns (IJBProjects);\n\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\n\n function tokenStore() external view returns (IJBTokenStore);\n\n function splitsStore() external view returns (IJBSplitsStore);\n\n function directory() external view returns (IJBDirectory);\n\n function reservedTokenBalanceOf(uint256 _projectId, uint256 _reservedRate)\n external\n view\n returns (uint256);\n\n function distributionLimitOf(\n uint256 _projectId,\n uint256 _configuration,\n IJBPaymentTerminal _terminal,\n address _token\n ) external view returns (uint256 distributionLimit, uint256 distributionLimitCurrency);\n\n function overflowAllowanceOf(\n uint256 _projectId,\n uint256 _configuration,\n IJBPaymentTerminal _terminal,\n address _token\n ) external view returns (uint256 overflowAllowance, uint256 overflowAllowanceCurrency);\n\n function totalOutstandingTokensOf(uint256 _projectId, uint256 _reservedRate)\n external\n view\n returns (uint256);\n\n function getFundingCycleOf(uint256 _projectId, uint256 _configuration)\n external\n view\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\n\n function latestConfiguredFundingCycleOf(uint256 _projectId)\n external\n view\n returns (\n JBFundingCycle memory,\n JBFundingCycleMetadata memory metadata,\n JBBallotState\n );\n\n function currentFundingCycleOf(uint256 _projectId)\n external\n view\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\n\n function queuedFundingCycleOf(uint256 _projectId)\n external\n view\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\n\n function launchProjectFor(\n address _owner,\n JBProjectMetadata calldata _projectMetadata,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] memory _groupedSplits,\n JBFundAccessConstraints[] memory _fundAccessConstraints,\n IJBPaymentTerminal[] memory _terminals,\n string calldata _memo\n ) external returns (uint256 projectId);\n\n function launchFundingCyclesFor(\n uint256 _projectId,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] memory _groupedSplits,\n JBFundAccessConstraints[] memory _fundAccessConstraints,\n IJBPaymentTerminal[] memory _terminals,\n string calldata _memo\n ) external returns (uint256 configuration);\n\n function reconfigureFundingCyclesOf(\n uint256 _projectId,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] memory _groupedSplits,\n JBFundAccessConstraints[] memory _fundAccessConstraints,\n string calldata _memo\n ) external returns (uint256);\n\n function mintTokensOf(\n uint256 _projectId,\n uint256 _tokenCount,\n address _beneficiary,\n string calldata _memo,\n bool _preferClaimedTokens,\n bool _useReservedRate\n ) external returns (uint256 beneficiaryTokenCount);\n\n function burnTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string calldata _memo,\n bool _preferClaimedTokens\n ) external;\n\n function distributeReservedTokensOf(uint256 _projectId, string memory _memo)\n external\n returns (uint256);\n\n function migrate(uint256 _projectId, IJBMigratable _to) external;\n}\n" @@ -230,13 +230,13 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nlibrary JBSplitsGroups {\n uint256 public constant ETH_PAYOUT = 1;\n uint256 public constant RESERVED_TOKENS = 2;\n}\n" }, "contracts/JBETHPaymentTerminal.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\nimport './libraries/JBSplitsGroups.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return address(this).balance;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n JBTokens.ETH,\n 18, // 18 decimals.\n JBCurrencies.ETH,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\nimport './libraries/JBSplitsGroups.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return address(this).balance;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n JBTokens.GAS_TOKEN,\n 18, // 18 decimals.\n JBCurrencies.GAS_CURRENCY,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n}\n" }, "@openzeppelin/contracts/utils/Address.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" }, "contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBPayDelegateAllocation.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal is\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n IJBPayoutRedemptionPaymentTerminal\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n @dev\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.ETH)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.ETH, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance.\n */\n function _balance() internal view virtual returns (uint256);\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.ETH) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual {\n _from; // Prevents unused var compiler and natspec complaints.\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\n {\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\n\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _forwardedAmount,\n _beneficiary,\n _memo,\n _metadata\n );\n\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\n\n emit DelegateDidRedeem(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n }\n\n // Take the fee.\n _fee = _feeEligibleDistributionAmount != 0\n ? _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n )\n : 0;\n\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\n if (_leftoverDistributionAmount != 0) {\n // Subtract the fee from the net leftover amount.\n netLeftoverDistributionAmount =\n _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n\n // Transfer the amount to the project owner.\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n // The total percentage available to split\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = _split.percent == leftoverPercentage\n ? leftoverAmount\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\n\n // Decrement the leftover percentage.\n leftoverPercentage -= _split.percent;\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount;\n\n if (_payoutAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\n isFeelessAddress[address(_split.allocator)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n _netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n // If this terminal's token is ETH, send it in msg.value.\n _split.allocator.allocate{value: token == JBTokens.ETH ? _netPayoutAmount : 0}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // Save gas if this contract is being used as the terminal.\n if (_terminal == this) {\n // This distribution does not incur a fee.\n _netPayoutAmount = _payoutAmount;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\n else\n _pay(\n _netPayoutAmount,\n address(this),\n _split.projectId,\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n } else {\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_terminal)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _netPayoutAmount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _terminal.addToBalanceOf{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n '',\n _projectMetadata\n );\n else\n _terminal.pay{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n }\n } else {\n // Keep a reference to the beneficiary.\n address payable _beneficiary = _split.beneficiary != address(0)\n ? _split.beneficiary\n : payable(msg.sender);\n\n // If there's a full discount, this distribution is not eligible for a fee.\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(address(this), _beneficiary, _netPayoutAmount);\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n */\n function _processFee(uint256 _amount, address _beneficiary) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\n\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\n if (_terminal == this)\n _pay(\n _amount,\n address(this),\n _FEE_BENEFICIARY_PROJECT_ID,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the local pay call.\n else {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _amount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _amount : 0;\n\n // Send the payment.\n _terminal.pay{value: _payableValue}(\n _FEE_BENEFICIARY_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the external pay call of the correct terminal.\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\n {\n JBPayDelegateAllocation[] memory _delegateAllocations;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n _forwardedAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n // Get a reference to the number of delegates to allocate to.\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\n\n emit DelegateDidPay(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n unchecked {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\n IJBPaymentTerminal(address(0))\n ) return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge != IJBFeeGauge(address(0)))\n // If the guage reverts, keep the discount at 0.\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n // If the fee discount is greater than the max, we ignore the return value\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\n } catch {\n return 0;\n }\n\n return 0;\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBPayDelegateAllocation.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal is\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n IJBPayoutRedemptionPaymentTerminal\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n @dev\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.GAS_CURRENCY)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.GAS_CURRENCY, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance.\n */\n function _balance() internal view virtual returns (uint256);\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.GAS_TOKEN) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual {\n _from; // Prevents unused var compiler and natspec complaints.\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\n {\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\n\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _forwardedAmount,\n _beneficiary,\n _memo,\n _metadata\n );\n\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\n\n emit DelegateDidRedeem(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n }\n\n // Take the fee.\n _fee = _feeEligibleDistributionAmount != 0\n ? _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n )\n : 0;\n\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\n if (_leftoverDistributionAmount != 0) {\n // Subtract the fee from the net leftover amount.\n netLeftoverDistributionAmount =\n _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n\n // Transfer the amount to the project owner.\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n // The total percentage available to split\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = _split.percent == leftoverPercentage\n ? leftoverAmount\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\n\n // Decrement the leftover percentage.\n leftoverPercentage -= _split.percent;\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount;\n\n if (_payoutAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\n isFeelessAddress[address(_split.allocator)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n _netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n // If this terminal's token is ETH, send it in msg.value.\n _split.allocator.allocate{value: token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // Save gas if this contract is being used as the terminal.\n if (_terminal == this) {\n // This distribution does not incur a fee.\n _netPayoutAmount = _payoutAmount;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\n else\n _pay(\n _netPayoutAmount,\n address(this),\n _split.projectId,\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n } else {\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_terminal)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _terminal.addToBalanceOf{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n '',\n _projectMetadata\n );\n else\n _terminal.pay{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n }\n } else {\n // Keep a reference to the beneficiary.\n address payable _beneficiary = _split.beneficiary != address(0)\n ? _split.beneficiary\n : payable(msg.sender);\n\n // If there's a full discount, this distribution is not eligible for a fee.\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(address(this), _beneficiary, _netPayoutAmount);\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n */\n function _processFee(uint256 _amount, address _beneficiary) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\n\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\n if (_terminal == this)\n _pay(\n _amount,\n address(this),\n _FEE_BENEFICIARY_PROJECT_ID,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the local pay call.\n else {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _amount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send the payment.\n _terminal.pay{value: _payableValue}(\n _FEE_BENEFICIARY_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the external pay call of the correct terminal.\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\n {\n JBPayDelegateAllocation[] memory _delegateAllocations;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n _forwardedAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n // Get a reference to the number of delegates to allocate to.\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\n\n emit DelegateDidPay(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n unchecked {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\n IJBPaymentTerminal(address(0))\n ) return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge != IJBFeeGauge(address(0)))\n // If the guage reverts, keep the discount at 0.\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n // If the fee discount is greater than the max, we ignore the return value\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\n } catch {\n return 0;\n }\n\n return 0;\n }\n}\n" }, "contracts/interfaces/IJBPayoutRedemptionPaymentTerminal.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './../structs/JBFee.sol';\nimport './IJBAllowanceTerminal.sol';\nimport './IJBDirectory.sol';\nimport './IJBFeeGauge.sol';\nimport './IJBPayDelegate.sol';\nimport './IJBPaymentTerminal.sol';\nimport './IJBPayoutTerminal.sol';\nimport './IJBPrices.sol';\nimport './IJBProjects.sol';\nimport './IJBRedemptionDelegate.sol';\nimport './IJBRedemptionTerminal.sol';\nimport './IJBSingleTokenPaymentTerminalStore.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBPayoutRedemptionPaymentTerminal is\n IJBPaymentTerminal,\n IJBPayoutTerminal,\n IJBAllowanceTerminal,\n IJBRedemptionTerminal\n{\n event AddToBalance(\n uint256 indexed projectId,\n uint256 amount,\n uint256 refundedFees,\n string memo,\n bytes metadata,\n address caller\n );\n\n event Migrate(\n uint256 indexed projectId,\n IJBPaymentTerminal indexed to,\n uint256 amount,\n address caller\n );\n\n event DistributePayouts(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address beneficiary,\n uint256 amount,\n uint256 distributedAmount,\n uint256 fee,\n uint256 beneficiaryDistributionAmount,\n string memo,\n address caller\n );\n\n event UseAllowance(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address beneficiary,\n uint256 amount,\n uint256 distributedAmount,\n uint256 netDistributedamount,\n string memo,\n address caller\n );\n\n event HoldFee(\n uint256 indexed projectId,\n uint256 indexed amount,\n uint256 indexed fee,\n uint256 feeDiscount,\n address beneficiary,\n address caller\n );\n\n event ProcessFee(\n uint256 indexed projectId,\n uint256 indexed amount,\n bool indexed wasHeld,\n address beneficiary,\n address caller\n );\n\n event RefundHeldFees(\n uint256 indexed projectId,\n uint256 indexed amount,\n uint256 indexed refundedFees,\n uint256 leftoverAmount,\n address caller\n );\n\n event Pay(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address payer,\n address beneficiary,\n uint256 amount,\n uint256 beneficiaryTokenCount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DelegateDidPay(\n IJBPayDelegate indexed delegate,\n JBDidPayData data,\n uint256 delegatedAmount,\n address caller\n );\n\n event RedeemTokens(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address holder,\n address beneficiary,\n uint256 tokenCount,\n uint256 reclaimedAmount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DelegateDidRedeem(\n IJBRedemptionDelegate indexed delegate,\n JBDidRedeemData data,\n uint256 delegatedAmount,\n address caller\n );\n\n event DistributeToPayoutSplit(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n JBSplit split,\n uint256 amount,\n address caller\n );\n\n event SetFee(uint256 fee, address caller);\n\n event SetFeeGauge(IJBFeeGauge indexed feeGauge, address caller);\n\n event SetFeelessAddress(address indexed addrs, bool indexed flag, address caller);\n\n function projects() external view returns (IJBProjects);\n\n function splitsStore() external view returns (IJBSplitsStore);\n\n function directory() external view returns (IJBDirectory);\n\n function prices() external view returns (IJBPrices);\n\n function store() external view returns (IJBSingleTokenPaymentTerminalStore);\n\n function baseWeightCurrency() external view returns (uint256);\n\n function payoutSplitsGroup() external view returns (uint256);\n\n function heldFeesOf(uint256 _projectId) external view returns (JBFee[] memory);\n\n function fee() external view returns (uint256);\n\n function feeGauge() external view returns (IJBFeeGauge);\n\n function isFeelessAddress(address _contract) external view returns (bool);\n\n function migrate(uint256 _projectId, IJBPaymentTerminal _to) external returns (uint256 balance);\n\n function processFees(uint256 _projectId) external;\n\n function setFee(uint256 _fee) external;\n\n function setFeeGauge(IJBFeeGauge _feeGauge) external;\n\n function setFeelessAddress(address _contract, bool _flag) external;\n}\n" @@ -268,23 +268,23 @@ "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n function safeTransfer(\n IERC20 token,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(\n IERC20 token,\n address from,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n uint256 newAllowance = token.allowance(address(this), spender) + value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n uint256 newAllowance = oldAllowance - value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) {\n // Return data is optional\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" }, - "contracts/JBETHERC20SplitsPayer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBSplitsPayer.sol';\nimport './interfaces/IJBSplitsStore.sol';\nimport './libraries/JBConstants.sol';\nimport './JBETHERC20ProjectPayer.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\n\n @dev\n Adheres to -\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBETHERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBETHERC20SplitsPayer is JBETHERC20ProjectPayer, ReentrancyGuard, IJBSplitsPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The ID of project for which the default splits are stored. \n */\n uint256 public override defaultSplitsProjectId;\n\n /**\n @notice\n The domain within which the default splits are stored. \n */\n uint256 public override defaultSplitsDomain;\n\n /**\n @notice\n The group within which the default splits are stored. \n */\n uint256 public override defaultSplitsGroup;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBETHERC20ProjectPayer, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n )\n JBETHERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _preferAddToBalance,\n _splitsStore.directory(),\n _owner\n )\n {\n defaultSplitsProjectId = _defaultSplitsProjectId;\n defaultSplitsDomain = _defaultSplitsDomain;\n defaultSplitsGroup = _defaultSplitsGroup;\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default split group using the stored default properties.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override nonReentrant {\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n JBTokens.ETH,\n address(this).balance,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // If there is no leftover amount, nothing left to pay.\n if (_leftoverAmount == 0) return;\n\n // If there's a default project ID, try to pay it.\n if (defaultProjectId != 0)\n if (defaultPreferAddToBalance)\n // Pay the project by adding to its balance if prefered.\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.ETH,\n _leftoverAmount,\n 18, // decimals.\n defaultMemo,\n defaultMetadata\n );\n // Otherwise, issue a payment to the project.\n else\n _pay(\n defaultProjectId,\n JBTokens.ETH,\n _leftoverAmount,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n 0, // min returned tokens.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else\n Address.sendValue(\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(tx.origin),\n _leftoverAmount\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the splits in the splits store that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n @param _groupedSplits The split groups to set.\n */\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n JBGroupedSplits[] memory _groupedSplits\n ) external virtual override onlyOwner {\n // Set the splits in the store.\n splitsStore.set(_projectId, _domain, _groupedSplits);\n\n // Set the splits reference.\n setDefaultSplitsReference(_projectId, _domain, _group);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the location of the splits that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n */\n function setDefaultSplitsReference(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) public virtual override onlyOwner {\n // Set the default splits project ID if it's changing.\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\n\n // Set the default splits domain if it's changing.\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\n\n // Set the default splits group if it's changing.\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\n\n emit SetDefaultSplitsReference(_projectId, _domain, _group, msg.sender);\n }\n\n /** \n @notice \n Make a payment to the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Pay any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to pay it.\n if (_projectId != 0) {\n _pay(\n _projectId,\n _token,\n _leftoverAmount,\n _decimals,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? payable(_beneficiary) : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit Pay(\n _projectId,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event. \n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Distribute any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to add to its balance.\n if (_projectId != 0)\n // Add to the project's balance.\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\n\n // Otherwise, send a payment to the beneficiary.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit AddToBalance(\n _projectId,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splitsProjectId The ID of the project to which the splits belong.\n @param _splitsDomain The splits domain to which the group belongs.\n @param _splitsGroup The splits group to pay.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payToSplits(\n uint256 _splitsProjectId,\n uint256 _splitsDomain,\n uint256 _splitsGroup,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Pay the splits.\n leftoverAmount = _payTo(\n splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup),\n _token,\n _amount,\n _decimals,\n _defaultBeneficiary\n );\n emit DistributeToSplitGroup(_splitsProjectId, _splitsDomain, _splitsGroup, msg.sender);\n }\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splits The splits.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payTo(\n JBSplit[] memory _splits,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Set the leftover amount to the initial balance.\n leftoverAmount = _amount;\n\n // Settle between all splits.\n for (uint256 i; i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[i];\n\n // The amount to send towards the split.\n uint256 _splitAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n if (_splitAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n _token,\n _splitAmount,\n _decimals,\n defaultProjectId,\n 0,\n _split\n );\n\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\n if (_token != JBTokens.ETH)\n IERC20(_token).safeApprove(address(_split.allocator), _splitAmount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _splitAmount : 0;\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n if (_split.preferAddToBalance)\n _addToBalanceOf(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n 0,\n _split.preferClaimed,\n defaultMemo,\n defaultMetadata\n );\n } else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : payable(_defaultBeneficiary),\n _splitAmount\n );\n // Or, transfer the ERC20.\n else {\n IERC20(_token).safeTransfer(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n _splitAmount\n );\n }\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _splitAmount;\n }\n\n emit DistributeToSplit(_split, _splitAmount, _defaultBeneficiary, msg.sender);\n\n unchecked {\n ++i;\n }\n }\n }\n}\n" + "contracts/JBGasTokenERC20SplitsPayer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBSplitsPayer.sol';\nimport './interfaces/IJBSplitsStore.sol';\nimport './libraries/JBConstants.sol';\nimport './JBGasTokenERC20ProjectPayer.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\n\n @dev\n Adheres to -\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBGasTokenERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBGasTokenERC20SplitsPayer is JBGasTokenERC20ProjectPayer, ReentrancyGuard, IJBSplitsPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The ID of project for which the default splits are stored. \n */\n uint256 public override defaultSplitsProjectId;\n\n /**\n @notice\n The domain within which the default splits are stored. \n */\n uint256 public override defaultSplitsDomain;\n\n /**\n @notice\n The group within which the default splits are stored. \n */\n uint256 public override defaultSplitsGroup;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBGasTokenERC20ProjectPayer, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n )\n JBGasTokenERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _preferAddToBalance,\n _splitsStore.directory(),\n _owner\n )\n {\n defaultSplitsProjectId = _defaultSplitsProjectId;\n defaultSplitsDomain = _defaultSplitsDomain;\n defaultSplitsGroup = _defaultSplitsGroup;\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default split group using the stored default properties.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override nonReentrant {\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // If there is no leftover amount, nothing left to pay.\n if (_leftoverAmount == 0) return;\n\n // If there's a default project ID, try to pay it.\n if (defaultProjectId != 0)\n if (defaultPreferAddToBalance)\n // Pay the project by adding to its balance if prefered.\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n _leftoverAmount,\n 18, // decimals.\n defaultMemo,\n defaultMetadata\n );\n // Otherwise, issue a payment to the project.\n else\n _pay(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n _leftoverAmount,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n 0, // min returned tokens.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else\n Address.sendValue(\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(tx.origin),\n _leftoverAmount\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the splits in the splits store that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n @param _groupedSplits The split groups to set.\n */\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n JBGroupedSplits[] memory _groupedSplits\n ) external virtual override onlyOwner {\n // Set the splits in the store.\n splitsStore.set(_projectId, _domain, _groupedSplits);\n\n // Set the splits reference.\n setDefaultSplitsReference(_projectId, _domain, _group);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the location of the splits that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n */\n function setDefaultSplitsReference(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) public virtual override onlyOwner {\n // Set the default splits project ID if it's changing.\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\n\n // Set the default splits domain if it's changing.\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\n\n // Set the default splits group if it's changing.\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\n\n emit SetDefaultSplitsReference(_projectId, _domain, _group, msg.sender);\n }\n\n /** \n @notice \n Make a payment to the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Pay any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to pay it.\n if (_projectId != 0) {\n _pay(\n _projectId,\n _token,\n _leftoverAmount,\n _decimals,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? payable(_beneficiary) : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit Pay(\n _projectId,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event. \n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Distribute any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to add to its balance.\n if (_projectId != 0)\n // Add to the project's balance.\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\n\n // Otherwise, send a payment to the beneficiary.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit AddToBalance(\n _projectId,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splitsProjectId The ID of the project to which the splits belong.\n @param _splitsDomain The splits domain to which the group belongs.\n @param _splitsGroup The splits group to pay.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payToSplits(\n uint256 _splitsProjectId,\n uint256 _splitsDomain,\n uint256 _splitsGroup,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Pay the splits.\n leftoverAmount = _payTo(\n splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup),\n _token,\n _amount,\n _decimals,\n _defaultBeneficiary\n );\n emit DistributeToSplitGroup(_splitsProjectId, _splitsDomain, _splitsGroup, msg.sender);\n }\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splits The splits.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payTo(\n JBSplit[] memory _splits,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Set the leftover amount to the initial balance.\n leftoverAmount = _amount;\n\n // Settle between all splits.\n for (uint256 i; i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[i];\n\n // The amount to send towards the split.\n uint256 _splitAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n if (_splitAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n _token,\n _splitAmount,\n _decimals,\n defaultProjectId,\n 0,\n _split\n );\n\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN)\n IERC20(_token).safeApprove(address(_split.allocator), _splitAmount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _splitAmount : 0;\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n if (_split.preferAddToBalance)\n _addToBalanceOf(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n 0,\n _split.preferClaimed,\n defaultMemo,\n defaultMetadata\n );\n } else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : payable(_defaultBeneficiary),\n _splitAmount\n );\n // Or, transfer the ERC20.\n else {\n IERC20(_token).safeTransfer(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n _splitAmount\n );\n }\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _splitAmount;\n }\n\n emit DistributeToSplit(_split, _splitAmount, _defaultBeneficiary, msg.sender);\n\n unchecked {\n ++i;\n }\n }\n }\n}\n" }, "contracts/interfaces/IJBSplitsPayer.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './../structs/JBSplit.sol';\nimport './../structs/JBGroupedSplits.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBSplitsPayer is IERC165 {\n event SetDefaultSplitsReference(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n address caller\n );\n event Pay(\n uint256 indexed projectId,\n address beneficiary,\n address token,\n uint256 amount,\n uint256 decimals,\n uint256 leftoverAmount,\n uint256 minReturnedTokens,\n bool preferClaimedTokens,\n string memo,\n bytes metadata,\n address caller\n );\n\n event AddToBalance(\n uint256 indexed projectId,\n address beneficiary,\n address token,\n uint256 amount,\n uint256 decimals,\n uint256 leftoverAmount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DistributeToSplitGroup(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n address caller\n );\n\n event DistributeToSplit(\n JBSplit split,\n uint256 amount,\n address defaultBeneficiary,\n address caller\n );\n\n function defaultSplitsProjectId() external view returns (uint256);\n\n function defaultSplitsDomain() external view returns (uint256);\n\n function defaultSplitsGroup() external view returns (uint256);\n\n function splitsStore() external view returns (IJBSplitsStore);\n\n function setDefaultSplitsReference(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) external;\n\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n JBGroupedSplits[] memory _splitsGroup\n ) external;\n}\n" }, - "contracts/JBETHERC20ProjectPayer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport './interfaces/IJBProjectPayer.sol';\nimport './libraries/JBTokens.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ERC165: Introspection on interface adherance. \n*/\ncontract JBETHERC20ProjectPayer is Ownable, ERC165, IJBProjectPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // -------------------------- custom errors -------------------------- //\n //*********************************************************************//\n error INCORRECT_DECIMAL_AMOUNT();\n error NO_MSG_VALUE_ALLOWED();\n error TERMINAL_NOT_FOUND();\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice \n A contract storing directories of terminals and controllers for each project.\n */\n IJBDirectory public immutable override directory;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The ID of the project that should be used to forward this contract's received payments.\n */\n uint256 public override defaultProjectId;\n\n /** \n @notice \n The beneficiary that should be used in the payment made when this contract receives payments.\n */\n address payable public override defaultBeneficiary;\n\n /** \n @notice \n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\n */\n bool public override defaultPreferClaimedTokens;\n\n /** \n @notice \n The memo that should be used in the payment made when this contract receives payments.\n */\n string public override defaultMemo;\n\n /** \n @notice \n The metadata that should be used in the payment made when this contract receives payments.\n */\n bytes public override defaultMetadata;\n\n /**\n @notice \n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n bool public override defaultPreferAddToBalance;\n\n //*********************************************************************//\n // ------------------------- public views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) {\n defaultProjectId = _defaultProjectId;\n defaultBeneficiary = _defaultBeneficiary;\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\n defaultMemo = _defaultMemo;\n defaultMetadata = _defaultMetadata;\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n directory = _directory;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default project ID using the stored default properties.\n\n @dev\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override {\n if (defaultPreferAddToBalance)\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.ETH,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n defaultProjectId,\n JBTokens.ETH,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultBeneficiary == address(0) ? tx.origin : defaultBeneficiary,\n 0, // Can't determine expectation of returned tokens ahead of time.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\n\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _beneficiary The address that'll receive the project's tokens. \n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _memo The memo that'll be used. \n @param _metadata The metadata that'll be sent. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external virtual override onlyOwner {\n // Set the default project ID if it has changed.\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\n\n // Set the default beneficiary if it has changed.\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\n\n // Set the default claimed token preference if it has changed.\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\n defaultPreferClaimedTokens = _preferClaimedTokens;\n\n // Set the default memo if it has changed.\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\n defaultMemo = _memo;\n\n // Set the default metadata if it has changed.\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\n defaultMetadata = _metadata;\n\n // Set the add to balance preference if it has changed.\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n\n emit SetDefaultValues(\n _projectId,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata,\n _defaultPreferAddToBalance,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _pay(\n _projectId,\n _token,\n _amount,\n _decimals,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. \n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source and delegate, if provided.\n */\n function _pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.ETH) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\n\n // Send funds to the terminal.\n // If the token is ETH, send it in msg.value.\n _terminal.pay{value: _payableValue}(\n _projectId,\n _amount, // ignored if the token is JBTokens.ETH.\n _token,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.ETH) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\n\n // Add to balance so tokens don't get issued.\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\n }\n}\n" + "contracts/JBGasTokenERC20ProjectPayer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport './interfaces/IJBProjectPayer.sol';\nimport './libraries/JBTokens.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ERC165: Introspection on interface adherance. \n*/\ncontract JBGasTokenERC20ProjectPayer is Ownable, ERC165, IJBProjectPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // -------------------------- custom errors -------------------------- //\n //*********************************************************************//\n error INCORRECT_DECIMAL_AMOUNT();\n error NO_MSG_VALUE_ALLOWED();\n error TERMINAL_NOT_FOUND();\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice \n A contract storing directories of terminals and controllers for each project.\n */\n IJBDirectory public immutable override directory;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The ID of the project that should be used to forward this contract's received payments.\n */\n uint256 public override defaultProjectId;\n\n /** \n @notice \n The beneficiary that should be used in the payment made when this contract receives payments.\n */\n address payable public override defaultBeneficiary;\n\n /** \n @notice \n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\n */\n bool public override defaultPreferClaimedTokens;\n\n /** \n @notice \n The memo that should be used in the payment made when this contract receives payments.\n */\n string public override defaultMemo;\n\n /** \n @notice \n The metadata that should be used in the payment made when this contract receives payments.\n */\n bytes public override defaultMetadata;\n\n /**\n @notice \n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n bool public override defaultPreferAddToBalance;\n\n //*********************************************************************//\n // ------------------------- public views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) {\n defaultProjectId = _defaultProjectId;\n defaultBeneficiary = _defaultBeneficiary;\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\n defaultMemo = _defaultMemo;\n defaultMetadata = _defaultMetadata;\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n directory = _directory;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default project ID using the stored default properties.\n\n @dev\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override {\n if (defaultPreferAddToBalance)\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultBeneficiary == address(0) ? tx.origin : defaultBeneficiary,\n 0, // Can't determine expectation of returned tokens ahead of time.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\n\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _beneficiary The address that'll receive the project's tokens. \n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _memo The memo that'll be used. \n @param _metadata The metadata that'll be sent. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external virtual override onlyOwner {\n // Set the default project ID if it has changed.\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\n\n // Set the default beneficiary if it has changed.\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\n\n // Set the default claimed token preference if it has changed.\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\n defaultPreferClaimedTokens = _preferClaimedTokens;\n\n // Set the default memo if it has changed.\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\n defaultMemo = _memo;\n\n // Set the default metadata if it has changed.\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\n defaultMetadata = _metadata;\n\n // Set the add to balance preference if it has changed.\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n\n emit SetDefaultValues(\n _projectId,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata,\n _defaultPreferAddToBalance,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _pay(\n _projectId,\n _token,\n _amount,\n _decimals,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. \n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source and delegate, if provided.\n */\n function _pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send funds to the terminal.\n // If the token is ETH, send it in msg.value.\n _terminal.pay{value: _payableValue}(\n _projectId,\n _amount, // ignored if the token is JBTokens.GAS_TOKEN.\n _token,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Add to balance so tokens don't get issued.\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\n }\n}\n" }, "contracts/interfaces/IJBProjectPayer.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './IJBDirectory.sol';\n\ninterface IJBProjectPayer is IERC165 {\n event SetDefaultValues(\n uint256 indexed projectId,\n address indexed beneficiary,\n bool preferClaimedTokens,\n string memo,\n bytes metadata,\n bool preferAddToBalance,\n address caller\n );\n\n function directory() external view returns (IJBDirectory);\n\n function defaultProjectId() external view returns (uint256);\n\n function defaultBeneficiary() external view returns (address payable);\n\n function defaultPreferClaimedTokens() external view returns (bool);\n\n function defaultMemo() external view returns (string memory);\n\n function defaultMetadata() external view returns (bytes memory);\n\n function defaultPreferAddToBalance() external view returns (bool);\n\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external;\n\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) external payable;\n\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) external payable;\n\n receive() external payable;\n}\n" }, - "contracts/JBETHERC20SplitsPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './interfaces/IJBETHERC20SplitsPayerDeployer.sol';\nimport './structs/JBSplit.sol';\nimport './structs/JBGroupedSplits.sol';\nimport './JBETHERC20SplitsPayer.sol';\n\n/** \n @notice \n Deploys splits payer contracts.\n\n @dev\n Adheres to -\n IJBETHERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBETHERC20SplitsPayerDeployer is IJBETHERC20SplitsPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @dev\n This contract must have Operator permissions over the SET_SPLITS permission of the specified `_defaultSplitsProjectId`.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplits The splits to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBSplitsPayer splitsPayer) {\n // Use this contract's address as the domain.\n uint256 _domain = uint256(uint160(address(this)));\n\n // Create the random hash using data unique to this instance that'll be used as the storage domain.\n uint256 _group = uint256(keccak256(abi.encodePacked(msg.sender, block.number)));\n\n // Set the splits in the store.\n JBGroupedSplits[] memory _groupedSplits;\n _groupedSplits = new JBGroupedSplits[](1);\n _groupedSplits[0] = JBGroupedSplits(_group, _defaultSplits);\n _splitsStore.set(_defaultSplitsProjectId, _domain, _groupedSplits);\n\n return\n deploySplitsPayer(\n _defaultSplitsProjectId,\n _domain,\n _group,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n }\n\n //*********************************************************************//\n // ---------------------- public transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) public override returns (IJBSplitsPayer splitsPayer) {\n // Deploy the splits payer.\n splitsPayer = new JBETHERC20SplitsPayer(\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeploySplitsPayer(\n splitsPayer,\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner,\n msg.sender\n );\n }\n}\n" + "contracts/JBGasTokenERC20SplitsPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './interfaces/IJBGasTokenERC20SplitsPayerDeployer.sol';\nimport './structs/JBSplit.sol';\nimport './structs/JBGroupedSplits.sol';\nimport './JBGasTokenERC20SplitsPayer.sol';\n\n/** \n @notice \n Deploys splits payer contracts.\n\n @dev\n Adheres to -\n IJBGasTokenERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBGasTokenERC20SplitsPayerDeployer is IJBGasTokenERC20SplitsPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @dev\n This contract must have Operator permissions over the SET_SPLITS permission of the specified `_defaultSplitsProjectId`.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplits The splits to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBSplitsPayer splitsPayer) {\n // Use this contract's address as the domain.\n uint256 _domain = uint256(uint160(address(this)));\n\n // Create the random hash using data unique to this instance that'll be used as the storage domain.\n uint256 _group = uint256(keccak256(abi.encodePacked(msg.sender, block.number)));\n\n // Set the splits in the store.\n JBGroupedSplits[] memory _groupedSplits;\n _groupedSplits = new JBGroupedSplits[](1);\n _groupedSplits[0] = JBGroupedSplits(_group, _defaultSplits);\n _splitsStore.set(_defaultSplitsProjectId, _domain, _groupedSplits);\n\n return\n deploySplitsPayer(\n _defaultSplitsProjectId,\n _domain,\n _group,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n }\n\n //*********************************************************************//\n // ---------------------- public transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) public override returns (IJBSplitsPayer splitsPayer) {\n // Deploy the splits payer.\n splitsPayer = new JBGasTokenERC20SplitsPayer(\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeploySplitsPayer(\n splitsPayer,\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner,\n msg.sender\n );\n }\n}\n" }, - "contracts/interfaces/IJBETHERC20SplitsPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBSplitsPayer.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBETHERC20SplitsPayerDeployer {\n event DeploySplitsPayer(\n IJBSplitsPayer indexed splitsPayer,\n uint256 defaultSplitsProjectId,\n uint256 defaultSplitsDomain,\n uint256 defaultSplitsGroup,\n IJBSplitsStore splitsStore,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n address owner,\n address caller\n );\n\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string calldata _defaultMemo,\n bytes calldata _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n}\n" + "contracts/interfaces/IJBGasTokenERC20SplitsPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBSplitsPayer.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBGasTokenERC20SplitsPayerDeployer {\n event DeploySplitsPayer(\n IJBSplitsPayer indexed splitsPayer,\n uint256 defaultSplitsProjectId,\n uint256 defaultSplitsDomain,\n uint256 defaultSplitsGroup,\n IJBSplitsStore splitsStore,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n address owner,\n address caller\n );\n\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string calldata _defaultMemo,\n bytes calldata _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n}\n" }, "contracts/JBSplitsStore.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './abstract/JBOperatable.sol';\nimport './interfaces/IJBDirectory.sol';\nimport './interfaces/IJBSplitsStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBOperations.sol';\n\n/**\n @notice\n Stores splits for each project.\n\n @dev\n Adheres to -\n IJBSplitsStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\ncontract JBSplitsStore is JBOperatable, IJBSplitsStore {\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_LOCKED_UNTIL();\n error INVALID_PROJECT_ID();\n error INVALID_SPLIT_PERCENT();\n error INVALID_TOTAL_PERCENT();\n error PREVIOUS_LOCKED_SPLITS_NOT_INCLUDED();\n\n //*********************************************************************//\n // --------------------- private stored properties ------------------- //\n //*********************************************************************//\n\n /** \n @notice\n The number of splits currently set for each project ID's configurations.\n\n _projectId The ID of the project to get the split count for.\n _domain An identifier within which the returned splits should be considered active.\n _group The identifying group of the splits.\n */\n mapping(uint256 => mapping(uint256 => mapping(uint256 => uint256))) private _splitCountOf;\n\n /** \n @notice\n Packed data of splits for each project ID's configurations.\n\n _projectId The ID of the project to get packed splits data for.\n _domain An identifier within which the returned splits should be considered active.\n _group The identifying group of the splits.\n _index The indexed order that the split was set at.\n */\n mapping(uint256 => mapping(uint256 => mapping(uint256 => mapping(uint256 => uint256))))\n private _packedSplitParts1Of;\n\n /** \n @notice\n More packed data of splits for each project ID's configurations.\n\n @dev\n This packed data is often 0.\n\n _projectId The ID of the project to get packed splits data for.\n _domain An identifier within which the returned splits should be considered active.\n _group The identifying group of the splits.\n _index The indexed order that the split was set at.\n */\n mapping(uint256 => mapping(uint256 => mapping(uint256 => mapping(uint256 => uint256))))\n private _packedSplitParts2Of;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /** \n @notice \n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /** \n @notice \n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice \n Get all splits for the specified project ID, within the specified domain, for the specified group.\n\n @param _projectId The ID of the project to get splits for.\n @param _domain An identifier within which the returned splits should be considered active.\n @param _group The identifying group of the splits.\n\n @return An array of all splits for the project.\n*/\n function splitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) external view override returns (JBSplit[] memory) {\n return _getStructsFor(_projectId, _domain, _group);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n */\n constructor(\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory\n ) JBOperatable(_operatorStore) {\n projects = _projects;\n directory = _directory;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets a project's splits.\n\n @dev\n Only the owner or operator of a project, or the current controller contract of the project, can set its splits.\n\n @dev\n The new splits must include any currently set splits that are locked.\n\n @param _projectId The ID of the project for which splits are being added.\n @param _domain An identifier within which the splits should be considered active.\n @param _groupedSplits An array of splits to set for any number of groups. \n */\n function set(\n uint256 _projectId,\n uint256 _domain,\n JBGroupedSplits[] calldata _groupedSplits\n )\n external\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.SET_SPLITS,\n address(directory.controllerOf(_projectId)) == msg.sender\n )\n {\n // Push array length in stack\n uint256 _groupedSplitsLength = _groupedSplits.length;\n\n // Set each grouped splits.\n for (uint256 _i; _i < _groupedSplitsLength; ) {\n // Get a reference to the grouped split being iterated on.\n JBGroupedSplits memory _groupedSplit = _groupedSplits[_i];\n\n // Set the splits for the group.\n _set(_projectId, _domain, _groupedSplit.group, _groupedSplit.splits);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets a project's splits.\n\n @dev\n The new splits must include any currently set splits that are locked.\n\n @param _projectId The ID of the project for which splits are being added.\n @param _domain An identifier within which the splits should be considered active.\n @param _group An identifier between of splits being set. All splits within this _group must add up to within 100%.\n @param _splits The splits to set.\n */\n function _set(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n JBSplit[] memory _splits\n ) internal {\n // Get a reference to the project's current splits.\n JBSplit[] memory _currentSplits = _getStructsFor(_projectId, _domain, _group);\n\n // Keep a reference to the number of splits.\n uint256 _currentSplitsLength = _currentSplits.length;\n\n // Check to see if all locked splits are included.\n for (uint256 _i; _i < _currentSplitsLength; ) {\n // If not locked, continue.\n if (\n block.timestamp < _currentSplits[_i].lockedUntil &&\n !_includesLocked(_splits, _currentSplits[_i])\n ) revert PREVIOUS_LOCKED_SPLITS_NOT_INCLUDED();\n\n unchecked {\n ++_i;\n }\n }\n\n // Add up all the percents to make sure they cumulatively are under 100%.\n uint256 _percentTotal;\n\n // Keep a reference to the number of splits.\n uint256 _splitsLength = _splits.length;\n\n for (uint256 _i; _i < _splitsLength; ) {\n // The percent should be greater than 0.\n if (_splits[_i].percent == 0) revert INVALID_SPLIT_PERCENT();\n\n // ProjectId should be within a uint56\n if (_splits[_i].projectId > type(uint56).max) revert INVALID_PROJECT_ID();\n\n // Add to the total percents.\n _percentTotal = _percentTotal + _splits[_i].percent;\n\n // Validate the total does not exceed the expected value.\n if (_percentTotal > JBConstants.SPLITS_TOTAL_PERCENT) revert INVALID_TOTAL_PERCENT();\n\n uint256 _packedSplitParts1;\n\n // prefer claimed in bit 0.\n if (_splits[_i].preferClaimed) _packedSplitParts1 = 1;\n // prefer add to balance in bit 1.\n if (_splits[_i].preferAddToBalance) _packedSplitParts1 |= 1 << 1;\n // percent in bits 2-33.\n _packedSplitParts1 |= _splits[_i].percent << 2;\n // projectId in bits 32-89.\n _packedSplitParts1 |= _splits[_i].projectId << 34;\n // beneficiary in bits 90-249.\n _packedSplitParts1 |= uint256(uint160(address(_splits[_i].beneficiary))) << 90;\n\n // Store the first split part.\n _packedSplitParts1Of[_projectId][_domain][_group][_i] = _packedSplitParts1;\n\n // If there's data to store in the second packed split part, pack and store.\n if (_splits[_i].lockedUntil > 0 || _splits[_i].allocator != IJBSplitAllocator(address(0))) {\n // Locked until should be within a uint48\n if (_splits[_i].lockedUntil > type(uint48).max) revert INVALID_LOCKED_UNTIL();\n\n // lockedUntil in bits 0-47.\n uint256 _packedSplitParts2 = uint48(_splits[_i].lockedUntil);\n // allocator in bits 48-207.\n _packedSplitParts2 |= uint256(uint160(address(_splits[_i].allocator))) << 48;\n\n // Store the second split part.\n _packedSplitParts2Of[_projectId][_domain][_group][_i] = _packedSplitParts2;\n\n // Otherwise if there's a value stored in the indexed position, delete it.\n } else if (_packedSplitParts2Of[_projectId][_domain][_group][_i] > 0)\n delete _packedSplitParts2Of[_projectId][_domain][_group][_i];\n\n emit SetSplit(_projectId, _domain, _group, _splits[_i], msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n\n // Set the new length of the splits.\n _splitCountOf[_projectId][_domain][_group] = _splitsLength;\n }\n\n /** \n @notice\n A flag indiciating if the provided splits array includes the locked split. \n\n @param _splits The array of splits to check within.\n @param _lockedSplit The locked split.\n\n @return A flag indicating if the `_lockedSplit` is contained in the `_splits`.\n */\n function _includesLocked(JBSplit[] memory _splits, JBSplit memory _lockedSplit)\n private\n pure\n returns (bool)\n {\n // Keep a reference to the number of splits.\n uint256 _numberOfSplits = _splits.length;\n\n for (uint256 _i; _i < _numberOfSplits; ) {\n // Check for sameness.\n if (\n _splits[_i].percent == _lockedSplit.percent &&\n _splits[_i].beneficiary == _lockedSplit.beneficiary &&\n _splits[_i].allocator == _lockedSplit.allocator &&\n _splits[_i].projectId == _lockedSplit.projectId &&\n _splits[_i].preferClaimed == _lockedSplit.preferClaimed &&\n _splits[_i].preferAddToBalance == _lockedSplit.preferAddToBalance &&\n // Allow lock extention.\n _splits[_i].lockedUntil >= _lockedSplit.lockedUntil\n ) return true;\n\n unchecked {\n ++_i;\n }\n }\n\n return false;\n }\n\n /**\n @notice \n Unpack splits' packed stored values into easy-to-work-with split structs.\n\n @param _projectId The ID of the project to which the split belongs.\n @param _domain The identifier within which the returned splits should be considered active.\n @param _group The identifying group of the splits.\n\n @return splits The split structs.\n */\n function _getStructsFor(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) private view returns (JBSplit[] memory) {\n // Get a reference to the number of splits that need to be added to the returned array.\n uint256 _splitCount = _splitCountOf[_projectId][_domain][_group];\n\n // Initialize an array to be returned that has the set length.\n JBSplit[] memory _splits = new JBSplit[](_splitCount);\n\n // Loop through each split and unpack the values into structs.\n for (uint256 _i; _i < _splitCount; ) {\n // Get a reference to the fist packed data.\n uint256 _packedSplitPart1 = _packedSplitParts1Of[_projectId][_domain][_group][_i];\n\n // Populate the split struct.\n JBSplit memory _split;\n\n // prefer claimed in bit 0.\n _split.preferClaimed = _packedSplitPart1 & 1 == 1;\n // prefer add to balance in bit 1.\n _split.preferAddToBalance = (_packedSplitPart1 >> 1) & 1 == 1;\n // percent in bits 2-33.\n _split.percent = uint256(uint32(_packedSplitPart1 >> 2));\n // projectId in bits 32-89.\n _split.projectId = uint256(uint56(_packedSplitPart1 >> 34));\n // beneficiary in bits 90-249.\n _split.beneficiary = payable(address(uint160(_packedSplitPart1 >> 90)));\n\n // Get a reference to the second packed data.\n uint256 _packedSplitPart2 = _packedSplitParts2Of[_projectId][_domain][_group][_i];\n\n // If there's anything in it, unpack.\n if (_packedSplitPart2 > 0) {\n // lockedUntil in bits 0-47.\n _split.lockedUntil = uint256(uint48(_packedSplitPart2));\n // allocator in bits 48-207.\n _split.allocator = IJBSplitAllocator(address(uint160(_packedSplitPart2 >> 48)));\n }\n\n // Add the split to the value being returned.\n _splits[_i] = _split;\n\n unchecked {\n ++_i;\n }\n }\n\n return _splits;\n }\n}\n" @@ -322,11 +322,11 @@ "contracts/interfaces/IJBTerminalUtility.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBDirectory.sol';\n\ninterface IJBPaymentTerminalUtility {\n function directory() external view returns (IJBDirectory);\n}\n" }, - "contracts/JBETHERC20ProjectPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './interfaces/IJBETHERC20ProjectPayerDeployer.sol';\nimport './JBETHERC20ProjectPayer.sol';\n\n/** \n @notice \n Deploys project payer contracts.\n\n @dev\n Adheres to -\n IJBETHERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBETHERC20ProjectPayerDeployer is IJBETHERC20ProjectPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new project payer contract.\n\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the project payer contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the project payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the project payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the project payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the project payer.\n\n @return projectPayer The project payer contract.\n */\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external override returns (IJBProjectPayer projectPayer) {\n // Deploy the project payer.\n projectPayer = new JBETHERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner\n );\n\n emit DeployProjectPayer(\n projectPayer,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner,\n msg.sender\n );\n }\n}\n" + "contracts/JBGasTokenERC20ProjectPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './interfaces/IJBGasTokenERC20ProjectPayerDeployer.sol';\nimport './JBGasTokenERC20ProjectPayer.sol';\n\n/** \n @notice \n Deploys project payer contracts.\n\n @dev\n Adheres to -\n IJBGasTokenERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBGasTokenERC20ProjectPayerDeployer is IJBGasTokenERC20ProjectPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new project payer contract.\n\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the project payer contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the project payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the project payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the project payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the project payer.\n\n @return projectPayer The project payer contract.\n */\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external override returns (IJBProjectPayer projectPayer) {\n // Deploy the project payer.\n projectPayer = new JBGasTokenERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner\n );\n\n emit DeployProjectPayer(\n projectPayer,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner,\n msg.sender\n );\n }\n}\n" }, - "contracts/interfaces/IJBETHERC20ProjectPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBDirectory.sol';\nimport './IJBProjectPayer.sol';\n\ninterface IJBETHERC20ProjectPayerDeployer {\n event DeployProjectPayer(\n IJBProjectPayer indexed projectPayer,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n IJBDirectory directory,\n address owner,\n address caller\n );\n\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external returns (IJBProjectPayer projectPayer);\n}\n" + "contracts/interfaces/IJBGasTokenERC20ProjectPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBDirectory.sol';\nimport './IJBProjectPayer.sol';\n\ninterface IJBGasTokenERC20ProjectPayerDeployer {\n event DeployProjectPayer(\n IJBProjectPayer indexed projectPayer,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n IJBDirectory directory,\n address owner,\n address caller\n );\n\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external returns (IJBProjectPayer projectPayer);\n}\n" }, "contracts/JBReconfigurationBufferBallot.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport './interfaces/IJBFundingCycleBallot.sol';\nimport './structs/JBFundingCycle.sol';\n\n/** \n @notice \n Manages approving funding cycle reconfigurations automatically after a buffer period.\n\n @dev\n Adheres to -\n IJBFundingCycleBallot: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ERC165: Introspection on interface adherance. \n*/\ncontract JBReconfigurationBufferBallot is ERC165, IJBFundingCycleBallot {\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice \n The number of seconds that must pass for a funding cycle reconfiguration to become either `Approved` or `Failed`.\n */\n uint256 public immutable override duration;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice \n The approval state of a particular funding cycle.\n\n @param _projectId The ID of the project to which the funding cycle being checked belongs.\n @param _configured The configuration of the funding cycle to check the state of.\n @param _start The start timestamp of the funding cycle to check the state of.\n\n @return The state of the provided ballot. \n */\n function stateOf(\n uint256 _projectId,\n uint256 _configured,\n uint256 _start\n ) public view override returns (JBBallotState) {\n _projectId; // Prevents unused var compiler and natspec complaints.\n\n // If the provided configured timestamp is after the start timestamp, the ballot is Failed.\n if (_configured > _start) return JBBallotState.Failed;\n\n unchecked {\n // If there was sufficient time between configuration and the start of the cycle, it is approved. Otherwise, it is failed.\n return (_start - _configured < duration) ? JBBallotState.Failed : JBBallotState.Approved;\n }\n }\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBFundingCycleBallot).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _duration The number of seconds to wait until a reconfiguration can be either `Approved` or `Failed`.\n */\n constructor(uint256 _duration) {\n duration = _duration;\n }\n}\n" diff --git a/deployments/mainnet/solcInputs/e87fd161fb98793b8dd4dcaee81afb88.json b/deployments/mainnet/solcInputs/e87fd161fb98793b8dd4dcaee81afb88.json index 611253126..c4b1a1061 100644 --- a/deployments/mainnet/solcInputs/e87fd161fb98793b8dd4dcaee81afb88.json +++ b/deployments/mainnet/solcInputs/e87fd161fb98793b8dd4dcaee81afb88.json @@ -164,7 +164,7 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './../structs/JBFundAccessConstraints.sol';\nimport './../structs/JBFundingCycleData.sol';\nimport './../structs/JBFundingCycleMetadata.sol';\nimport './../structs/JBGroupedSplits.sol';\nimport './../structs/JBProjectMetadata.sol';\nimport './IJBDirectory.sol';\nimport './IJBFundingCycleStore.sol';\nimport './IJBMigratable.sol';\nimport './IJBPaymentTerminal.sol';\nimport './IJBSplitsStore.sol';\nimport './IJBTokenStore.sol';\n\ninterface IJBController is IERC165 {\n event LaunchProject(uint256 configuration, uint256 projectId, string memo, address caller);\n\n event LaunchFundingCycles(uint256 configuration, uint256 projectId, string memo, address caller);\n\n event ReconfigureFundingCycles(\n uint256 configuration,\n uint256 projectId,\n string memo,\n address caller\n );\n\n event SetFundAccessConstraints(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n JBFundAccessConstraints constraints,\n address caller\n );\n\n event DistributeReservedTokens(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address beneficiary,\n uint256 tokenCount,\n uint256 beneficiaryTokenCount,\n string memo,\n address caller\n );\n\n event DistributeToReservedTokenSplit(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n JBSplit split,\n uint256 tokenCount,\n address caller\n );\n\n event MintTokens(\n address indexed beneficiary,\n uint256 indexed projectId,\n uint256 tokenCount,\n uint256 beneficiaryTokenCount,\n string memo,\n uint256 reservedRate,\n address caller\n );\n\n event BurnTokens(\n address indexed holder,\n uint256 indexed projectId,\n uint256 tokenCount,\n string memo,\n address caller\n );\n\n event Migrate(uint256 indexed projectId, IJBMigratable to, address caller);\n\n event PrepMigration(uint256 indexed projectId, address from, address caller);\n\n function projects() external view returns (IJBProjects);\n\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\n\n function tokenStore() external view returns (IJBTokenStore);\n\n function splitsStore() external view returns (IJBSplitsStore);\n\n function directory() external view returns (IJBDirectory);\n\n function reservedTokenBalanceOf(uint256 _projectId, uint256 _reservedRate)\n external\n view\n returns (uint256);\n\n function distributionLimitOf(\n uint256 _projectId,\n uint256 _configuration,\n IJBPaymentTerminal _terminal,\n address _token\n ) external view returns (uint256 distributionLimit, uint256 distributionLimitCurrency);\n\n function overflowAllowanceOf(\n uint256 _projectId,\n uint256 _configuration,\n IJBPaymentTerminal _terminal,\n address _token\n ) external view returns (uint256 overflowAllowance, uint256 overflowAllowanceCurrency);\n\n function totalOutstandingTokensOf(uint256 _projectId, uint256 _reservedRate)\n external\n view\n returns (uint256);\n\n function getFundingCycleOf(uint256 _projectId, uint256 _configuration)\n external\n view\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\n\n function latestConfiguredFundingCycleOf(uint256 _projectId)\n external\n view\n returns (\n JBFundingCycle memory,\n JBFundingCycleMetadata memory metadata,\n JBBallotState\n );\n\n function currentFundingCycleOf(uint256 _projectId)\n external\n view\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\n\n function queuedFundingCycleOf(uint256 _projectId)\n external\n view\n returns (JBFundingCycle memory fundingCycle, JBFundingCycleMetadata memory metadata);\n\n function launchProjectFor(\n address _owner,\n JBProjectMetadata calldata _projectMetadata,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] memory _groupedSplits,\n JBFundAccessConstraints[] memory _fundAccessConstraints,\n IJBPaymentTerminal[] memory _terminals,\n string calldata _memo\n ) external returns (uint256 projectId);\n\n function launchFundingCyclesFor(\n uint256 _projectId,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] memory _groupedSplits,\n JBFundAccessConstraints[] memory _fundAccessConstraints,\n IJBPaymentTerminal[] memory _terminals,\n string calldata _memo\n ) external returns (uint256 configuration);\n\n function reconfigureFundingCyclesOf(\n uint256 _projectId,\n JBFundingCycleData calldata _data,\n JBFundingCycleMetadata calldata _metadata,\n uint256 _mustStartAtOrAfter,\n JBGroupedSplits[] memory _groupedSplits,\n JBFundAccessConstraints[] memory _fundAccessConstraints,\n string calldata _memo\n ) external returns (uint256);\n\n function mintTokensOf(\n uint256 _projectId,\n uint256 _tokenCount,\n address _beneficiary,\n string calldata _memo,\n bool _preferClaimedTokens,\n bool _useReservedRate\n ) external returns (uint256 beneficiaryTokenCount);\n\n function burnTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string calldata _memo,\n bool _preferClaimedTokens\n ) external;\n\n function distributeReservedTokensOf(uint256 _projectId, string memory _memo)\n external\n returns (uint256);\n\n function migrate(uint256 _projectId, IJBMigratable _to) external;\n}\n" }, "contracts/JBSingleTokenPaymentTerminalStore3_1.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController3_1.sol';\nimport './interfaces/IJBFundingCycleDataSource.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './structs/JBPayDelegateAllocation.sol';\nimport './structs/JBPayParamsData.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n\n @dev\n This Store expects a project's controller to be an IJBController3_1. This is the only difference between this version and the original.\n*/\ncontract JBSingleTokenPaymentTerminalStore3_1 is\n ReentrancyGuard,\n IJBSingleTokenPaymentTerminalStore\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId);\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n JBPayDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .payParams(_data);\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\n {\n // Keep a reference to the amount that should be added to the project's balance.\n uint256 _balanceDiff = _amount.value;\n\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\n if (delegateAllocations.length != 0) {\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0) {\n // Can't delegate more than was paid.\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\n\n // Decrement the total amount being added to the balance.\n _balanceDiff = _balanceDiff - _delegatedAmount;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Add the correct balance difference to the token balance of the project.\n if (_balanceDiff != 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _balanceDiff;\n }\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId);\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow != 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\n {\n // Get a reference to the ballot state.\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\n\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n _state == JBBallotState.Active\n ? fundingCycle.ballotRedemptionRate()\n : fundingCycle.redemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\n fundingCycle.dataSource()\n ).redeemParams(_data);\n }\n } else {\n memo = _memo;\n }\n }\n\n // Keep a reference to the amount that should be subtracted from the project's balance.\n uint256 _balanceDiff = reclaimAmount;\n\n if (delegateAllocations.length != 0) {\n // Validate all delegated amounts.\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0)\n // Increment the total amount being subtracted from the balance.\n _balanceDiff = _balanceDiff + _delegatedAmount;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (_balanceDiff != 0) {\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n _balanceDiff;\n }\n }\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).fundAccessConstraintsStore().distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).fundAccessConstraintsStore().overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).fundAccessConstraintsStore().distributionLimitOf(\n _projectId,\n _fundingCycle.configuration,\n _terminal,\n _terminal.token()\n );\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n unchecked {\n return\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i; _i < _terminals.length; ) {\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n unchecked {\n ++_i;\n }\n }\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.ETH\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.ETH, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController3_1.sol';\nimport './interfaces/IJBFundingCycleDataSource.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './structs/JBPayDelegateAllocation.sol';\nimport './structs/JBPayParamsData.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n\n @dev\n This Store expects a project's controller to be an IJBController3_1. This is the only difference between this version and the original.\n*/\ncontract JBSingleTokenPaymentTerminalStore3_1 is\n ReentrancyGuard,\n IJBSingleTokenPaymentTerminalStore\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId);\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n JBPayDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .payParams(_data);\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\n {\n // Keep a reference to the amount that should be added to the project's balance.\n uint256 _balanceDiff = _amount.value;\n\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\n if (delegateAllocations.length != 0) {\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0) {\n // Can't delegate more than was paid.\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\n\n // Decrement the total amount being added to the balance.\n _balanceDiff = _balanceDiff - _delegatedAmount;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Add the correct balance difference to the token balance of the project.\n if (_balanceDiff != 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _balanceDiff;\n }\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId);\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow != 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\n {\n // Get a reference to the ballot state.\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\n\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n _state == JBBallotState.Active\n ? fundingCycle.ballotRedemptionRate()\n : fundingCycle.redemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\n fundingCycle.dataSource()\n ).redeemParams(_data);\n }\n } else {\n memo = _memo;\n }\n }\n\n // Keep a reference to the amount that should be subtracted from the project's balance.\n uint256 _balanceDiff = reclaimAmount;\n\n if (delegateAllocations.length != 0) {\n // Validate all delegated amounts.\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0)\n // Increment the total amount being subtracted from the balance.\n _balanceDiff = _balanceDiff + _delegatedAmount;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (_balanceDiff != 0) {\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n _balanceDiff;\n }\n }\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).fundAccessConstraintsStore().distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).fundAccessConstraintsStore().overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).fundAccessConstraintsStore().distributionLimitOf(\n _projectId,\n _fundingCycle.configuration,\n _terminal,\n _terminal.token()\n );\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n unchecked {\n return\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i; _i < _terminals.length; ) {\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n unchecked {\n ++_i;\n }\n }\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.GAS_CURRENCY\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.GAS_CURRENCY, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" }, "@openzeppelin/contracts/security/ReentrancyGuard.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n constructor() {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n // On the first call to nonReentrant, _notEntered will be true\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n\n _;\n\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n}\n" @@ -224,7 +224,7 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IJBPriceFeed {\n function currentPrice(uint256 _targetDecimals) external view returns (uint256);\n}\n" }, "contracts/JBSingleTokenPaymentTerminalStore.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController.sol';\nimport './interfaces/IJBFundingCycleDataSource.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './structs/JBPayDelegateAllocation.sol';\nimport './structs/JBPayParamsData.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBSingleTokenPaymentTerminalStore is ReentrancyGuard, IJBSingleTokenPaymentTerminalStore {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n JBPayDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .payParams(_data);\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\n {\n // Keep a reference to the amount that should be added to the project's balance.\n uint256 _balanceDiff = _amount.value;\n\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\n if (delegateAllocations.length != 0) {\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0) {\n // Can't delegate more than was paid.\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\n\n // Decrement the total amount being added to the balance.\n _balanceDiff = _balanceDiff - _delegatedAmount;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Add the correct balance difference to the token balance of the project.\n if (_balanceDiff != 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _balanceDiff;\n }\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\n _projectId,\n fundingCycle.reservedRate()\n );\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow != 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\n {\n // Get a reference to the ballot state.\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\n\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n _state == JBBallotState.Active\n ? fundingCycle.ballotRedemptionRate()\n : fundingCycle.redemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\n fundingCycle.dataSource()\n ).redeemParams(_data);\n }\n } else {\n memo = _memo;\n }\n }\n\n // Keep a reference to the amount that should be subtracted from the project's balance.\n uint256 _balanceDiff = reclaimAmount;\n\n if (delegateAllocations.length != 0) {\n // Validate all delegated amounts.\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0)\n // Increment the total amount being subtracted from the balance.\n _balanceDiff = _balanceDiff + _delegatedAmount;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (_balanceDiff != 0) {\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n _balanceDiff;\n }\n }\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n unchecked {\n return\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i; _i < _terminals.length; ) {\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n unchecked {\n ++_i;\n }\n }\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.ETH\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.ETH, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController.sol';\nimport './interfaces/IJBFundingCycleDataSource.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './structs/JBPayDelegateAllocation.sol';\nimport './structs/JBPayParamsData.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBSingleTokenPaymentTerminalStore is ReentrancyGuard, IJBSingleTokenPaymentTerminalStore {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n JBPayDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .payParams(_data);\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\n {\n // Keep a reference to the amount that should be added to the project's balance.\n uint256 _balanceDiff = _amount.value;\n\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\n if (delegateAllocations.length != 0) {\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0) {\n // Can't delegate more than was paid.\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\n\n // Decrement the total amount being added to the balance.\n _balanceDiff = _balanceDiff - _delegatedAmount;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Add the correct balance difference to the token balance of the project.\n if (_balanceDiff != 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _balanceDiff;\n }\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\n _projectId,\n fundingCycle.reservedRate()\n );\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow != 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\n {\n // Get a reference to the ballot state.\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\n\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n _state == JBBallotState.Active\n ? fundingCycle.ballotRedemptionRate()\n : fundingCycle.redemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\n fundingCycle.dataSource()\n ).redeemParams(_data);\n }\n } else {\n memo = _memo;\n }\n }\n\n // Keep a reference to the amount that should be subtracted from the project's balance.\n uint256 _balanceDiff = reclaimAmount;\n\n if (delegateAllocations.length != 0) {\n // Validate all delegated amounts.\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0)\n // Increment the total amount being subtracted from the balance.\n _balanceDiff = _balanceDiff + _delegatedAmount;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (_balanceDiff != 0) {\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n _balanceDiff;\n }\n }\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n unchecked {\n return\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i; _i < _terminals.length; ) {\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n unchecked {\n ++_i;\n }\n }\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.GAS_CURRENCY\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.GAS_CURRENCY, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" }, "contracts/interfaces/IJBPayoutRedemptionPaymentTerminal3_1.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './../structs/JBFee.sol';\nimport './IJBAllowanceTerminal3_1.sol';\nimport './IJBDirectory.sol';\nimport './IJBFeeGauge.sol';\nimport './IJBFeeHoldingTerminal.sol';\nimport './IJBPayDelegate.sol';\nimport './IJBPaymentTerminal.sol';\nimport './IJBPayoutTerminal3_1.sol';\nimport './IJBPrices.sol';\nimport './IJBProjects.sol';\nimport './IJBRedemptionDelegate.sol';\nimport './IJBRedemptionTerminal.sol';\nimport './IJBSingleTokenPaymentTerminalStore.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBPayoutRedemptionPaymentTerminal3_1 is\n IJBPaymentTerminal,\n IJBPayoutTerminal3_1,\n IJBAllowanceTerminal3_1,\n IJBRedemptionTerminal,\n IJBFeeHoldingTerminal\n{\n event AddToBalance(\n uint256 indexed projectId,\n uint256 amount,\n uint256 refundedFees,\n string memo,\n bytes metadata,\n address caller\n );\n\n event Migrate(\n uint256 indexed projectId,\n IJBPaymentTerminal indexed to,\n uint256 amount,\n address caller\n );\n\n event DistributePayouts(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address beneficiary,\n uint256 amount,\n uint256 distributedAmount,\n uint256 fee,\n uint256 beneficiaryDistributionAmount,\n bytes metadata,\n address caller\n );\n\n event UseAllowance(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address beneficiary,\n uint256 amount,\n uint256 distributedAmount,\n uint256 netDistributedamount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event HoldFee(\n uint256 indexed projectId,\n uint256 indexed amount,\n uint256 indexed fee,\n uint256 feeDiscount,\n address beneficiary,\n address caller\n );\n\n event ProcessFee(\n uint256 indexed projectId,\n uint256 indexed amount,\n bool indexed wasHeld,\n address beneficiary,\n address caller\n );\n\n event RefundHeldFees(\n uint256 indexed projectId,\n uint256 indexed amount,\n uint256 indexed refundedFees,\n uint256 leftoverAmount,\n address caller\n );\n\n event Pay(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address payer,\n address beneficiary,\n uint256 amount,\n uint256 beneficiaryTokenCount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DelegateDidPay(\n IJBPayDelegate indexed delegate,\n JBDidPayData data,\n uint256 delegatedAmount,\n address caller\n );\n\n event RedeemTokens(\n uint256 indexed fundingCycleConfiguration,\n uint256 indexed fundingCycleNumber,\n uint256 indexed projectId,\n address holder,\n address beneficiary,\n uint256 tokenCount,\n uint256 reclaimedAmount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DelegateDidRedeem(\n IJBRedemptionDelegate indexed delegate,\n JBDidRedeemData data,\n uint256 delegatedAmount,\n address caller\n );\n\n event DistributeToPayoutSplit(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n JBSplit split,\n uint256 amount,\n uint256 netAmount,\n address caller\n );\n\n event SetFee(uint256 fee, address caller);\n\n event SetFeeGauge(IJBFeeGauge indexed feeGauge, address caller);\n\n event SetFeelessAddress(address indexed addrs, bool indexed flag, address caller);\n\n event PayoutReverted(uint256 indexed projectId, JBSplit split, uint256 amount, bytes reason, address caller);\n\n event FeeReverted(\n uint256 indexed projectId,\n uint256 indexed feeProjectId,\n uint256 amount,\n bytes reason,\n address caller\n );\n\n function projects() external view returns (IJBProjects);\n\n function splitsStore() external view returns (IJBSplitsStore);\n\n function directory() external view returns (IJBDirectory);\n\n function prices() external view returns (IJBPrices);\n\n function store() external view returns (IJBSingleTokenPaymentTerminalStore);\n\n function baseWeightCurrency() external view returns (uint256);\n\n function payoutSplitsGroup() external view returns (uint256);\n\n function heldFeesOf(uint256 _projectId) external view returns (JBFee[] memory);\n\n function fee() external view returns (uint256);\n\n function feeGauge() external view returns (IJBFeeGauge);\n\n function isFeelessAddress(address _contract) external view returns (bool);\n\n function migrate(uint256 _projectId, IJBPaymentTerminal _to) external returns (uint256 balance);\n\n function processFees(uint256 _projectId) external;\n\n function setFee(uint256 _fee) external;\n\n function setFeeGauge(IJBFeeGauge _feeGauge) external;\n\n function setFeelessAddress(address _contract, bool _flag) external;\n}\n" @@ -296,10 +296,10 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nlibrary JBSplitsGroups {\n uint256 public constant ETH_PAYOUT = 1;\n uint256 public constant RESERVED_TOKENS = 2;\n}\n" }, "contracts/JBETHPaymentTerminal3_1.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal3_1.sol';\nimport './libraries/JBSplitsGroups.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal3_1: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal3_1 is JBPayoutRedemptionPaymentTerminal3_1 {\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return address(this).balance;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal3_1(\n JBTokens.ETH,\n 18, // 18 decimals.\n JBCurrencies.ETH,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal3_1.sol';\nimport './libraries/JBSplitsGroups.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal3_1: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal3_1 is JBPayoutRedemptionPaymentTerminal3_1 {\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return address(this).balance;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal3_1(\n JBTokens.GAS_TOKEN,\n 18, // 18 decimals.\n JBCurrencies.GAS_CURRENCY,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n}\n" }, "contracts/abstract/JBPayoutRedemptionPaymentTerminal3_1.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/utils/introspection/ERC165Checker.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal3_1.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBPayDelegateAllocation.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal3_1: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal3_1 is\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n IJBPayoutRedemptionPaymentTerminal3_1\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n @dev\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.ETH)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.ETH, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal3_1).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal3_1).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal3_1).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance.\n */\n function _balance() internal view virtual returns (uint256);\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n bytes calldata _metadata\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _metadata);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes calldata _metadata\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _useAllowanceOf(\n _projectId,\n _amount,\n _currency,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n // Do not refund held fees by default.\n addToBalanceOf(_projectId, _amount, _token, false, _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary, _projectId);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n bool _shouldRefundHeldFees,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.ETH) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance.\n _addToBalanceOf(_projectId, _amount, _shouldRefundHeldFees, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual {\n _from; // Prevents unused var compiler and natspec complaints.\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered if a transfer should be undone\n\n @param _to The address to which the transfer went.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _cancelTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\n {\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\n\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _forwardedAmount,\n _beneficiary,\n _memo,\n _metadata\n );\n\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\n\n emit DelegateDidRedeem(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n bytes calldata _metadata\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n }\n\n // Take the fee.\n _fee = _feeEligibleDistributionAmount != 0\n ? _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n )\n : 0;\n\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\n if (_leftoverDistributionAmount != 0) {\n // Subtract the fee from the net leftover amount.\n netLeftoverDistributionAmount =\n _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n\n // Transfer the amount to the project owner.\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes calldata _metadata\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n // The total percentage available to split\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = _split.percent == leftoverPercentage\n ? leftoverAmount\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\n\n // Decrement the leftover percentage.\n leftoverPercentage -= _split.percent;\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount = _distributeToPayoutSplit(\n _split,\n _projectId,\n _group,\n _payoutAmount,\n _feeDiscount\n );\n\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (_netPayoutAmount != 0 && _netPayoutAmount != _payoutAmount)\n feeEligibleDistributionAmount += _payoutAmount;\n\n if (_payoutAmount > 0) {\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _payoutAmount,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Pays out a split for a project's funding cycle configuration.\n \n @param _split The split to distribute payouts to.\n @param _amount The total amount being distributed to the split, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return netPayoutAmount The amount sent to the split after subtracting fees.\n */\n function _distributeToPayoutSplit(\n JBSplit memory _split,\n uint256 _projectId,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 netPayoutAmount) {\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_split.allocator)]\n )\n netPayoutAmount = _amount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\n }\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), netPayoutAmount);\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n uint256 _error;\n bytes memory _reason;\n\n if (\n ERC165Checker.supportsInterface(\n address(_split.allocator),\n type(IJBSplitAllocator).interfaceId\n )\n )\n // If this terminal's token is ETH, send it in msg.value.\n try _split.allocator.allocate{value: token == JBTokens.ETH ? netPayoutAmount : 0}(_data) {\n\n } catch (bytes memory reason) {\n _reason = reason;\n _error = 1;\n }\n else _error = 2;\n\n\n if (_error != 0) {\n // Trigger any inhereted post-transfer cancelation logic.\n _cancelTransferTo(address(_split.allocator), netPayoutAmount);\n\n // Set the net payout amount to 0 to signal the reversion.\n netPayoutAmount = 0;\n\n // Add undistributed amount back to project's balance.\n store.recordAddedBalanceFor(_projectId, _amount);\n\n emit PayoutReverted(_projectId, _split, _amount, _error == 1 ? _reason : abi.encode(\"IERC165 fail\"), msg.sender);\n }\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (\n _terminal == this ||\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\n isFeelessAddress[address(_terminal)]\n )\n netPayoutAmount = _amount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\n }\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), netPayoutAmount);\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n try\n _terminal.addToBalanceOf{value: token == JBTokens.ETH ? netPayoutAmount : 0}(\n _split.projectId,\n netPayoutAmount,\n token,\n '',\n _projectMetadata\n )\n {} catch (bytes memory reason) {\n // Trigger any inhereted post-transfer cancelation logic.\n _cancelTransferTo(address(_terminal), netPayoutAmount);\n\n // Set the net payout amount to 0 to signal the reversion.\n netPayoutAmount = 0;\n\n // Add undistributed amount back to project's balance.\n store.recordAddedBalanceFor(_projectId, _amount);\n\n emit PayoutReverted(_projectId, _split, _amount, reason, msg.sender);\n }\n else\n try\n _terminal.pay{value: token == JBTokens.ETH ? netPayoutAmount : 0}(\n _split.projectId,\n netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n )\n {} catch (bytes memory reason) {\n // Trigger any inhereted post-transfer cancelation logic.\n _cancelTransferTo(address(_terminal), netPayoutAmount);\n\n // Set the net payout amount to 0 to signal the reversion.\n netPayoutAmount = 0;\n\n // Add undistributed amount back to project's balance.\n store.recordAddedBalanceFor(_projectId, _amount);\n\n emit PayoutReverted(_projectId, _split, _amount, reason, msg.sender);\n }\n } else {\n // Keep a reference to the beneficiary.\n address payable _beneficiary = _split.beneficiary != address(0)\n ? _split.beneficiary\n : payable(msg.sender);\n\n // If there's a full discount, this distribution is not eligible for a fee.\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\n netPayoutAmount = _amount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\n else {\n unchecked {\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\n }\n }\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(address(this), _beneficiary, netPayoutAmount);\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary, _projectId); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n @param _from The project ID the fee is being paid from.\n */\n function _processFee(\n uint256 _amount,\n address _beneficiary,\n uint256 _from\n ) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _amount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_from));\n\n // Trigger any inherited pre-transfer logic if funds will be transferred.\n if (address(_terminal) != address(this)) _beforeTransferTo(address(_terminal), _amount);\n\n try\n // Send the fee.\n _terminal.pay{value: _payableValue}(\n _FEE_BENEFICIARY_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n _projectMetadata\n )\n {} catch (bytes memory reason) {\n // Trigger any inhereted post-transfer cancelation logic if the pre-transfer logic was triggered.\n if (address(_terminal) != address(this)) _cancelTransferTo(address(_terminal), _amount);\n\n // Add fee amount back to project's balance.\n store.recordAddedBalanceFor(_from, _amount);\n\n emit FeeReverted(_from, _FEE_BENEFICIARY_PROJECT_ID, _amount, reason, msg.sender);\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\n {\n JBPayDelegateAllocation[] memory _delegateAllocations;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n _forwardedAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n // Get a reference to the number of delegates to allocate to.\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\n\n emit DelegateDidPay(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n unchecked {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\n IJBPaymentTerminal(address(0))\n ) return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge != IJBFeeGauge(address(0)))\n // If the guage reverts, keep the discount at 0.\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n // If the fee discount is greater than the max, we ignore the return value\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\n } catch {\n return 0;\n }\n\n return 0;\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/utils/introspection/ERC165Checker.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal3_1.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBPayDelegateAllocation.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal3_1: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal3_1 is\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n IJBPayoutRedemptionPaymentTerminal3_1\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n @dev\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.GAS_CURRENCY)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.GAS_CURRENCY, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal3_1).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal3_1).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal3_1).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance.\n */\n function _balance() internal view virtual returns (uint256);\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n bytes calldata _metadata\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _metadata);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes calldata _metadata\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _useAllowanceOf(\n _projectId,\n _amount,\n _currency,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n // Do not refund held fees by default.\n addToBalanceOf(_projectId, _amount, _token, false, _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary, _projectId);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n bool _shouldRefundHeldFees,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.GAS_TOKEN) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance.\n _addToBalanceOf(_projectId, _amount, _shouldRefundHeldFees, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual {\n _from; // Prevents unused var compiler and natspec complaints.\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered if a transfer should be undone\n\n @param _to The address to which the transfer went.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _cancelTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\n {\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\n\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _forwardedAmount,\n _beneficiary,\n _memo,\n _metadata\n );\n\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\n\n emit DelegateDidRedeem(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n bytes calldata _metadata\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n }\n\n // Take the fee.\n _fee = _feeEligibleDistributionAmount != 0\n ? _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n )\n : 0;\n\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\n if (_leftoverDistributionAmount != 0) {\n // Subtract the fee from the net leftover amount.\n netLeftoverDistributionAmount =\n _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n\n // Transfer the amount to the project owner.\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes calldata _metadata\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n // The total percentage available to split\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = _split.percent == leftoverPercentage\n ? leftoverAmount\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\n\n // Decrement the leftover percentage.\n leftoverPercentage -= _split.percent;\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount = _distributeToPayoutSplit(\n _split,\n _projectId,\n _group,\n _payoutAmount,\n _feeDiscount\n );\n\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (_netPayoutAmount != 0 && _netPayoutAmount != _payoutAmount)\n feeEligibleDistributionAmount += _payoutAmount;\n\n if (_payoutAmount > 0) {\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _payoutAmount,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Pays out a split for a project's funding cycle configuration.\n \n @param _split The split to distribute payouts to.\n @param _amount The total amount being distributed to the split, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return netPayoutAmount The amount sent to the split after subtracting fees.\n */\n function _distributeToPayoutSplit(\n JBSplit memory _split,\n uint256 _projectId,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 netPayoutAmount) {\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_split.allocator)]\n )\n netPayoutAmount = _amount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\n }\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), netPayoutAmount);\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n uint256 _error;\n bytes memory _reason;\n\n if (\n ERC165Checker.supportsInterface(\n address(_split.allocator),\n type(IJBSplitAllocator).interfaceId\n )\n )\n // If this terminal's token is ETH, send it in msg.value.\n try _split.allocator.allocate{value: token == JBTokens.GAS_TOKEN ? netPayoutAmount : 0}(_data) {\n\n } catch (bytes memory reason) {\n _reason = reason;\n _error = 1;\n }\n else _error = 2;\n\n\n if (_error != 0) {\n // Trigger any inhereted post-transfer cancelation logic.\n _cancelTransferTo(address(_split.allocator), netPayoutAmount);\n\n // Set the net payout amount to 0 to signal the reversion.\n netPayoutAmount = 0;\n\n // Add undistributed amount back to project's balance.\n store.recordAddedBalanceFor(_projectId, _amount);\n\n emit PayoutReverted(_projectId, _split, _amount, _error == 1 ? _reason : abi.encode(\"IERC165 fail\"), msg.sender);\n }\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (\n _terminal == this ||\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\n isFeelessAddress[address(_terminal)]\n )\n netPayoutAmount = _amount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\n }\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), netPayoutAmount);\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n try\n _terminal.addToBalanceOf{value: token == JBTokens.GAS_TOKEN ? netPayoutAmount : 0}(\n _split.projectId,\n netPayoutAmount,\n token,\n '',\n _projectMetadata\n )\n {} catch (bytes memory reason) {\n // Trigger any inhereted post-transfer cancelation logic.\n _cancelTransferTo(address(_terminal), netPayoutAmount);\n\n // Set the net payout amount to 0 to signal the reversion.\n netPayoutAmount = 0;\n\n // Add undistributed amount back to project's balance.\n store.recordAddedBalanceFor(_projectId, _amount);\n\n emit PayoutReverted(_projectId, _split, _amount, reason, msg.sender);\n }\n else\n try\n _terminal.pay{value: token == JBTokens.GAS_TOKEN ? netPayoutAmount : 0}(\n _split.projectId,\n netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n )\n {} catch (bytes memory reason) {\n // Trigger any inhereted post-transfer cancelation logic.\n _cancelTransferTo(address(_terminal), netPayoutAmount);\n\n // Set the net payout amount to 0 to signal the reversion.\n netPayoutAmount = 0;\n\n // Add undistributed amount back to project's balance.\n store.recordAddedBalanceFor(_projectId, _amount);\n\n emit PayoutReverted(_projectId, _split, _amount, reason, msg.sender);\n }\n } else {\n // Keep a reference to the beneficiary.\n address payable _beneficiary = _split.beneficiary != address(0)\n ? _split.beneficiary\n : payable(msg.sender);\n\n // If there's a full discount, this distribution is not eligible for a fee.\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\n netPayoutAmount = _amount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\n else {\n unchecked {\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\n }\n }\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(address(this), _beneficiary, netPayoutAmount);\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary, _projectId); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n @param _from The project ID the fee is being paid from.\n */\n function _processFee(\n uint256 _amount,\n address _beneficiary,\n uint256 _from\n ) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_from));\n\n // Trigger any inherited pre-transfer logic if funds will be transferred.\n if (address(_terminal) != address(this)) _beforeTransferTo(address(_terminal), _amount);\n\n try\n // Send the fee.\n _terminal.pay{value: _payableValue}(\n _FEE_BENEFICIARY_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n _projectMetadata\n )\n {} catch (bytes memory reason) {\n // Trigger any inhereted post-transfer cancelation logic if the pre-transfer logic was triggered.\n if (address(_terminal) != address(this)) _cancelTransferTo(address(_terminal), _amount);\n\n // Add fee amount back to project's balance.\n store.recordAddedBalanceFor(_from, _amount);\n\n emit FeeReverted(_from, _FEE_BENEFICIARY_PROJECT_ID, _amount, reason, msg.sender);\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\n {\n JBPayDelegateAllocation[] memory _delegateAllocations;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n _forwardedAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n // Get a reference to the number of delegates to allocate to.\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\n\n emit DelegateDidPay(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n unchecked {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\n IJBPaymentTerminal(address(0))\n ) return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge != IJBFeeGauge(address(0)))\n // If the guage reverts, keep the discount at 0.\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n // If the fee discount is greater than the max, we ignore the return value\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\n } catch {\n return 0;\n }\n\n return 0;\n }\n}\n" }, "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165Checker.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Library used to query support of an interface declared via {IERC165}.\n *\n * Note that these functions return the actual result of the query: they do not\n * `revert` if an interface is not supported. It is up to the caller to decide\n * what to do in these cases.\n */\nlibrary ERC165Checker {\n // As per the EIP-165 spec, no interface should ever match 0xffffffff\n bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;\n\n /**\n * @dev Returns true if `account` supports the {IERC165} interface,\n */\n function supportsERC165(address account) internal view returns (bool) {\n // Any contract that implements ERC165 must explicitly indicate support of\n // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid\n return\n _supportsERC165Interface(account, type(IERC165).interfaceId) &&\n !_supportsERC165Interface(account, _INTERFACE_ID_INVALID);\n }\n\n /**\n * @dev Returns true if `account` supports the interface defined by\n * `interfaceId`. Support for {IERC165} itself is queried automatically.\n *\n * See {IERC165-supportsInterface}.\n */\n function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {\n // query support of both ERC165 as per the spec and support of _interfaceId\n return supportsERC165(account) && _supportsERC165Interface(account, interfaceId);\n }\n\n /**\n * @dev Returns a boolean array where each value corresponds to the\n * interfaces passed in and whether they're supported or not. This allows\n * you to batch check interfaces for a contract where your expectation\n * is that some interfaces may not be supported.\n *\n * See {IERC165-supportsInterface}.\n *\n * _Available since v3.4._\n */\n function getSupportedInterfaces(address account, bytes4[] memory interfaceIds)\n internal\n view\n returns (bool[] memory)\n {\n // an array of booleans corresponding to interfaceIds and whether they're supported or not\n bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);\n\n // query support of ERC165 itself\n if (supportsERC165(account)) {\n // query support of each interface in interfaceIds\n for (uint256 i = 0; i < interfaceIds.length; i++) {\n interfaceIdsSupported[i] = _supportsERC165Interface(account, interfaceIds[i]);\n }\n }\n\n return interfaceIdsSupported;\n }\n\n /**\n * @dev Returns true if `account` supports all the interfaces defined in\n * `interfaceIds`. Support for {IERC165} itself is queried automatically.\n *\n * Batch-querying can lead to gas savings by skipping repeated checks for\n * {IERC165} support.\n *\n * See {IERC165-supportsInterface}.\n */\n function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {\n // query support of ERC165 itself\n if (!supportsERC165(account)) {\n return false;\n }\n\n // query support of each interface in _interfaceIds\n for (uint256 i = 0; i < interfaceIds.length; i++) {\n if (!_supportsERC165Interface(account, interfaceIds[i])) {\n return false;\n }\n }\n\n // all interfaces supported\n return true;\n }\n\n /**\n * @notice Query if a contract implements an interface, does not check ERC165 support\n * @param account The address of the contract to query for support of an interface\n * @param interfaceId The interface identifier, as specified in ERC-165\n * @return true if the contract at account indicates support of the interface with\n * identifier interfaceId, false otherwise\n * @dev Assumes that account contains a contract that supports ERC165, otherwise\n * the behavior of this method is undefined. This precondition can be checked\n * with {supportsERC165}.\n * Interface identification is specified in ERC-165.\n */\n function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) {\n bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);\n (bool success, bytes memory result) = account.staticcall{gas: 30000}(encodedParams);\n if (result.length < 32) return false;\n return success && abi.decode(result, (bool));\n }\n}\n" @@ -316,32 +316,32 @@ "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n function safeTransfer(\n IERC20 token,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(\n IERC20 token,\n address from,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n uint256 newAllowance = token.allowance(address(this), spender) + value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n uint256 newAllowance = oldAllowance - value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) {\n // Return data is optional\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" }, - "contracts/JBETHERC20SplitsPayer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBSplitsPayer.sol';\nimport './interfaces/IJBSplitsStore.sol';\nimport './libraries/JBConstants.sol';\nimport './JBETHERC20ProjectPayer.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\n\n @dev\n Adheres to -\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBETHERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBETHERC20SplitsPayer is JBETHERC20ProjectPayer, ReentrancyGuard, IJBSplitsPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The ID of project for which the default splits are stored. \n */\n uint256 public override defaultSplitsProjectId;\n\n /**\n @notice\n The domain within which the default splits are stored. \n */\n uint256 public override defaultSplitsDomain;\n\n /**\n @notice\n The group within which the default splits are stored. \n */\n uint256 public override defaultSplitsGroup;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBETHERC20ProjectPayer, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n/**\n @param _splitsStore A contract that stores splits for each project.\n*/\n constructor(\n IJBSplitsStore _splitsStore\n )\n JBETHERC20ProjectPayer(\n _splitsStore.directory()\n )\n {\n splitsStore = _splitsStore;\n }\n /**\n @dev The re-initialize check is done in the inherited paroject payer\n \n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n function initialize(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external override {\n\n super.initialize(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _preferAddToBalance,\n _owner\n );\n\n defaultSplitsProjectId = _defaultSplitsProjectId;\n defaultSplitsDomain = _defaultSplitsDomain;\n defaultSplitsGroup = _defaultSplitsGroup;\n }\n\n\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default split group using the stored default properties.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override nonReentrant {\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n JBTokens.ETH,\n address(this).balance,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // If there is no leftover amount, nothing left to pay.\n if (_leftoverAmount == 0) return;\n\n // If there's a default project ID, try to pay it.\n if (defaultProjectId != 0)\n if (defaultPreferAddToBalance)\n // Pay the project by adding to its balance if prefered.\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.ETH,\n _leftoverAmount,\n 18, // decimals.\n defaultMemo,\n defaultMetadata\n );\n // Otherwise, issue a payment to the project.\n else\n _pay(\n defaultProjectId,\n JBTokens.ETH,\n _leftoverAmount,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n 0, // min returned tokens.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else\n Address.sendValue(\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(tx.origin),\n _leftoverAmount\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the splits in the splits store that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n @param _groupedSplits The split groups to set.\n */\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n JBGroupedSplits[] memory _groupedSplits\n ) external virtual override onlyOwner {\n // Set the splits in the store.\n splitsStore.set(_projectId, _domain, _groupedSplits);\n\n // Set the splits reference.\n setDefaultSplitsReference(_projectId, _domain, _group);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the location of the splits that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n */\n function setDefaultSplitsReference(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) public virtual override onlyOwner {\n // Set the default splits project ID if it's changing.\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\n\n // Set the default splits domain if it's changing.\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\n\n // Set the default splits group if it's changing.\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\n\n emit SetDefaultSplitsReference(_projectId, _domain, _group, msg.sender);\n }\n\n /** \n @notice \n Make a payment to the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Pay any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to pay it.\n if (_projectId != 0) {\n _pay(\n _projectId,\n _token,\n _leftoverAmount,\n _decimals,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? payable(_beneficiary) : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit Pay(\n _projectId,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event. \n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Distribute any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to add to its balance.\n if (_projectId != 0)\n // Add to the project's balance.\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\n\n // Otherwise, send a payment to the beneficiary.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit AddToBalance(\n _projectId,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splitsProjectId The ID of the project to which the splits belong.\n @param _splitsDomain The splits domain to which the group belongs.\n @param _splitsGroup The splits group to pay.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payToSplits(\n uint256 _splitsProjectId,\n uint256 _splitsDomain,\n uint256 _splitsGroup,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Pay the splits.\n leftoverAmount = _payTo(\n splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup),\n _token,\n _amount,\n _decimals,\n _defaultBeneficiary\n );\n emit DistributeToSplitGroup(_splitsProjectId, _splitsDomain, _splitsGroup, msg.sender);\n }\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splits The splits.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payTo(\n JBSplit[] memory _splits,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Set the leftover amount to the initial balance.\n leftoverAmount = _amount;\n\n // Settle between all splits.\n for (uint256 i; i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[i];\n\n // The amount to send towards the split.\n uint256 _splitAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n if (_splitAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n _token,\n _splitAmount,\n _decimals,\n defaultProjectId,\n 0,\n _split\n );\n\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\n if (_token != JBTokens.ETH)\n IERC20(_token).safeApprove(address(_split.allocator), _splitAmount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _splitAmount : 0;\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n if (_split.preferAddToBalance)\n _addToBalanceOf(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n 0,\n _split.preferClaimed,\n defaultMemo,\n defaultMetadata\n );\n } else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : payable(_defaultBeneficiary),\n _splitAmount\n );\n // Or, transfer the ERC20.\n else {\n IERC20(_token).safeTransfer(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n _splitAmount\n );\n }\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _splitAmount;\n }\n\n emit DistributeToSplit(_split, _splitAmount, _defaultBeneficiary, msg.sender);\n\n unchecked {\n ++i;\n }\n }\n }\n}\n" + "contracts/JBGasTokenERC20SplitsPayer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBSplitsPayer.sol';\nimport './interfaces/IJBSplitsStore.sol';\nimport './libraries/JBConstants.sol';\nimport './JBGasTokenERC20ProjectPayer.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\n\n @dev\n Adheres to -\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBGasTokenERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBGasTokenERC20SplitsPayer is JBGasTokenERC20ProjectPayer, ReentrancyGuard, IJBSplitsPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The ID of project for which the default splits are stored. \n */\n uint256 public override defaultSplitsProjectId;\n\n /**\n @notice\n The domain within which the default splits are stored. \n */\n uint256 public override defaultSplitsDomain;\n\n /**\n @notice\n The group within which the default splits are stored. \n */\n uint256 public override defaultSplitsGroup;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBGasTokenERC20ProjectPayer, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n/**\n @param _splitsStore A contract that stores splits for each project.\n*/\n constructor(\n IJBSplitsStore _splitsStore\n )\n JBGasTokenERC20ProjectPayer(\n _splitsStore.directory()\n )\n {\n splitsStore = _splitsStore;\n }\n /**\n @dev The re-initialize check is done in the inherited paroject payer\n \n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n function initialize(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external override {\n\n super.initialize(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _preferAddToBalance,\n _owner\n );\n\n defaultSplitsProjectId = _defaultSplitsProjectId;\n defaultSplitsDomain = _defaultSplitsDomain;\n defaultSplitsGroup = _defaultSplitsGroup;\n }\n\n\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default split group using the stored default properties.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override nonReentrant {\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // If there is no leftover amount, nothing left to pay.\n if (_leftoverAmount == 0) return;\n\n // If there's a default project ID, try to pay it.\n if (defaultProjectId != 0)\n if (defaultPreferAddToBalance)\n // Pay the project by adding to its balance if prefered.\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n _leftoverAmount,\n 18, // decimals.\n defaultMemo,\n defaultMetadata\n );\n // Otherwise, issue a payment to the project.\n else\n _pay(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n _leftoverAmount,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n 0, // min returned tokens.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else\n Address.sendValue(\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(tx.origin),\n _leftoverAmount\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the splits in the splits store that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n @param _groupedSplits The split groups to set.\n */\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n JBGroupedSplits[] memory _groupedSplits\n ) external virtual override onlyOwner {\n // Set the splits in the store.\n splitsStore.set(_projectId, _domain, _groupedSplits);\n\n // Set the splits reference.\n setDefaultSplitsReference(_projectId, _domain, _group);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the location of the splits that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n */\n function setDefaultSplitsReference(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) public virtual override onlyOwner {\n // Set the default splits project ID if it's changing.\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\n\n // Set the default splits domain if it's changing.\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\n\n // Set the default splits group if it's changing.\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\n\n emit SetDefaultSplitsReference(_projectId, _domain, _group, msg.sender);\n }\n\n /** \n @notice \n Make a payment to the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Pay any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to pay it.\n if (_projectId != 0) {\n _pay(\n _projectId,\n _token,\n _leftoverAmount,\n _decimals,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? payable(_beneficiary) : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit Pay(\n _projectId,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event. \n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Distribute any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to add to its balance.\n if (_projectId != 0)\n // Add to the project's balance.\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\n\n // Otherwise, send a payment to the beneficiary.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit AddToBalance(\n _projectId,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splitsProjectId The ID of the project to which the splits belong.\n @param _splitsDomain The splits domain to which the group belongs.\n @param _splitsGroup The splits group to pay.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payToSplits(\n uint256 _splitsProjectId,\n uint256 _splitsDomain,\n uint256 _splitsGroup,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Pay the splits.\n leftoverAmount = _payTo(\n splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup),\n _token,\n _amount,\n _decimals,\n _defaultBeneficiary\n );\n emit DistributeToSplitGroup(_splitsProjectId, _splitsDomain, _splitsGroup, msg.sender);\n }\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splits The splits.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payTo(\n JBSplit[] memory _splits,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Set the leftover amount to the initial balance.\n leftoverAmount = _amount;\n\n // Settle between all splits.\n for (uint256 i; i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[i];\n\n // The amount to send towards the split.\n uint256 _splitAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n if (_splitAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n _token,\n _splitAmount,\n _decimals,\n defaultProjectId,\n 0,\n _split\n );\n\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN)\n IERC20(_token).safeApprove(address(_split.allocator), _splitAmount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _splitAmount : 0;\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n if (_split.preferAddToBalance)\n _addToBalanceOf(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n 0,\n _split.preferClaimed,\n defaultMemo,\n defaultMetadata\n );\n } else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : payable(_defaultBeneficiary),\n _splitAmount\n );\n // Or, transfer the ERC20.\n else {\n IERC20(_token).safeTransfer(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n _splitAmount\n );\n }\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _splitAmount;\n }\n\n emit DistributeToSplit(_split, _splitAmount, _defaultBeneficiary, msg.sender);\n\n unchecked {\n ++i;\n }\n }\n }\n}\n" }, "contracts/interfaces/IJBSplitsPayer.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './../structs/JBSplit.sol';\nimport './../structs/JBGroupedSplits.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBSplitsPayer is IERC165 {\n event SetDefaultSplitsReference(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n address caller\n );\n event Pay(\n uint256 indexed projectId,\n address beneficiary,\n address token,\n uint256 amount,\n uint256 decimals,\n uint256 leftoverAmount,\n uint256 minReturnedTokens,\n bool preferClaimedTokens,\n string memo,\n bytes metadata,\n address caller\n );\n\n event AddToBalance(\n uint256 indexed projectId,\n address beneficiary,\n address token,\n uint256 amount,\n uint256 decimals,\n uint256 leftoverAmount,\n string memo,\n bytes metadata,\n address caller\n );\n\n event DistributeToSplitGroup(\n uint256 indexed projectId,\n uint256 indexed domain,\n uint256 indexed group,\n address caller\n );\n\n event DistributeToSplit(\n JBSplit split,\n uint256 amount,\n address defaultBeneficiary,\n address caller\n );\n\n function defaultSplitsProjectId() external view returns (uint256);\n\n function defaultSplitsDomain() external view returns (uint256);\n\n function defaultSplitsGroup() external view returns (uint256);\n\n function splitsStore() external view returns (IJBSplitsStore);\n\n function initialize(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external;\n\n function setDefaultSplitsReference(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) external;\n\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n JBGroupedSplits[] memory _splitsGroup\n ) external;\n}\n" }, - "contracts/JBETHERC20ProjectPayer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport './interfaces/IJBProjectPayer.sol';\nimport './libraries/JBTokens.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ERC165: Introspection on interface adherance. \n*/\ncontract JBETHERC20ProjectPayer is Ownable, ERC165, IJBProjectPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // -------------------------- custom errors -------------------------- //\n //*********************************************************************//\n error INCORRECT_DECIMAL_AMOUNT();\n error ALREADY_INITIALIZED();\n error NO_MSG_VALUE_ALLOWED();\n error TERMINAL_NOT_FOUND();\n\n //*********************************************************************//\n // ------------------- public immutable properties ------------------- //\n //*********************************************************************//\n\n /**\n @notice \n A contract storing directories of terminals and controllers for each project.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice \n The deployer associated with this implementation. Used to rule out double initialization.\n */\n address public immutable override projectPayerDeployer;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The ID of the project that should be used to forward this contract's received payments.\n */\n uint256 public override defaultProjectId;\n\n /** \n @notice \n The beneficiary that should be used in the payment made when this contract receives payments.\n */\n address payable public override defaultBeneficiary;\n\n /** \n @notice \n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\n */\n bool public override defaultPreferClaimedTokens;\n\n /** \n @notice \n The memo that should be used in the payment made when this contract receives payments.\n */\n string public override defaultMemo;\n\n /** \n @notice \n The metadata that should be used in the payment made when this contract receives payments.\n */\n bytes public override defaultMetadata;\n\n /**\n @notice \n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n bool public override defaultPreferAddToBalance;\n\n //*********************************************************************//\n // ------------------------- public views ---------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructors --------------------------- //\n //*********************************************************************//\n\n /**\n @dev This is the constructor of the implementation. The directory is shared between project payers and is\n immutable. If a new JBDirectory is needed, a new JBProjectPayerDeployer should be deployed.\n @param _directory A contract storing directories of terminals and controllers for each project.\n */\n constructor(IJBDirectory _directory) {\n directory = _directory;\n projectPayerDeployer = msg.sender;\n }\n\n /** \n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n function initialize(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) public {\n if(msg.sender != projectPayerDeployer) revert ALREADY_INITIALIZED();\n\n defaultProjectId = _defaultProjectId;\n defaultBeneficiary = _defaultBeneficiary;\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\n defaultMemo = _defaultMemo;\n defaultMetadata = _defaultMetadata;\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default project ID using the stored default properties.\n\n @dev\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override {\n if (defaultPreferAddToBalance)\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.ETH,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n defaultProjectId,\n JBTokens.ETH,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultBeneficiary == address(0) ? tx.origin : defaultBeneficiary,\n 0, // Can't determine expectation of returned tokens ahead of time.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\n\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _beneficiary The address that'll receive the project's tokens. \n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _memo The memo that'll be used. \n @param _metadata The metadata that'll be sent. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external virtual override onlyOwner {\n // Set the default project ID if it has changed.\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\n\n // Set the default beneficiary if it has changed.\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\n\n // Set the default claimed token preference if it has changed.\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\n defaultPreferClaimedTokens = _preferClaimedTokens;\n\n // Set the default memo if it has changed.\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\n defaultMemo = _memo;\n\n // Set the default metadata if it has changed.\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\n defaultMetadata = _metadata;\n\n // Set the add to balance preference if it has changed.\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n\n emit SetDefaultValues(\n _projectId,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata,\n _defaultPreferAddToBalance,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _pay(\n _projectId,\n _token,\n _amount,\n _decimals,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. \n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source and delegate, if provided.\n */\n function _pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.ETH) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\n\n // Send funds to the terminal.\n // If the token is ETH, send it in msg.value.\n _terminal.pay{value: _payableValue}(\n _projectId,\n _amount, // ignored if the token is JBTokens.ETH.\n _token,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.ETH) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\n\n // Add to balance so tokens don't get issued.\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\n }\n}\n" + "contracts/JBGasTokenERC20ProjectPayer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport './interfaces/IJBProjectPayer.sol';\nimport './libraries/JBTokens.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ERC165: Introspection on interface adherance. \n*/\ncontract JBGasTokenERC20ProjectPayer is Ownable, ERC165, IJBProjectPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // -------------------------- custom errors -------------------------- //\n //*********************************************************************//\n error INCORRECT_DECIMAL_AMOUNT();\n error ALREADY_INITIALIZED();\n error NO_MSG_VALUE_ALLOWED();\n error TERMINAL_NOT_FOUND();\n\n //*********************************************************************//\n // ------------------- public immutable properties ------------------- //\n //*********************************************************************//\n\n /**\n @notice \n A contract storing directories of terminals and controllers for each project.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice \n The deployer associated with this implementation. Used to rule out double initialization.\n */\n address public immutable override projectPayerDeployer;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The ID of the project that should be used to forward this contract's received payments.\n */\n uint256 public override defaultProjectId;\n\n /** \n @notice \n The beneficiary that should be used in the payment made when this contract receives payments.\n */\n address payable public override defaultBeneficiary;\n\n /** \n @notice \n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\n */\n bool public override defaultPreferClaimedTokens;\n\n /** \n @notice \n The memo that should be used in the payment made when this contract receives payments.\n */\n string public override defaultMemo;\n\n /** \n @notice \n The metadata that should be used in the payment made when this contract receives payments.\n */\n bytes public override defaultMetadata;\n\n /**\n @notice \n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n bool public override defaultPreferAddToBalance;\n\n //*********************************************************************//\n // ------------------------- public views ---------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructors --------------------------- //\n //*********************************************************************//\n\n /**\n @dev This is the constructor of the implementation. The directory is shared between project payers and is\n immutable. If a new JBDirectory is needed, a new JBProjectPayerDeployer should be deployed.\n @param _directory A contract storing directories of terminals and controllers for each project.\n */\n constructor(IJBDirectory _directory) {\n directory = _directory;\n projectPayerDeployer = msg.sender;\n }\n\n /** \n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n function initialize(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) public {\n if(msg.sender != projectPayerDeployer) revert ALREADY_INITIALIZED();\n\n defaultProjectId = _defaultProjectId;\n defaultBeneficiary = _defaultBeneficiary;\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\n defaultMemo = _defaultMemo;\n defaultMetadata = _defaultMetadata;\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default project ID using the stored default properties.\n\n @dev\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override {\n if (defaultPreferAddToBalance)\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultBeneficiary == address(0) ? tx.origin : defaultBeneficiary,\n 0, // Can't determine expectation of returned tokens ahead of time.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\n\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _beneficiary The address that'll receive the project's tokens. \n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _memo The memo that'll be used. \n @param _metadata The metadata that'll be sent. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external virtual override onlyOwner {\n // Set the default project ID if it has changed.\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\n\n // Set the default beneficiary if it has changed.\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\n\n // Set the default claimed token preference if it has changed.\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\n defaultPreferClaimedTokens = _preferClaimedTokens;\n\n // Set the default memo if it has changed.\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\n defaultMemo = _memo;\n\n // Set the default metadata if it has changed.\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\n defaultMetadata = _metadata;\n\n // Set the add to balance preference if it has changed.\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n\n emit SetDefaultValues(\n _projectId,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata,\n _defaultPreferAddToBalance,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _pay(\n _projectId,\n _token,\n _amount,\n _decimals,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. \n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source and delegate, if provided.\n */\n function _pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send funds to the terminal.\n // If the token is ETH, send it in msg.value.\n _terminal.pay{value: _payableValue}(\n _projectId,\n _amount, // ignored if the token is JBTokens.GAS_TOKEN.\n _token,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Add to balance so tokens don't get issued.\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\n }\n}\n" }, "contracts/interfaces/IJBProjectPayer.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport '@openzeppelin/contracts/utils/introspection/IERC165.sol';\nimport './IJBDirectory.sol';\n\ninterface IJBProjectPayer is IERC165 {\n event SetDefaultValues(\n uint256 indexed projectId,\n address indexed beneficiary,\n bool preferClaimedTokens,\n string memo,\n bytes metadata,\n bool preferAddToBalance,\n address caller\n );\n\n function directory() external view returns (IJBDirectory);\n\n function projectPayerDeployer() external view returns (address);\n\n function defaultProjectId() external view returns (uint256);\n\n function defaultBeneficiary() external view returns (address payable);\n\n function defaultPreferClaimedTokens() external view returns (bool);\n\n function defaultMemo() external view returns (string memory);\n\n function defaultMetadata() external view returns (bytes memory);\n\n function defaultPreferAddToBalance() external view returns (bool);\n\n function initialize(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external;\n\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external;\n\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) external payable;\n\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) external payable;\n\n receive() external payable;\n}\n" }, - "contracts/JBETHERC20SplitsPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport { Clones } from '@openzeppelin/contracts/proxy/Clones.sol';\n\nimport './interfaces/IJBETHERC20SplitsPayerDeployer.sol';\nimport './structs/JBSplit.sol';\nimport './structs/JBGroupedSplits.sol';\nimport './JBETHERC20SplitsPayer.sol';\n\n/** \n @notice \n Deploys splits payer contracts.\n\n @dev\n Adheres to -\n IJBETHERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBETHERC20SplitsPayerDeployer is IJBETHERC20SplitsPayerDeployer {\n\n address immutable implementation;\n\n IJBSplitsStore immutable splitsStore;\n\n constructor(IJBSplitsStore _splitsStore) {\n implementation = address(new JBETHERC20SplitsPayer(_splitsStore));\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @dev\n This contract must have Operator permissions over the SET_SPLITS permission of the specified `_defaultSplitsProjectId`.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplits The splits to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBSplitsPayer splitsPayer) {\n // Use this contract's address as the domain.\n uint256 _domain = uint256(uint160(address(this)));\n\n // Create the random hash using data unique to this instance that'll be used as the storage domain.\n uint256 _group = uint256(keccak256(abi.encodePacked(msg.sender, block.number)));\n\n // Set the splits in the store.\n JBGroupedSplits[] memory _groupedSplits;\n _groupedSplits = new JBGroupedSplits[](1);\n _groupedSplits[0] = JBGroupedSplits(_group, _defaultSplits);\n _splitsStore.set(_defaultSplitsProjectId, _domain, _groupedSplits);\n\n return\n deploySplitsPayer(\n _defaultSplitsProjectId,\n _domain,\n _group,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n }\n\n //*********************************************************************//\n // ---------------------- public transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) public override returns (IJBSplitsPayer splitsPayer) {\n\n // Deploy the splits payer.\n splitsPayer = IJBSplitsPayer(payable(Clones.clone(implementation)));\n\n splitsPayer.initialize(\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeploySplitsPayer(\n splitsPayer,\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner,\n msg.sender\n );\n }\n}\n" + "contracts/JBGasTokenERC20SplitsPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport { Clones } from '@openzeppelin/contracts/proxy/Clones.sol';\n\nimport './interfaces/IJBGasTokenERC20SplitsPayerDeployer.sol';\nimport './structs/JBSplit.sol';\nimport './structs/JBGroupedSplits.sol';\nimport './JBGasTokenERC20SplitsPayer.sol';\n\n/** \n @notice \n Deploys splits payer contracts.\n\n @dev\n Adheres to -\n IJBGasTokenERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBGasTokenERC20SplitsPayerDeployer is IJBGasTokenERC20SplitsPayerDeployer {\n\n address immutable implementation;\n\n IJBSplitsStore immutable splitsStore;\n\n constructor(IJBSplitsStore _splitsStore) {\n implementation = address(new JBGasTokenERC20SplitsPayer(_splitsStore));\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @dev\n This contract must have Operator permissions over the SET_SPLITS permission of the specified `_defaultSplitsProjectId`.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplits The splits to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBSplitsPayer splitsPayer) {\n // Use this contract's address as the domain.\n uint256 _domain = uint256(uint160(address(this)));\n\n // Create the random hash using data unique to this instance that'll be used as the storage domain.\n uint256 _group = uint256(keccak256(abi.encodePacked(msg.sender, block.number)));\n\n // Set the splits in the store.\n JBGroupedSplits[] memory _groupedSplits;\n _groupedSplits = new JBGroupedSplits[](1);\n _groupedSplits[0] = JBGroupedSplits(_group, _defaultSplits);\n _splitsStore.set(_defaultSplitsProjectId, _domain, _groupedSplits);\n\n return\n deploySplitsPayer(\n _defaultSplitsProjectId,\n _domain,\n _group,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n }\n\n //*********************************************************************//\n // ---------------------- public transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) public override returns (IJBSplitsPayer splitsPayer) {\n\n // Deploy the splits payer.\n splitsPayer = IJBSplitsPayer(payable(Clones.clone(implementation)));\n\n splitsPayer.initialize(\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeploySplitsPayer(\n splitsPayer,\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner,\n msg.sender\n );\n }\n}\n" }, "@openzeppelin/contracts/proxy/Clones.sol": { "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/Clones.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for\n * deploying minimal proxy contracts, also known as \"clones\".\n *\n * > To simply and cheaply clone contract functionality in an immutable way, this standard specifies\n * > a minimal bytecode implementation that delegates all calls to a known, fixed address.\n *\n * The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2`\n * (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the\n * deterministic method.\n *\n * _Available since v3.4._\n */\nlibrary Clones {\n /**\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.\n *\n * This function uses the create opcode, which should never revert.\n */\n function clone(address implementation) internal returns (address instance) {\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\n mstore(add(ptr, 0x14), shl(0x60, implementation))\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\n instance := create(0, ptr, 0x37)\n }\n require(instance != address(0), \"ERC1167: create failed\");\n }\n\n /**\n * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.\n *\n * This function uses the create2 opcode and a `salt` to deterministically deploy\n * the clone. Using the same `implementation` and `salt` multiple time will revert, since\n * the clones cannot be deployed twice at the same address.\n */\n function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) {\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\n mstore(add(ptr, 0x14), shl(0x60, implementation))\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)\n instance := create2(0, ptr, 0x37, salt)\n }\n require(instance != address(0), \"ERC1167: create2 failed\");\n }\n\n /**\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\n */\n function predictDeterministicAddress(\n address implementation,\n bytes32 salt,\n address deployer\n ) internal pure returns (address predicted) {\n assembly {\n let ptr := mload(0x40)\n mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)\n mstore(add(ptr, 0x14), shl(0x60, implementation))\n mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf3ff00000000000000000000000000000000)\n mstore(add(ptr, 0x38), shl(0x60, deployer))\n mstore(add(ptr, 0x4c), salt)\n mstore(add(ptr, 0x6c), keccak256(ptr, 0x37))\n predicted := keccak256(add(ptr, 0x37), 0x55)\n }\n }\n\n /**\n * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.\n */\n function predictDeterministicAddress(address implementation, bytes32 salt)\n internal\n view\n returns (address predicted)\n {\n return predictDeterministicAddress(implementation, salt, address(this));\n }\n}\n" }, - "contracts/interfaces/IJBETHERC20SplitsPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBSplitsPayer.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBETHERC20SplitsPayerDeployer {\n event DeploySplitsPayer(\n IJBSplitsPayer indexed splitsPayer,\n uint256 defaultSplitsProjectId,\n uint256 defaultSplitsDomain,\n uint256 defaultSplitsGroup,\n IJBSplitsStore splitsStore,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n address owner,\n address caller\n );\n\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string calldata _defaultMemo,\n bytes calldata _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n}\n" + "contracts/interfaces/IJBGasTokenERC20SplitsPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBSplitsPayer.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBGasTokenERC20SplitsPayerDeployer {\n event DeploySplitsPayer(\n IJBSplitsPayer indexed splitsPayer,\n uint256 defaultSplitsProjectId,\n uint256 defaultSplitsDomain,\n uint256 defaultSplitsGroup,\n IJBSplitsStore splitsStore,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n address owner,\n address caller\n );\n\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string calldata _defaultMemo,\n bytes calldata _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n}\n" }, - "contracts/JBETHERC20ProjectPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport { Clones } from '@openzeppelin/contracts/proxy/Clones.sol';\n\nimport './interfaces/IJBETHERC20ProjectPayerDeployer.sol';\nimport './JBETHERC20ProjectPayer.sol';\n\n/** \n @notice \n Deploys project payer contracts.\n\n @dev\n Adheres to -\n IJBETHERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBETHERC20ProjectPayerDeployer is IJBETHERC20ProjectPayerDeployer {\n\n address immutable implementation;\n\n IJBDirectory immutable directory;\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n */\n constructor(IJBDirectory _directory) {\n implementation = address(new JBETHERC20ProjectPayer(_directory));\n directory = _directory;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new project payer contract.\n\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the project payer contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the project payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the project payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the project payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the project payer.\n\n @return projectPayer The project payer contract.\n */\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBProjectPayer projectPayer) {\n // Deploy the project payer.\n projectPayer = IJBProjectPayer(payable(Clones.clone(implementation)));\n\n // Initialize the project payer.\n projectPayer.initialize(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeployProjectPayer(\n projectPayer,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n directory,\n _owner,\n msg.sender\n );\n }\n}\n" + "contracts/JBGasTokenERC20ProjectPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport { Clones } from '@openzeppelin/contracts/proxy/Clones.sol';\n\nimport './interfaces/IJBGasTokenERC20ProjectPayerDeployer.sol';\nimport './JBGasTokenERC20ProjectPayer.sol';\n\n/** \n @notice \n Deploys project payer contracts.\n\n @dev\n Adheres to -\n IJBGasTokenERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBGasTokenERC20ProjectPayerDeployer is IJBGasTokenERC20ProjectPayerDeployer {\n\n address immutable implementation;\n\n IJBDirectory immutable directory;\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n */\n constructor(IJBDirectory _directory) {\n implementation = address(new JBGasTokenERC20ProjectPayer(_directory));\n directory = _directory;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new project payer contract.\n\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the project payer contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the project payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the project payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the project payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the project payer.\n\n @return projectPayer The project payer contract.\n */\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBProjectPayer projectPayer) {\n // Deploy the project payer.\n projectPayer = IJBProjectPayer(payable(Clones.clone(implementation)));\n\n // Initialize the project payer.\n projectPayer.initialize(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeployProjectPayer(\n projectPayer,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n directory,\n _owner,\n msg.sender\n );\n }\n}\n" }, - "contracts/interfaces/IJBETHERC20ProjectPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBDirectory.sol';\nimport './IJBProjectPayer.sol';\n\ninterface IJBETHERC20ProjectPayerDeployer {\n event DeployProjectPayer(\n IJBProjectPayer indexed projectPayer,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n IJBDirectory directory,\n address owner,\n address caller\n );\n\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBProjectPayer projectPayer);\n}\n" + "contracts/interfaces/IJBGasTokenERC20ProjectPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBDirectory.sol';\nimport './IJBProjectPayer.sol';\n\ninterface IJBGasTokenERC20ProjectPayerDeployer {\n event DeployProjectPayer(\n IJBProjectPayer indexed projectPayer,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n IJBDirectory directory,\n address owner,\n address caller\n );\n\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBProjectPayer projectPayer);\n}\n" }, "contracts/JBDirectory.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport './abstract/JBOperatable.sol';\nimport './interfaces/IJBDirectory.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './libraries/JBOperations.sol';\n\n/**\n @notice\n Keeps a reference of which terminal contracts each project is currently accepting funds through, and which controller contract is managing each project's tokens and funding cycles.\n\n @dev\n Adheres to -\n IJBDirectory: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\ncontract JBDirectory is JBOperatable, Ownable, IJBDirectory {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error DUPLICATE_TERMINALS();\n error INVALID_PROJECT_ID_IN_DIRECTORY();\n error SET_CONTROLLER_NOT_ALLOWED();\n error SET_TERMINALS_NOT_ALLOWED();\n error TOKEN_NOT_ACCEPTED();\n\n //*********************************************************************//\n // --------------------- private stored properties ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n For each project ID, the terminals that are currently managing its funds.\n\n _projectId The ID of the project to get terminals of.\n */\n mapping(uint256 => IJBPaymentTerminal[]) private _terminalsOf;\n\n /**\n @notice\n The project's primary terminal for a token.\n\n _projectId The ID of the project to get the primary terminal of.\n _token The token to get the project's primary terminal of.\n */\n mapping(uint256 => mapping(address => IJBPaymentTerminal)) private _primaryTerminalOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n For each project ID, the controller that manages how terminals interact with tokens and funding cycles.\n\n _projectId The ID of the project to get the controller of.\n */\n mapping(uint256 => address) public override controllerOf;\n\n /**\n @notice\n Addresses that can set a project's first controller on their behalf. These addresses/contracts have been vetted and verified by this contract's owner.\n\n _address The address that is either allowed or not.\n */\n mapping(address => bool) public override isAllowedToSetFirstController;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n For each project ID, the terminals that are currently managing its funds.\n\n @param _projectId The ID of the project to get terminals of.\n\n @return An array of terminal addresses.\n */\n function terminalsOf(uint256 _projectId)\n external\n view\n override\n returns (IJBPaymentTerminal[] memory)\n {\n return _terminalsOf[_projectId];\n }\n\n /**\n @notice\n The primary terminal that is managing funds for a project for a specified token.\n\n @dev\n The zero address is returned if a terminal isn't found for the specified token.\n\n @param _projectId The ID of the project to get a terminal for.\n @param _token The token the terminal accepts.\n\n @return The primary terminal for the project for the specified token.\n */\n function primaryTerminalOf(uint256 _projectId, address _token)\n external\n view\n override\n returns (IJBPaymentTerminal)\n {\n // Keep a reference to the primary terminal for the provided project ID and token.\n IJBPaymentTerminal _primaryTerminal = _primaryTerminalOf[_projectId][_token];\n\n // If a primary terminal for the token was specifically set and it's one of the project's terminals, return it.\n if (\n _primaryTerminal != IJBPaymentTerminal(address(0)) &&\n isTerminalOf(_projectId, _primaryTerminal)\n ) return _primaryTerminal;\n\n // Keep a reference to the number of terminals the project has.\n uint256 _numberOfTerminals = _terminalsOf[_projectId].length;\n\n // Return the first terminal which accepts the specified token.\n for (uint256 _i; _i < _numberOfTerminals; ) {\n // Keep a reference to the terminal being iterated on.\n IJBPaymentTerminal _terminal = _terminalsOf[_projectId][_i];\n\n // If the terminal accepts the specified token, return it.\n if (_terminal.acceptsToken(_token, _projectId)) return _terminal;\n\n unchecked {\n ++_i;\n }\n }\n\n // Not found.\n return IJBPaymentTerminal(address(0));\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Whether or not a specified terminal is a terminal of the specified project.\n\n @param _projectId The ID of the project to check within.\n @param _terminal The address of the terminal to check for.\n\n @return A flag indicating whether or not the specified terminal is a terminal of the specified project.\n */\n function isTerminalOf(uint256 _projectId, IJBPaymentTerminal _terminal)\n public\n view\n override\n returns (bool)\n {\n // Keep a reference to the number of terminals the project has.\n uint256 _numberOfTerminals = _terminalsOf[_projectId].length;\n\n // Loop through and return true if the terminal is contained.\n for (uint256 _i; _i < _numberOfTerminals; ) {\n // If the terminal being iterated on matches the provided terminal, return true.\n if (_terminalsOf[_projectId][_i] == _terminal) return true;\n\n unchecked {\n ++_i;\n }\n }\n\n // Otherwise, return false.\n return false;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _owner The address that will own the contract.\n */\n constructor(\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBFundingCycleStore _fundingCycleStore,\n address _owner\n ) JBOperatable(_operatorStore) {\n projects = _projects;\n fundingCycleStore = _fundingCycleStore;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Update the controller that manages how terminals interact with the ecosystem.\n\n @dev\n A controller can be set if:\n - the message sender is the project owner or an operator having the correct authorization.\n - the message sender is the project's current controller.\n - or, an allowedlisted address is setting a controller for a project that doesn't already have a controller.\n\n @param _projectId The ID of the project to set a new controller for.\n @param _controller The new controller to set.\n */\n function setControllerOf(uint256 _projectId, address _controller)\n external\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.SET_CONTROLLER,\n (msg.sender == address(controllerOf[_projectId]) ||\n (isAllowedToSetFirstController[msg.sender] && controllerOf[_projectId] == address(0)))\n )\n {\n // The project must exist.\n if (projects.count() < _projectId) revert INVALID_PROJECT_ID_IN_DIRECTORY();\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Setting controller is allowed if called from the current controller, or if the project doesn't have a current controller, or if the project's funding cycle allows setting the controller. Revert otherwise.\n if (\n msg.sender != address(controllerOf[_projectId]) &&\n controllerOf[_projectId] != address(0) &&\n !_fundingCycle.global().allowSetController\n ) revert SET_CONTROLLER_NOT_ALLOWED();\n\n // Set the new controller.\n controllerOf[_projectId] = _controller;\n\n emit SetController(_projectId, _controller, msg.sender);\n }\n\n /** \n @notice \n Set a project's terminals.\n\n @dev\n Only a project owner, an operator, or its controller can set its terminals.\n\n @param _projectId The ID of the project having terminals set.\n @param _terminals The terminal to set.\n */\n function setTerminalsOf(uint256 _projectId, IJBPaymentTerminal[] calldata _terminals)\n external\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.SET_TERMINALS,\n msg.sender == address(controllerOf[_projectId])\n )\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Setting terminals must be allowed if not called from the current controller.\n if (\n msg.sender != address(controllerOf[_projectId]) && !_fundingCycle.global().allowSetTerminals\n ) revert SET_TERMINALS_NOT_ALLOWED();\n\n // Set the stored terminals for the project.\n _terminalsOf[_projectId] = _terminals;\n\n // Make sure duplicates were not added.\n if (_terminals.length > 1) {\n for (uint256 _i; _i < _terminals.length; ) {\n for (uint256 _j = _i + 1; _j < _terminals.length; ) {\n if (_terminals[_i] == _terminals[_j]) revert DUPLICATE_TERMINALS();\n\n unchecked {\n ++_j;\n }\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n emit SetTerminals(_projectId, _terminals, msg.sender);\n }\n\n /**\n @notice\n Project's can set which terminal should be their primary for a particular token.\n This is useful in case a project has several terminals connected for a particular token.\n\n @dev\n The terminal will be set as the primary terminal where ecosystem contracts should route tokens.\n\n @dev\n If setting a newly added terminal and the funding cycle doesn't allow new terminals, the caller must be the current controller.\n\n @param _projectId The ID of the project for which a primary token is being set.\n @param _token The token to set the primary terminal of.\n @param _terminal The terminal to make primary.\n */\n function setPrimaryTerminalOf(\n uint256 _projectId,\n address _token,\n IJBPaymentTerminal _terminal\n )\n external\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.SET_PRIMARY_TERMINAL)\n {\n // Can't set the primary terminal for a token if it doesn't accept the token.\n if (!_terminal.acceptsToken(_token, _projectId)) revert TOKEN_NOT_ACCEPTED();\n\n // Add the terminal to the project if it hasn't been already.\n _addTerminalIfNeeded(_projectId, _terminal);\n\n // Store the terminal as the primary for the particular token.\n _primaryTerminalOf[_projectId][_token] = _terminal;\n\n emit SetPrimaryTerminal(_projectId, _token, _terminal, msg.sender);\n }\n\n /** \n @notice\t\n Set a contract to the list of trusted addresses that can set a first controller for any project.\t\n\n @dev\n The owner can add addresses which are allowed to change projects' first controllers. \n These addresses are known and vetted controllers as well as contracts designed to launch new projects. \n A project can set its own controller without it being on the allow list.\n\n @dev\n If you would like an address/contract allowlisted, please reach out to the contract owner.\n\n @param _address The address to allow or revoke allowance from.\n @param _flag Whether allowance is being added or revoked.\n */\n function setIsAllowedToSetFirstController(address _address, bool _flag)\n external\n override\n onlyOwner\n {\n // Set the flag in the allowlist.\n isAllowedToSetFirstController[_address] = _flag;\n\n emit SetIsAllowedToSetFirstController(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Add a terminal to a project's list of terminals if it hasn't been already.\n\n @param _projectId The ID of the project having a terminal added.\n @param _terminal The terminal to add.\n */\n function _addTerminalIfNeeded(uint256 _projectId, IJBPaymentTerminal _terminal) private {\n // Check that the terminal has not already been added.\n if (isTerminalOf(_projectId, _terminal)) return;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Setting terminals must be allowed if not called from the current controller.\n if (\n msg.sender != address(controllerOf[_projectId]) && !_fundingCycle.global().allowSetTerminals\n ) revert SET_TERMINALS_NOT_ALLOWED();\n\n // Add the new terminal.\n _terminalsOf[_projectId].push(_terminal);\n\n emit AddTerminal(_projectId, _terminal, msg.sender);\n }\n}\n" @@ -365,10 +365,10 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './interfaces/IJBOperatorStore.sol';\n\n/** \n @notice\n Stores operator permissions for all addresses. Addresses can give permissions to any other address to take specific indexed actions on their behalf.\n\n @dev\n Adheres to -\n IJBOperatorStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBOperatorStore is IJBOperatorStore {\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error PERMISSION_INDEX_OUT_OF_BOUNDS();\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice\n The permissions that an operator has been given to operate on a specific domain.\n \n @dev\n An account can give an operator permissions that only pertain to a specific domain namespace.\n There is no domain with a value of 0 – accounts can use the 0 domain to give an operator\n permissions to all domains on their behalf.\n\n @dev\n Permissions are stored in a packed `uint256`. Each 256 bits represents the on/off state of a permission. Applications can specify the significance of each index.\n\n _operator The address of the operator.\n _account The address of the account being operated.\n _domain The domain within which the permissions apply. Applications can use the domain namespace as they wish.\n */\n mapping(address => mapping(address => mapping(uint256 => uint256))) public override permissionsOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Whether or not an operator has the permission to take a certain action pertaining to the specified domain.\n\n @param _operator The operator to check.\n @param _account The account that has given out permissions to the operator.\n @param _domain The domain that the operator has been given permissions to operate.\n @param _permissionIndex The permission index to check for.\n\n @return A flag indicating whether the operator has the specified permission.\n */\n function hasPermission(\n address _operator,\n address _account,\n uint256 _domain,\n uint256 _permissionIndex\n ) external view override returns (bool) {\n if (_permissionIndex > 255) revert PERMISSION_INDEX_OUT_OF_BOUNDS();\n\n return (((permissionsOf[_operator][_account][_domain] >> _permissionIndex) & 1) == 1);\n }\n\n /** \n @notice \n Whether or not an operator has the permission to take certain actions pertaining to the specified domain.\n\n @param _operator The operator to check.\n @param _account The account that has given out permissions to the operator.\n @param _domain The domain that the operator has been given permissions to operate.\n @param _permissionIndexes An array of permission indexes to check for.\n\n @return A flag indicating whether the operator has all specified permissions.\n */\n function hasPermissions(\n address _operator,\n address _account,\n uint256 _domain,\n uint256[] calldata _permissionIndexes\n ) external view override returns (bool) {\n for (uint256 _i; _i < _permissionIndexes.length; ) {\n uint256 _permissionIndex = _permissionIndexes[_i];\n\n if (_permissionIndex > 255) revert PERMISSION_INDEX_OUT_OF_BOUNDS();\n\n if (((permissionsOf[_operator][_account][_domain] >> _permissionIndex) & 1) == 0)\n return false;\n\n unchecked {\n ++_i;\n }\n }\n return true;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Sets permissions for an operators.\n\n @dev\n Only an address can set its own operators.\n\n @param _operatorData The data that specifies the params for the operator being set.\n */\n function setOperator(JBOperatorData calldata _operatorData) external override {\n // Pack the indexes into a uint256.\n uint256 _packed = _packedPermissions(_operatorData.permissionIndexes);\n\n // Store the new value.\n permissionsOf[_operatorData.operator][msg.sender][_operatorData.domain] = _packed;\n\n emit SetOperator(\n _operatorData.operator,\n msg.sender,\n _operatorData.domain,\n _operatorData.permissionIndexes,\n _packed\n );\n }\n\n /**\n @notice\n Sets permissions for many operators.\n\n @dev\n Only an address can set its own operators.\n\n @param _operatorData The data that specify the params for each operator being set.\n */\n function setOperators(JBOperatorData[] calldata _operatorData) external override {\n for (uint256 _i; _i < _operatorData.length; ) {\n // Pack the indexes into a uint256.\n uint256 _packed = _packedPermissions(_operatorData[_i].permissionIndexes);\n\n // Store the new value.\n permissionsOf[_operatorData[_i].operator][msg.sender][_operatorData[_i].domain] = _packed;\n\n emit SetOperator(\n _operatorData[_i].operator,\n msg.sender,\n _operatorData[_i].domain,\n _operatorData[_i].permissionIndexes,\n _packed\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Converts an array of permission indexes to a packed `uint256`.\n\n @param _indexes The indexes of the permissions to pack.\n\n @return packed The packed value.\n */\n function _packedPermissions(uint256[] calldata _indexes) private pure returns (uint256 packed) {\n for (uint256 _i; _i < _indexes.length; ) {\n uint256 _index = _indexes[_i];\n\n if (_index > 255) revert PERMISSION_INDEX_OUT_OF_BOUNDS();\n\n // Turn the bit at the index on.\n packed |= 1 << _index;\n\n unchecked {\n ++_i;\n }\n }\n }\n}\n" }, "contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBPayDelegateAllocation.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal is\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n IJBPayoutRedemptionPaymentTerminal\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n @dev\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.ETH)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.ETH, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance.\n */\n function _balance() internal view virtual returns (uint256);\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.ETH) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual {\n _from; // Prevents unused var compiler and natspec complaints.\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\n {\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\n\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _forwardedAmount,\n _beneficiary,\n _memo,\n _metadata\n );\n\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\n\n emit DelegateDidRedeem(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n }\n\n // Take the fee.\n _fee = _feeEligibleDistributionAmount != 0\n ? _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n )\n : 0;\n\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\n if (_leftoverDistributionAmount != 0) {\n // Subtract the fee from the net leftover amount.\n netLeftoverDistributionAmount =\n _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n\n // Transfer the amount to the project owner.\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n // The total percentage available to split\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = _split.percent == leftoverPercentage\n ? leftoverAmount\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\n\n // Decrement the leftover percentage.\n leftoverPercentage -= _split.percent;\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount;\n\n if (_payoutAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\n isFeelessAddress[address(_split.allocator)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n _netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n // If this terminal's token is ETH, send it in msg.value.\n _split.allocator.allocate{value: token == JBTokens.ETH ? _netPayoutAmount : 0}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // Save gas if this contract is being used as the terminal.\n if (_terminal == this) {\n // This distribution does not incur a fee.\n _netPayoutAmount = _payoutAmount;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\n else\n _pay(\n _netPayoutAmount,\n address(this),\n _split.projectId,\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n } else {\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_terminal)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _netPayoutAmount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _terminal.addToBalanceOf{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n '',\n _projectMetadata\n );\n else\n _terminal.pay{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n }\n } else {\n // Keep a reference to the beneficiary.\n address payable _beneficiary = _split.beneficiary != address(0)\n ? _split.beneficiary\n : payable(msg.sender);\n\n // If there's a full discount, this distribution is not eligible for a fee.\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(address(this), _beneficiary, _netPayoutAmount);\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n */\n function _processFee(uint256 _amount, address _beneficiary) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\n\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\n if (_terminal == this)\n _pay(\n _amount,\n address(this),\n _FEE_BENEFICIARY_PROJECT_ID,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the local pay call.\n else {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _amount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _amount : 0;\n\n // Send the payment.\n _terminal.pay{value: _payableValue}(\n _FEE_BENEFICIARY_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the external pay call of the correct terminal.\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\n {\n JBPayDelegateAllocation[] memory _delegateAllocations;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n _forwardedAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n // Get a reference to the number of delegates to allocate to.\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\n\n emit DelegateDidPay(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n unchecked {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\n IJBPaymentTerminal(address(0))\n ) return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge != IJBFeeGauge(address(0)))\n // If the guage reverts, keep the discount at 0.\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n // If the fee discount is greater than the max, we ignore the return value\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\n } catch {\n return 0;\n }\n\n return 0;\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBPayDelegateAllocation.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal is\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n IJBPayoutRedemptionPaymentTerminal\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n @dev\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.GAS_CURRENCY)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.GAS_CURRENCY, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance.\n */\n function _balance() internal view virtual returns (uint256);\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.GAS_TOKEN) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual {\n _from; // Prevents unused var compiler and natspec complaints.\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\n {\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\n\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _forwardedAmount,\n _beneficiary,\n _memo,\n _metadata\n );\n\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\n\n emit DelegateDidRedeem(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n }\n\n // Take the fee.\n _fee = _feeEligibleDistributionAmount != 0\n ? _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n )\n : 0;\n\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\n if (_leftoverDistributionAmount != 0) {\n // Subtract the fee from the net leftover amount.\n netLeftoverDistributionAmount =\n _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n\n // Transfer the amount to the project owner.\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n // The total percentage available to split\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = _split.percent == leftoverPercentage\n ? leftoverAmount\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\n\n // Decrement the leftover percentage.\n leftoverPercentage -= _split.percent;\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount;\n\n if (_payoutAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\n isFeelessAddress[address(_split.allocator)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n _netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n // If this terminal's token is ETH, send it in msg.value.\n _split.allocator.allocate{value: token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // Save gas if this contract is being used as the terminal.\n if (_terminal == this) {\n // This distribution does not incur a fee.\n _netPayoutAmount = _payoutAmount;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\n else\n _pay(\n _netPayoutAmount,\n address(this),\n _split.projectId,\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n } else {\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_terminal)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _terminal.addToBalanceOf{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n '',\n _projectMetadata\n );\n else\n _terminal.pay{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n }\n } else {\n // Keep a reference to the beneficiary.\n address payable _beneficiary = _split.beneficiary != address(0)\n ? _split.beneficiary\n : payable(msg.sender);\n\n // If there's a full discount, this distribution is not eligible for a fee.\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(address(this), _beneficiary, _netPayoutAmount);\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n */\n function _processFee(uint256 _amount, address _beneficiary) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\n\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\n if (_terminal == this)\n _pay(\n _amount,\n address(this),\n _FEE_BENEFICIARY_PROJECT_ID,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the local pay call.\n else {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _amount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send the payment.\n _terminal.pay{value: _payableValue}(\n _FEE_BENEFICIARY_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the external pay call of the correct terminal.\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\n {\n JBPayDelegateAllocation[] memory _delegateAllocations;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n _forwardedAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n // Get a reference to the number of delegates to allocate to.\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\n\n emit DelegateDidPay(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n unchecked {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\n IJBPaymentTerminal(address(0))\n ) return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge != IJBFeeGauge(address(0)))\n // If the guage reverts, keep the discount at 0.\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n // If the fee discount is greater than the max, we ignore the return value\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\n } catch {\n return 0;\n }\n\n return 0;\n }\n}\n" }, "contracts/JBETHPaymentTerminal.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\nimport './libraries/JBSplitsGroups.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return address(this).balance;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n JBTokens.ETH,\n 18, // 18 decimals.\n JBCurrencies.ETH,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\nimport './libraries/JBSplitsGroups.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return address(this).balance;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n JBTokens.GAS_TOKEN,\n 18, // 18 decimals.\n JBCurrencies.GAS_CURRENCY,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n}\n" }, "contracts/JBERC20PaymentTerminal.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\n\n/** \n @notice \n Manages the inflows and outflows of an ERC-20 token.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\ncontract JBERC20PaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return IERC20(token).balanceOf(address(this));\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n IERC20Metadata _token,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n address(_token),\n _token.decimals(),\n _currency,\n _baseWeightCurrency,\n _payoutSplitsGroup,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from == address(this)\n ? IERC20(token).safeTransfer(_to, _amount)\n : IERC20(token).safeTransferFrom(_from, _to, _amount);\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal override {\n IERC20(token).safeApprove(_to, _amount);\n }\n}\n" diff --git a/deployments/mainnet/solcInputs/ed590828cf2d3bd8e9fe992c4f52dc83.json b/deployments/mainnet/solcInputs/ed590828cf2d3bd8e9fe992c4f52dc83.json index 4f93930ae..ca1a732f6 100644 --- a/deployments/mainnet/solcInputs/ed590828cf2d3bd8e9fe992c4f52dc83.json +++ b/deployments/mainnet/solcInputs/ed590828cf2d3bd8e9fe992c4f52dc83.json @@ -101,10 +101,10 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './../interfaces/IJBOperatable.sol';\n\n/** \n @notice\n Modifiers to allow access to functions based on the message sender's operator status.\n\n @dev\n Adheres to -\n IJBOperatable: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\nabstract contract JBOperatable is IJBOperatable {\n //*********************************************************************//\n // --------------------------- custom errors -------------------------- //\n //*********************************************************************//\n error UNAUTHORIZED();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Only allows the speficied account or an operator of the account to proceed. \n\n @param _account The account to check for.\n @param _domain The domain namespace to look for an operator within. \n @param _permissionIndex The index of the permission to check for. \n */\n modifier requirePermission(\n address _account,\n uint256 _domain,\n uint256 _permissionIndex\n ) {\n _requirePermission(_account, _domain, _permissionIndex);\n _;\n }\n\n /** \n @notice\n Only allows the speficied account, an operator of the account to proceed, or a truthy override flag. \n\n @param _account The account to check for.\n @param _domain The domain namespace to look for an operator within. \n @param _permissionIndex The index of the permission to check for. \n @param _override A condition to force allowance for.\n */\n modifier requirePermissionAllowingOverride(\n address _account,\n uint256 _domain,\n uint256 _permissionIndex,\n bool _override\n ) {\n _requirePermissionAllowingOverride(_account, _domain, _permissionIndex, _override);\n _;\n }\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /** \n @notice \n A contract storing operator assignments.\n */\n IJBOperatorStore public immutable override operatorStore;\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _operatorStore A contract storing operator assignments.\n */\n constructor(IJBOperatorStore _operatorStore) {\n operatorStore = _operatorStore;\n }\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Require the message sender is either the account or has the specified permission.\n\n @param _account The account to allow.\n @param _domain The domain namespace within which the permission index will be checked.\n @param _permissionIndex The permission index that an operator must have within the specified domain to be allowed.\n */\n function _requirePermission(\n address _account,\n uint256 _domain,\n uint256 _permissionIndex\n ) internal view {\n if (\n msg.sender != _account &&\n !operatorStore.hasPermission(msg.sender, _account, _domain, _permissionIndex) &&\n !operatorStore.hasPermission(msg.sender, _account, 0, _permissionIndex)\n ) revert UNAUTHORIZED();\n }\n\n /** \n @notice\n Require the message sender is either the account, has the specified permission, or the override condition is true.\n\n @param _account The account to allow.\n @param _domain The domain namespace within which the permission index will be checked.\n @param _domain The permission index that an operator must have within the specified domain to be allowed.\n @param _override The override condition to allow.\n */\n function _requirePermissionAllowingOverride(\n address _account,\n uint256 _domain,\n uint256 _permissionIndex,\n bool _override\n ) internal view {\n if (\n !_override &&\n msg.sender != _account &&\n !operatorStore.hasPermission(msg.sender, _account, _domain, _permissionIndex) &&\n !operatorStore.hasPermission(msg.sender, _account, 0, _permissionIndex)\n ) revert UNAUTHORIZED();\n }\n}\n" }, "contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBPayDelegateAllocation.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal is\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n IJBPayoutRedemptionPaymentTerminal\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n @dev\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.ETH)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.ETH, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance.\n */\n function _balance() internal view virtual returns (uint256);\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.ETH) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual {\n _from; // Prevents unused var compiler and natspec complaints.\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\n {\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\n\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _forwardedAmount,\n _beneficiary,\n _memo,\n _metadata\n );\n\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\n\n emit DelegateDidRedeem(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n }\n\n // Take the fee.\n _fee = _feeEligibleDistributionAmount != 0\n ? _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n )\n : 0;\n\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\n if (_leftoverDistributionAmount != 0) {\n // Subtract the fee from the net leftover amount.\n netLeftoverDistributionAmount =\n _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n\n // Transfer the amount to the project owner.\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n // The total percentage available to split\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = _split.percent == leftoverPercentage\n ? leftoverAmount\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\n\n // Decrement the leftover percentage.\n leftoverPercentage -= _split.percent;\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount;\n\n if (_payoutAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\n isFeelessAddress[address(_split.allocator)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n _netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n // If this terminal's token is ETH, send it in msg.value.\n _split.allocator.allocate{value: token == JBTokens.ETH ? _netPayoutAmount : 0}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // Save gas if this contract is being used as the terminal.\n if (_terminal == this) {\n // This distribution does not incur a fee.\n _netPayoutAmount = _payoutAmount;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\n else\n _pay(\n _netPayoutAmount,\n address(this),\n _split.projectId,\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n } else {\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_terminal)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _netPayoutAmount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _terminal.addToBalanceOf{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n '',\n _projectMetadata\n );\n else\n _terminal.pay{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n }\n } else {\n // Keep a reference to the beneficiary.\n address payable _beneficiary = _split.beneficiary != address(0)\n ? _split.beneficiary\n : payable(msg.sender);\n\n // If there's a full discount, this distribution is not eligible for a fee.\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(address(this), _beneficiary, _netPayoutAmount);\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n */\n function _processFee(uint256 _amount, address _beneficiary) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\n\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\n if (_terminal == this)\n _pay(\n _amount,\n address(this),\n _FEE_BENEFICIARY_PROJECT_ID,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the local pay call.\n else {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _amount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _amount : 0;\n\n // Send the payment.\n _terminal.pay{value: _payableValue}(\n _FEE_BENEFICIARY_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the external pay call of the correct terminal.\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\n {\n JBPayDelegateAllocation[] memory _delegateAllocations;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n _forwardedAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n // Get a reference to the number of delegates to allocate to.\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\n\n emit DelegateDidPay(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n unchecked {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\n IJBPaymentTerminal(address(0))\n ) return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge != IJBFeeGauge(address(0)))\n // If the guage reverts, keep the discount at 0.\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n // If the fee discount is greater than the max, we ignore the return value\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\n } catch {\n return 0;\n }\n\n return 0;\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBPayDelegateAllocation.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal is\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n IJBPayoutRedemptionPaymentTerminal\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n @dev\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.GAS_CURRENCY)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.GAS_CURRENCY, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance.\n */\n function _balance() internal view virtual returns (uint256);\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _memo);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _useAllowanceOf(_projectId, _amount, _currency, _minReturnedTokens, _beneficiary, _memo);\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.GAS_TOKEN) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance while only refunding held fees if the funds aren't originating from a feeless terminal.\n _addToBalanceOf(_projectId, _amount, !isFeelessAddress[msg.sender], _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual {\n _from; // Prevents unused var compiler and natspec complaints.\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\n {\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\n\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _forwardedAmount,\n _beneficiary,\n _memo,\n _metadata\n );\n\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\n\n emit DelegateDidRedeem(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _memo A memo to pass along to the emitted event.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n string calldata _memo\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n }\n\n // Take the fee.\n _fee = _feeEligibleDistributionAmount != 0\n ? _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n )\n : 0;\n\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\n if (_leftoverDistributionAmount != 0) {\n // Subtract the fee from the net leftover amount.\n netLeftoverDistributionAmount =\n _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n\n // Transfer the amount to the project owner.\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n // The total percentage available to split\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = _split.percent == leftoverPercentage\n ? leftoverAmount\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\n\n // Decrement the leftover percentage.\n leftoverPercentage -= _split.percent;\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount;\n\n if (_payoutAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\n isFeelessAddress[address(_split.allocator)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n // This distribution is eligible for a fee since the funds are leaving the ecosystem.\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), _netPayoutAmount);\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n _netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n // If this terminal's token is ETH, send it in msg.value.\n _split.allocator.allocate{value: token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // Save gas if this contract is being used as the terminal.\n if (_terminal == this) {\n // This distribution does not incur a fee.\n _netPayoutAmount = _payoutAmount;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _addToBalanceOf(_split.projectId, _netPayoutAmount, false, '', _projectMetadata);\n else\n _pay(\n _netPayoutAmount,\n address(this),\n _split.projectId,\n (_split.beneficiary != address(0)) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n } else {\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_terminal)]\n )\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _netPayoutAmount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _netPayoutAmount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n _terminal.addToBalanceOf{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n '',\n _projectMetadata\n );\n else\n _terminal.pay{value: _payableValue}(\n _split.projectId,\n _netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n );\n }\n } else {\n // Keep a reference to the beneficiary.\n address payable _beneficiary = _split.beneficiary != address(0)\n ? _split.beneficiary\n : payable(msg.sender);\n\n // If there's a full discount, this distribution is not eligible for a fee.\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\n _netPayoutAmount = _payoutAmount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\n else {\n unchecked {\n _netPayoutAmount = _payoutAmount - _feeAmount(_payoutAmount, fee, _feeDiscount);\n }\n\n feeEligibleDistributionAmount += _payoutAmount;\n }\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(address(this), _beneficiary, _netPayoutAmount);\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n */\n function _processFee(uint256 _amount, address _beneficiary) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\n\n // When processing the admin fee, save gas if the admin is using this contract as its terminal.\n if (_terminal == this)\n _pay(\n _amount,\n address(this),\n _FEE_BENEFICIARY_PROJECT_ID,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the local pay call.\n else {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), _amount);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send the payment.\n _terminal.pay{value: _payableValue}(\n _FEE_BENEFICIARY_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n bytes('')\n ); // Use the external pay call of the correct terminal.\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\n {\n JBPayDelegateAllocation[] memory _delegateAllocations;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n _forwardedAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n // Get a reference to the number of delegates to allocate to.\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\n\n emit DelegateDidPay(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n unchecked {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\n IJBPaymentTerminal(address(0))\n ) return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge != IJBFeeGauge(address(0)))\n // If the guage reverts, keep the discount at 0.\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n // If the fee discount is greater than the max, we ignore the return value\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\n } catch {\n return 0;\n }\n\n return 0;\n }\n}\n" }, "contracts/abstract/JBPayoutRedemptionPaymentTerminal3_1.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/utils/introspection/ERC165Checker.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal3_1.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBPayDelegateAllocation.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal3_1: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal3_1 is\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n IJBPayoutRedemptionPaymentTerminal3_1\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n @dev\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.ETH)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.ETH, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal3_1).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal3_1).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal3_1).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance.\n */\n function _balance() internal view virtual returns (uint256);\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n bytes calldata _metadata\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _metadata);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes calldata _metadata\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _useAllowanceOf(\n _projectId,\n _amount,\n _currency,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n // Do not refund held fees by default.\n addToBalanceOf(_projectId, _amount, _token, false, _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary, _projectId);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n bool _shouldRefundHeldFees,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.ETH) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance.\n _addToBalanceOf(_projectId, _amount, _shouldRefundHeldFees, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual {\n _from; // Prevents unused var compiler and natspec complaints.\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered if a transfer should be undone\n\n @param _to The address to which the transfer went.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _cancelTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\n {\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\n\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _forwardedAmount,\n _beneficiary,\n _memo,\n _metadata\n );\n\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\n\n emit DelegateDidRedeem(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n bytes calldata _metadata\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n }\n\n // Take the fee.\n _fee = _feeEligibleDistributionAmount != 0\n ? _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n )\n : 0;\n\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\n if (_leftoverDistributionAmount != 0) {\n // Subtract the fee from the net leftover amount.\n netLeftoverDistributionAmount =\n _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n\n // Transfer the amount to the project owner.\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes calldata _metadata\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n // The total percentage available to split\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = _split.percent == leftoverPercentage\n ? leftoverAmount\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\n\n // Decrement the leftover percentage.\n leftoverPercentage -= _split.percent;\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount = _distributeToPayoutSplit(\n _split,\n _projectId,\n _group,\n _payoutAmount,\n _feeDiscount\n );\n\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (_netPayoutAmount != 0 && _netPayoutAmount != _payoutAmount)\n feeEligibleDistributionAmount += _payoutAmount;\n\n if (_payoutAmount > 0) {\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _payoutAmount,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Pays out a split for a project's funding cycle configuration.\n \n @param _split The split to distribute payouts to.\n @param _amount The total amount being distributed to the split, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return netPayoutAmount The amount sent to the split after subtracting fees.\n */\n function _distributeToPayoutSplit(\n JBSplit memory _split,\n uint256 _projectId,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 netPayoutAmount) {\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_split.allocator)]\n )\n netPayoutAmount = _amount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\n }\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), netPayoutAmount);\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n uint256 _error;\n bytes memory _reason;\n\n if (\n ERC165Checker.supportsInterface(\n address(_split.allocator),\n type(IJBSplitAllocator).interfaceId\n )\n )\n // If this terminal's token is ETH, send it in msg.value.\n try _split.allocator.allocate{value: token == JBTokens.ETH ? netPayoutAmount : 0}(_data) {\n\n } catch (bytes memory reason) {\n _reason = reason;\n _error = 1;\n }\n else _error = 2;\n\n\n if (_error != 0) {\n // Trigger any inhereted post-transfer cancelation logic.\n _cancelTransferTo(address(_split.allocator), netPayoutAmount);\n\n // Set the net payout amount to 0 to signal the reversion.\n netPayoutAmount = 0;\n\n // Add undistributed amount back to project's balance.\n store.recordAddedBalanceFor(_projectId, _amount);\n\n emit PayoutReverted(_projectId, _split, _amount, _error == 1 ? _reason : abi.encode(\"IERC165 fail\"), msg.sender);\n }\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (\n _terminal == this ||\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\n isFeelessAddress[address(_terminal)]\n )\n netPayoutAmount = _amount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\n }\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), netPayoutAmount);\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n try\n _terminal.addToBalanceOf{value: token == JBTokens.ETH ? netPayoutAmount : 0}(\n _split.projectId,\n netPayoutAmount,\n token,\n '',\n _projectMetadata\n )\n {} catch (bytes memory reason) {\n // Trigger any inhereted post-transfer cancelation logic.\n _cancelTransferTo(address(_terminal), netPayoutAmount);\n\n // Set the net payout amount to 0 to signal the reversion.\n netPayoutAmount = 0;\n\n // Add undistributed amount back to project's balance.\n store.recordAddedBalanceFor(_projectId, _amount);\n\n emit PayoutReverted(_projectId, _split, _amount, reason, msg.sender);\n }\n else\n try\n _terminal.pay{value: token == JBTokens.ETH ? netPayoutAmount : 0}(\n _split.projectId,\n netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n )\n {} catch (bytes memory reason) {\n // Trigger any inhereted post-transfer cancelation logic.\n _cancelTransferTo(address(_terminal), netPayoutAmount);\n\n // Set the net payout amount to 0 to signal the reversion.\n netPayoutAmount = 0;\n\n // Add undistributed amount back to project's balance.\n store.recordAddedBalanceFor(_projectId, _amount);\n\n emit PayoutReverted(_projectId, _split, _amount, reason, msg.sender);\n }\n } else {\n // Keep a reference to the beneficiary.\n address payable _beneficiary = _split.beneficiary != address(0)\n ? _split.beneficiary\n : payable(msg.sender);\n\n // If there's a full discount, this distribution is not eligible for a fee.\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\n netPayoutAmount = _amount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\n else {\n unchecked {\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\n }\n }\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(address(this), _beneficiary, netPayoutAmount);\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary, _projectId); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n @param _from The project ID the fee is being paid from.\n */\n function _processFee(\n uint256 _amount,\n address _beneficiary,\n uint256 _from\n ) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.ETH ? _amount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_from));\n\n // Trigger any inherited pre-transfer logic if funds will be transferred.\n if (address(_terminal) != address(this)) _beforeTransferTo(address(_terminal), _amount);\n\n try\n // Send the fee.\n _terminal.pay{value: _payableValue}(\n _FEE_BENEFICIARY_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n _projectMetadata\n )\n {} catch (bytes memory reason) {\n // Trigger any inhereted post-transfer cancelation logic if the pre-transfer logic was triggered.\n if (address(_terminal) != address(this)) _cancelTransferTo(address(_terminal), _amount);\n\n // Add fee amount back to project's balance.\n store.recordAddedBalanceFor(_from, _amount);\n\n emit FeeReverted(_from, _FEE_BENEFICIARY_PROJECT_ID, _amount, reason, msg.sender);\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\n {\n JBPayDelegateAllocation[] memory _delegateAllocations;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n _forwardedAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n // Get a reference to the number of delegates to allocate to.\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.ETH) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\n\n emit DelegateDidPay(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n unchecked {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\n IJBPaymentTerminal(address(0))\n ) return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge != IJBFeeGauge(address(0)))\n // If the guage reverts, keep the discount at 0.\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n // If the fee discount is greater than the max, we ignore the return value\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\n } catch {\n return 0;\n }\n\n return 0;\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/utils/introspection/ERC165Checker.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './../interfaces/IJBController.sol';\nimport './../interfaces/IJBPayoutRedemptionPaymentTerminal3_1.sol';\nimport './../libraries/JBConstants.sol';\nimport './../libraries/JBCurrencies.sol';\nimport './../libraries/JBFixedPointNumber.sol';\nimport './../libraries/JBFundingCycleMetadataResolver.sol';\nimport './../libraries/JBOperations.sol';\nimport './../libraries/JBTokens.sol';\nimport './../structs/JBPayDelegateAllocation.sol';\nimport './../structs/JBTokenAmount.sol';\nimport './JBOperatable.sol';\nimport './JBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n\n @dev\n A project can transfer its funds, along with the power to reconfigure and mint/burn their tokens, from this contract to another allowed terminal of the same token type contract at any time.\n\n @dev\n Adheres to -\n IJBPayoutRedemptionPaymentTerminal3_1: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBSingleTokenPaymentTerminal: Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\nabstract contract JBPayoutRedemptionPaymentTerminal3_1 is\n JBSingleTokenPaymentTerminal,\n JBOperatable,\n Ownable,\n IJBPayoutRedemptionPaymentTerminal3_1\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error FEE_TOO_HIGH();\n error INADEQUATE_DISTRIBUTION_AMOUNT();\n error INADEQUATE_RECLAIM_AMOUNT();\n error INADEQUATE_TOKEN_COUNT();\n error NO_MSG_VALUE_ALLOWED();\n error PAY_TO_ZERO_ADDRESS();\n error PROJECT_TERMINAL_MISMATCH();\n error REDEEM_TO_ZERO_ADDRESS();\n error TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n error TERMINAL_TOKENS_INCOMPATIBLE();\n\n //*********************************************************************//\n // ---------------------------- modifiers ---------------------------- //\n //*********************************************************************//\n\n /** \n @notice \n A modifier that verifies this terminal is a terminal of provided project ID.\n */\n modifier isTerminalOf(uint256 _projectId) {\n if (!directory.isTerminalOf(_projectId, this)) revert PROJECT_TERMINAL_MISMATCH();\n _;\n }\n\n //*********************************************************************//\n // --------------------- internal stored constants ------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Maximum fee that can be set for a funding cycle configuration.\n\n @dev\n Out of MAX_FEE (50_000_000 / 1_000_000_000).\n */\n uint256 internal constant _FEE_CAP = 50_000_000;\n\n /**\n @notice\n The fee beneficiary project ID is 1, as it should be the first project launched during the deployment process.\n */\n uint256 internal constant _FEE_BENEFICIARY_PROJECT_ID = 1;\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Fees that are being held to be processed later.\n\n _projectId The ID of the project for which fees are being held.\n */\n mapping(uint256 => JBFee[]) internal _heldFeesOf;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n /**\n @notice\n The contract that stores and manages the terminal's data.\n */\n IJBSingleTokenPaymentTerminalStore public immutable override store;\n\n /**\n @notice\n The currency to base token issuance on.\n\n @dev\n If this differs from `currency`, there must be a price feed available to convert `currency` to `baseWeightCurrency`.\n */\n uint256 public immutable override baseWeightCurrency;\n\n /**\n @notice\n The group that payout splits coming from this terminal are identified by.\n */\n uint256 public immutable override payoutSplitsGroup;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The platform fee percent.\n\n @dev\n Out of MAX_FEE (25_000_000 / 1_000_000_000)\n */\n uint256 public override fee = 25_000_000; // 2.5%\n\n /**\n @notice\n The data source that returns a discount to apply to a project's fee.\n */\n IJBFeeGauge public override feeGauge;\n\n /**\n @notice\n Addresses that can be paid towards from this terminal without incurring a fee.\n\n @dev\n Only addresses that are considered to be contained within the ecosystem can be feeless. Funds sent outside the ecosystem may incur fees despite being stored as feeless.\n\n _address The address that can be paid toward.\n */\n mapping(address => bool) public override isFeelessAddress;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in this terminal for a specified project, in terms of ETH.\n\n @dev\n The current overflow is represented as a fixed point number with 18 decimals.\n\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of ETH overflow that project has in this terminal, as a fixed point number with 18 decimals.\n */\n function currentEthOverflowOf(uint256 _projectId)\n external\n view\n virtual\n override\n returns (uint256)\n {\n // Get this terminal's current overflow.\n uint256 _overflow = store.currentOverflowOf(this, _projectId);\n\n // Adjust the decimals of the fixed point number if needed to have 18 decimals.\n uint256 _adjustedOverflow = (decimals == 18)\n ? _overflow\n : JBFixedPointNumber.adjustDecimals(_overflow, decimals, 18);\n\n // Return the amount converted to ETH.\n return\n (currency == JBCurrencies.GAS_CURRENCY)\n ? _adjustedOverflow\n : PRBMath.mulDiv(\n _adjustedOverflow,\n 10**decimals,\n prices.priceFor(currency, JBCurrencies.GAS_CURRENCY, decimals)\n );\n }\n\n /**\n @notice\n The fees that are currently being held to be processed later for each project.\n\n @param _projectId The ID of the project for which fees are being held.\n\n @return An array of fees that are being held.\n */\n function heldFeesOf(uint256 _projectId) external view override returns (JBFee[] memory) {\n return _heldFeesOf[_projectId];\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBSingleTokenPaymentTerminal, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPayoutRedemptionPaymentTerminal3_1).interfaceId ||\n _interfaceId == type(IJBPayoutTerminal3_1).interfaceId ||\n _interfaceId == type(IJBAllowanceTerminal3_1).interfaceId ||\n _interfaceId == type(IJBRedemptionTerminal).interfaceId ||\n _interfaceId == type(IJBOperatable).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance.\n */\n function _balance() internal view virtual returns (uint256);\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n // payable constructor save the gas used to check msg.value==0\n address _token,\n uint256 _decimals,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n payable\n JBSingleTokenPaymentTerminal(_token, _decimals, _currency)\n JBOperatable(_operatorStore)\n {\n baseWeightCurrency = _baseWeightCurrency;\n payoutSplitsGroup = _payoutSplitsGroup;\n projects = _projects;\n directory = _directory;\n splitsStore = _splitsStore;\n prices = _prices;\n store = _store;\n\n transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _projectId The ID of the project being paid.\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _token The token being paid. This terminal ignores this property since it only manages one token. \n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function pay(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (token != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If this terminal's token is ETH, override _amount with msg.value.\n else _amount = msg.value;\n\n return\n _pay(\n _amount,\n msg.sender,\n _projectId,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _token The token being reclaimed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n )\n external\n virtual\n override\n requirePermission(_holder, _projectId, JBOperations.REDEEM)\n returns (uint256 reclaimAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _redeemTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n bytes calldata _metadata\n ) external virtual override returns (uint256 netLeftoverDistributionAmount) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return _distributePayoutsOf(_projectId, _amount, _currency, _minReturnedTokens, _metadata);\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _token The token being distributed. This terminal ignores this property since it only manages one token. \n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n address _token,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes calldata _metadata\n )\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.USE_ALLOWANCE)\n returns (uint256 netDistributedAmount)\n {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return\n _useAllowanceOf(\n _projectId,\n _amount,\n _currency,\n _minReturnedTokens,\n _beneficiary,\n _memo,\n _metadata\n );\n }\n\n /**\n @notice\n Allows a project owner to migrate its funds and operations to a new terminal that accepts the same token type.\n\n @dev\n Only a project's owner or a designated operator can migrate it.\n\n @param _projectId The ID of the project being migrated.\n @param _to The terminal contract that will gain the project's funds.\n\n @return balance The amount of funds that were migrated, as a fixed point number with the same amount of decimals as this terminal.\n */\n function migrate(uint256 _projectId, IJBPaymentTerminal _to)\n external\n virtual\n override\n requirePermission(projects.ownerOf(_projectId), _projectId, JBOperations.MIGRATE_TERMINAL)\n returns (uint256 balance)\n {\n // The terminal being migrated to must accept the same token as this terminal.\n if (!_to.acceptsToken(token, _projectId)) revert TERMINAL_TOKENS_INCOMPATIBLE();\n\n // Record the migration in the store.\n balance = store.recordMigration(_projectId);\n\n // Transfer the balance if needed.\n if (balance > 0) {\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_to), balance);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? balance : 0;\n\n // Withdraw the balance to transfer to the new terminal;\n _to.addToBalanceOf{value: _payableValue}(_projectId, balance, token, '', bytes(''));\n }\n\n emit Migrate(_projectId, _to, balance, msg.sender);\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n string calldata _memo,\n bytes calldata _metadata\n ) external payable virtual override isTerminalOf(_projectId) {\n // Do not refund held fees by default.\n addToBalanceOf(_projectId, _amount, _token, false, _memo, _metadata);\n }\n\n /**\n @notice\n Process any fees that are being held for the project.\n\n @dev\n Only a project owner, an operator, or the contract's owner can process held fees.\n\n @param _projectId The ID of the project whos held fees should be processed.\n */\n function processFees(uint256 _projectId)\n external\n virtual\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.PROCESS_FEES,\n msg.sender == owner()\n )\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the held fees.\n delete _heldFeesOf[_projectId];\n\n // Push array length in stack\n uint256 _heldFeeLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeeLength; ) {\n // Get the fee amount.\n uint256 _amount = _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n\n // Process the fee.\n _processFee(_amount, _heldFees[_i].beneficiary, _projectId);\n\n emit ProcessFee(_projectId, _amount, true, _heldFees[_i].beneficiary, msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Allows the fee to be updated.\n\n @dev\n Only the owner of this contract can change the fee.\n\n @param _fee The new fee, out of MAX_FEE.\n */\n function setFee(uint256 _fee) external virtual override onlyOwner {\n // The provided fee must be within the max.\n if (_fee > _FEE_CAP) revert FEE_TOO_HIGH();\n\n // Store the new fee.\n fee = _fee;\n\n emit SetFee(_fee, msg.sender);\n }\n\n /**\n @notice\n Allows the fee gauge to be updated.\n\n @dev\n Only the owner of this contract can change the fee gauge.\n\n @param _feeGauge The new fee gauge.\n */\n function setFeeGauge(IJBFeeGauge _feeGauge) external virtual override onlyOwner {\n // Store the new fee gauge.\n feeGauge = _feeGauge;\n\n emit SetFeeGauge(_feeGauge, msg.sender);\n }\n\n /**\n @notice\n Sets whether projects operating on this terminal can pay towards the specified address without incurring a fee.\n\n @dev\n Only the owner of this contract can set addresses as feeless.\n\n @param _address The address that can be paid towards while still bypassing fees.\n @param _flag A flag indicating whether the terminal should be feeless or not.\n */\n function setFeelessAddress(address _address, bool _flag) external virtual override onlyOwner {\n // Set the flag value.\n isFeelessAddress[_address] = _flag;\n\n emit SetFeelessAddress(_address, _flag, msg.sender);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _token The token being paid. This terminal ignores this property since it only manages one currency. \n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n address _token,\n bool _shouldRefundHeldFees,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override isTerminalOf(_projectId) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n // If this terminal's token isn't ETH, make sure no msg.value was sent, then transfer the tokens in from msg.sender.\n if (token != JBTokens.GAS_TOKEN) {\n // Amount must be greater than 0.\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = _balance();\n\n // Transfer tokens to this terminal from the msg sender.\n _transferFrom(msg.sender, payable(address(this)), _amount);\n\n // The amount should reflect the change in balance.\n _amount = _balance() - _balanceBefore;\n }\n // If the terminal's token is ETH, override `_amount` with msg.value.\n else _amount = msg.value;\n\n // Add to balance.\n _addToBalanceOf(_projectId, _amount, _shouldRefundHeldFees, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal virtual {\n _from; // Prevents unused var compiler and natspec complaints.\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /** \n @notice\n Logic to be triggered if a transfer should be undone\n\n @param _to The address to which the transfer went.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _cancelTransferTo(address _to, uint256 _amount) internal virtual {\n _to; // Prevents unused var compiler and natspec complaints.\n _amount; // Prevents unused var compiler and natspec complaints.\n }\n\n /**\n @notice\n Holders can redeem their tokens to claim the project's overflowed tokens, or to trigger rules determined by the project's current funding cycle's data source.\n\n @dev\n Only a token holder or a designated operator can redeem its tokens.\n\n @param _holder The account to redeem tokens for.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _minReturnedTokens The minimum amount of terminal tokens expected in return, as a fixed point number with the same amount of decimals as the terminal.\n @param _beneficiary The address to send the terminal tokens to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return reclaimAmount The amount of terminal tokens that the project tokens were redeemed for, as a fixed point number with 18 decimals.\n */\n function _redeemTokensOf(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 reclaimAmount) {\n // Can't send reclaimed funds to the zero address.\n if (_beneficiary == address(0)) revert REDEEM_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the redemption is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` only used within scope.\n {\n JBRedemptionDelegateAllocation[] memory _delegateAllocations;\n\n // Record the redemption.\n (_fundingCycle, reclaimAmount, _delegateAllocations, _memo) = store.recordRedemptionFor(\n _holder,\n _projectId,\n _tokenCount,\n _memo,\n _metadata\n );\n\n // The amount being reclaimed must be at least as much as was expected.\n if (reclaimAmount < _minReturnedTokens) revert INADEQUATE_RECLAIM_AMOUNT();\n\n // Burn the project tokens.\n if (_tokenCount > 0)\n IJBController(directory.controllerOf(_projectId)).burnTokensOf(\n _holder,\n _projectId,\n _tokenCount,\n '',\n false\n );\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, 0, decimals, currency);\n\n JBDidRedeemData memory _data = JBDidRedeemData(\n _holder,\n _projectId,\n _fundingCycle.configuration,\n _tokenCount,\n JBTokenAmount(token, reclaimAmount, decimals, currency),\n _forwardedAmount,\n _beneficiary,\n _memo,\n _metadata\n );\n\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBRedemptionDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didRedeem{value: _payableValue}(_data);\n\n emit DelegateDidRedeem(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n // Send the reclaimed funds to the beneficiary.\n if (reclaimAmount > 0) _transferFrom(address(this), _beneficiary, reclaimAmount);\n\n emit RedeemTokens(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _holder,\n _beneficiary,\n _tokenCount,\n reclaimAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Distributes payouts for a project with the distribution limit of its current funding cycle.\n\n @dev\n Payouts are sent to the preprogrammed splits. Any leftover is sent to the project's owner.\n\n @dev\n Anyone can distribute payouts on a project's behalf. The project can preconfigure a wildcard split that is used to send funds to msg.sender. This can be used to incentivize calling this function.\n\n @dev\n All funds distributed outside of this contract or any feeless terminals incure the protocol fee.\n\n @param _projectId The ID of the project having its payouts distributed.\n @param _amount The amount of terminal tokens to distribute, as a fixed point number with same number of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's distribution limit currency.\n @param _minReturnedTokens The minimum number of terminal tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with the same number of decimals as this terminal.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netLeftoverDistributionAmount The amount that was sent to the project owner, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _distributePayoutsOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n bytes calldata _metadata\n ) internal returns (uint256 netLeftoverDistributionAmount) {\n // Record the distribution.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordDistributionFor(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being distributed must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee\n // and receive any extra distributable funds not allocated to payout splits.\n address payable _projectOwner = payable(projects.ownerOf(_projectId));\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Scoped section prevents stack too deep. `_feeDiscount`, `_feeEligibleDistributionAmount`, and `_leftoverDistributionAmount` only used within scope.\n {\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // The amount distributed that is eligible for incurring fees.\n uint256 _feeEligibleDistributionAmount;\n\n // The amount leftover after distributing to the splits.\n uint256 _leftoverDistributionAmount;\n\n // Payout to splits and get a reference to the leftover transfer amount after all splits have been paid.\n // Also get a reference to the amount that was distributed to splits from which fees should be taken.\n (_leftoverDistributionAmount, _feeEligibleDistributionAmount) = _distributeToPayoutSplitsOf(\n _projectId,\n _fundingCycle.configuration,\n payoutSplitsGroup,\n _distributedAmount,\n _feeDiscount\n );\n\n if (_feeDiscount != JBConstants.MAX_FEE_DISCOUNT) {\n // Leftover distribution amount is also eligible for a fee since the funds are going out of the ecosystem to _beneficiary.\n unchecked {\n _feeEligibleDistributionAmount += _leftoverDistributionAmount;\n }\n }\n\n // Take the fee.\n _fee = _feeEligibleDistributionAmount != 0\n ? _takeFeeFrom(\n _projectId,\n _fundingCycle,\n _feeEligibleDistributionAmount,\n _projectOwner,\n _feeDiscount\n )\n : 0;\n\n // Transfer any remaining balance to the project owner and update returned leftover accordingly.\n if (_leftoverDistributionAmount != 0) {\n // Subtract the fee from the net leftover amount.\n netLeftoverDistributionAmount =\n _leftoverDistributionAmount -\n _feeAmount(_leftoverDistributionAmount, fee, _feeDiscount);\n\n // Transfer the amount to the project owner.\n _transferFrom(address(this), _projectOwner, netLeftoverDistributionAmount);\n }\n }\n\n emit DistributePayouts(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _projectOwner,\n _amount,\n _distributedAmount,\n _fee,\n netLeftoverDistributionAmount,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Allows a project to send funds from its overflow up to the preconfigured allowance.\n\n @dev\n Only a project's owner or a designated operator can use its allowance.\n\n @dev\n Incurs the protocol fee.\n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount of terminal tokens to use from this project's current allowance, as a fixed point number with the same amount of decimals as this terminal.\n @param _currency The expected currency of the amount being distributed. Must match the project's current funding cycle's overflow allowance currency.\n @param _minReturnedTokens The minimum number of tokens that the `_amount` should be valued at in terms of this terminal's currency, as a fixed point number with 18 decimals.\n @param _beneficiary The address to send the funds to.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the emitted event, if provided.\n\n @return netDistributedAmount The amount of tokens that was distributed to the beneficiary, as a fixed point number with the same amount of decimals as the terminal.\n */\n function _useAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency,\n uint256 _minReturnedTokens,\n address payable _beneficiary,\n string memory _memo,\n bytes calldata _metadata\n ) internal returns (uint256 netDistributedAmount) {\n // Record the use of the allowance.\n (JBFundingCycle memory _fundingCycle, uint256 _distributedAmount) = store.recordUsedAllowanceOf(\n _projectId,\n _amount,\n _currency\n );\n\n // The amount being withdrawn must be at least as much as was expected.\n if (_distributedAmount < _minReturnedTokens) revert INADEQUATE_DISTRIBUTION_AMOUNT();\n\n // Scoped section prevents stack too deep. `_fee`, `_projectOwner`, `_feeDiscount`, and `_netAmount` only used within scope.\n {\n // Keep a reference to the fee amount that was paid.\n uint256 _fee;\n\n // Get a reference to the project owner, which will receive tokens from paying the platform fee.\n address _projectOwner = projects.ownerOf(_projectId);\n\n // Get the amount of discount that should be applied to any fees taken.\n // If the fee is zero or if the fee is being used by an address that doesn't incur fees, set the discount to 100% for convenience.\n uint256 _feeDiscount = fee == 0 || isFeelessAddress[msg.sender]\n ? JBConstants.MAX_FEE_DISCOUNT\n : _currentFeeDiscount(_projectId);\n\n // Take a fee from the `_distributedAmount`, if needed.\n _fee = _feeDiscount == JBConstants.MAX_FEE_DISCOUNT\n ? 0\n : _takeFeeFrom(_projectId, _fundingCycle, _distributedAmount, _projectOwner, _feeDiscount);\n\n unchecked {\n // The net amount is the withdrawn amount without the fee.\n netDistributedAmount = _distributedAmount - _fee;\n }\n\n // Transfer any remaining balance to the beneficiary.\n if (netDistributedAmount > 0)\n _transferFrom(address(this), _beneficiary, netDistributedAmount);\n }\n\n emit UseAllowance(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _beneficiary,\n _amount,\n _distributedAmount,\n netDistributedAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Pays out splits for a project's funding cycle configuration.\n\n @param _projectId The ID of the project for which payout splits are being distributed.\n @param _domain The domain of the splits to distribute the payout between.\n @param _group The group of the splits to distribute the payout between.\n @param _amount The total amount being distributed, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return leftoverAmount If the leftover amount if the splits don't add up to 100%.\n @return feeEligibleDistributionAmount The total amount of distributions that are eligible to have fees taken from.\n */\n function _distributeToPayoutSplitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 leftoverAmount, uint256 feeEligibleDistributionAmount) {\n // Set the leftover amount to the initial amount.\n leftoverAmount = _amount;\n // The total percentage available to split\n uint256 leftoverPercentage = JBConstants.SPLITS_TOTAL_PERCENT;\n\n // Get a reference to the project's payout splits.\n JBSplit[] memory _splits = splitsStore.splitsOf(_projectId, _domain, _group);\n\n // Transfer between all splits.\n for (uint256 _i; _i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[_i];\n\n // The amount to send towards the split.\n uint256 _payoutAmount = _split.percent == leftoverPercentage\n ? leftoverAmount\n : PRBMath.mulDiv(_amount, _split.percent, JBConstants.SPLITS_TOTAL_PERCENT);\n\n // Decrement the leftover percentage.\n leftoverPercentage -= _split.percent;\n\n // The payout amount substracting any applicable incurred fees.\n uint256 _netPayoutAmount = _distributeToPayoutSplit(\n _split,\n _projectId,\n _group,\n _payoutAmount,\n _feeDiscount\n );\n\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (_netPayoutAmount != 0 && _netPayoutAmount != _payoutAmount)\n feeEligibleDistributionAmount += _payoutAmount;\n\n if (_payoutAmount > 0) {\n // Subtract from the amount to be sent to the beneficiary.\n unchecked {\n leftoverAmount = leftoverAmount - _payoutAmount;\n }\n }\n\n emit DistributeToPayoutSplit(\n _projectId,\n _domain,\n _group,\n _split,\n _payoutAmount,\n _netPayoutAmount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n\n /**\n @notice\n Pays out a split for a project's funding cycle configuration.\n \n @param _split The split to distribute payouts to.\n @param _amount The total amount being distributed to the split, as a fixed point number with the same number of decimals as this terminal.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return netPayoutAmount The amount sent to the split after subtracting fees.\n */\n function _distributeToPayoutSplit(\n JBSplit memory _split,\n uint256 _projectId,\n uint256 _group,\n uint256 _amount,\n uint256 _feeDiscount\n ) internal returns (uint256 netPayoutAmount) {\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // If the split allocator is set as feeless, this distribution is not eligible for a fee.\n if (\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT || isFeelessAddress[address(_split.allocator)]\n )\n netPayoutAmount = _amount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the allocator isn't listed as feeless.\n else {\n unchecked {\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\n }\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_split.allocator), netPayoutAmount);\n\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n token,\n netPayoutAmount,\n decimals,\n _projectId,\n _group,\n _split\n );\n\n // Trigger the allocator's `allocate` function.\n uint256 _error;\n bytes memory _reason;\n\n if (\n ERC165Checker.supportsInterface(\n address(_split.allocator),\n type(IJBSplitAllocator).interfaceId\n )\n )\n // If this terminal's token is ETH, send it in msg.value.\n try _split.allocator.allocate{value: token == JBTokens.GAS_TOKEN ? netPayoutAmount : 0}(_data) {\n\n } catch (bytes memory reason) {\n _reason = reason;\n _error = 1;\n }\n else _error = 2;\n\n\n if (_error != 0) {\n // Trigger any inhereted post-transfer cancelation logic.\n _cancelTransferTo(address(_split.allocator), netPayoutAmount);\n\n // Set the net payout amount to 0 to signal the reversion.\n netPayoutAmount = 0;\n\n // Add undistributed amount back to project's balance.\n store.recordAddedBalanceFor(_projectId, _amount);\n\n emit PayoutReverted(_projectId, _split, _amount, _error == 1 ? _reason : abi.encode(\"IERC165 fail\"), msg.sender);\n }\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n // Get a reference to the Juicebox terminal being used.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_split.projectId, token);\n\n // The project must have a terminal to send funds to.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_IN_SPLIT_ZERO_ADDRESS();\n\n // If the terminal is set as feeless, this distribution is not eligible for a fee.\n if (\n _terminal == this ||\n _feeDiscount == JBConstants.MAX_FEE_DISCOUNT ||\n isFeelessAddress[address(_terminal)]\n )\n netPayoutAmount = _amount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the terminal isn't listed as feeless.\n else {\n unchecked {\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\n }\n }\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_terminal), netPayoutAmount);\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_projectId));\n\n // Add to balance if prefered.\n if (_split.preferAddToBalance)\n try\n _terminal.addToBalanceOf{value: token == JBTokens.GAS_TOKEN ? netPayoutAmount : 0}(\n _split.projectId,\n netPayoutAmount,\n token,\n '',\n _projectMetadata\n )\n {} catch (bytes memory reason) {\n // Trigger any inhereted post-transfer cancelation logic.\n _cancelTransferTo(address(_terminal), netPayoutAmount);\n\n // Set the net payout amount to 0 to signal the reversion.\n netPayoutAmount = 0;\n\n // Add undistributed amount back to project's balance.\n store.recordAddedBalanceFor(_projectId, _amount);\n\n emit PayoutReverted(_projectId, _split, _amount, reason, msg.sender);\n }\n else\n try\n _terminal.pay{value: token == JBTokens.GAS_TOKEN ? netPayoutAmount : 0}(\n _split.projectId,\n netPayoutAmount,\n token,\n _split.beneficiary != address(0) ? _split.beneficiary : msg.sender,\n 0,\n _split.preferClaimed,\n '',\n _projectMetadata\n )\n {} catch (bytes memory reason) {\n // Trigger any inhereted post-transfer cancelation logic.\n _cancelTransferTo(address(_terminal), netPayoutAmount);\n\n // Set the net payout amount to 0 to signal the reversion.\n netPayoutAmount = 0;\n\n // Add undistributed amount back to project's balance.\n store.recordAddedBalanceFor(_projectId, _amount);\n\n emit PayoutReverted(_projectId, _split, _amount, reason, msg.sender);\n }\n } else {\n // Keep a reference to the beneficiary.\n address payable _beneficiary = _split.beneficiary != address(0)\n ? _split.beneficiary\n : payable(msg.sender);\n\n // If there's a full discount, this distribution is not eligible for a fee.\n // Don't enforce feeless address for the beneficiary since the funds are leaving the ecosystem.\n if (_feeDiscount == JBConstants.MAX_FEE_DISCOUNT)\n netPayoutAmount = _amount;\n // This distribution is eligible for a fee since the funds are leaving this contract and the beneficiary isn't listed as feeless.\n else {\n unchecked {\n netPayoutAmount = _amount - _feeAmount(_amount, fee, _feeDiscount);\n }\n }\n\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the msg.sender.\n _transferFrom(address(this), _beneficiary, netPayoutAmount);\n }\n }\n\n /**\n @notice\n Takes a fee into the platform's project, which has an id of _FEE_BENEFICIARY_PROJECT_ID.\n\n @param _projectId The ID of the project having fees taken from.\n @param _fundingCycle The funding cycle during which the fee is being taken.\n @param _amount The amount of the fee to take, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platforms tokens for.\n @param _feeDiscount The amount of discount to apply to the fee, out of the MAX_FEE.\n\n @return feeAmount The amount of the fee taken.\n */\n function _takeFeeFrom(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _amount,\n address _beneficiary,\n uint256 _feeDiscount\n ) internal returns (uint256 feeAmount) {\n feeAmount = _feeAmount(_amount, fee, _feeDiscount);\n\n if (_fundingCycle.shouldHoldFees()) {\n // Store the held fee.\n _heldFeesOf[_projectId].push(JBFee(_amount, uint32(fee), uint32(_feeDiscount), _beneficiary));\n\n emit HoldFee(_projectId, _amount, fee, _feeDiscount, _beneficiary, msg.sender);\n } else {\n // Process the fee.\n _processFee(feeAmount, _beneficiary, _projectId); // Take the fee.\n\n emit ProcessFee(_projectId, feeAmount, false, _beneficiary, msg.sender);\n }\n }\n\n /**\n @notice\n Process a fee of the specified amount.\n\n @param _amount The fee amount, as a floating point number with 18 decimals.\n @param _beneficiary The address to mint the platform's tokens for.\n @param _from The project ID the fee is being paid from.\n */\n function _processFee(\n uint256 _amount,\n address _beneficiary,\n uint256 _from\n ) internal {\n // Get the terminal for the protocol project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token);\n\n // If this terminal's token is ETH, send it in msg.value.\n uint256 _payableValue = token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send the projectId in the metadata.\n bytes memory _projectMetadata = new bytes(32);\n _projectMetadata = bytes(abi.encodePacked(_from));\n\n // Trigger any inherited pre-transfer logic if funds will be transferred.\n if (address(_terminal) != address(this)) _beforeTransferTo(address(_terminal), _amount);\n\n try\n // Send the fee.\n _terminal.pay{value: _payableValue}(\n _FEE_BENEFICIARY_PROJECT_ID,\n _amount,\n token,\n _beneficiary,\n 0,\n false,\n '',\n _projectMetadata\n )\n {} catch (bytes memory reason) {\n // Trigger any inhereted post-transfer cancelation logic if the pre-transfer logic was triggered.\n if (address(_terminal) != address(this)) _cancelTransferTo(address(_terminal), _amount);\n\n // Add fee amount back to project's balance.\n store.recordAddedBalanceFor(_from, _amount);\n\n emit FeeReverted(_from, _FEE_BENEFICIARY_PROJECT_ID, _amount, reason, msg.sender);\n }\n }\n\n /**\n @notice\n Contribute tokens to a project.\n\n @param _amount The amount of terminal tokens being received, as a fixed point number with the same amount of decimals as this terminal. If this terminal's token is ETH, this is ignored and msg.value is used in its place.\n @param _payer The address making the payment.\n @param _projectId The ID of the project being paid.\n @param _beneficiary The address to mint tokens for and pass along to the funding cycle's data source and delegate.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with the same amount of decimals as this terminal.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n\n @return beneficiaryTokenCount The number of tokens minted for the beneficiary, as a fixed point number with 18 decimals.\n */\n function _pay(\n uint256 _amount,\n address _payer,\n uint256 _projectId,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal returns (uint256 beneficiaryTokenCount) {\n // Cant send tokens to the zero address.\n if (_beneficiary == address(0)) revert PAY_TO_ZERO_ADDRESS();\n\n // Define variables that will be needed outside the scoped section below.\n // Keep a reference to the funding cycle during which the payment is being made.\n JBFundingCycle memory _fundingCycle;\n\n // Scoped section prevents stack too deep. `_delegateAllocations` and `_tokenCount` only used within scope.\n {\n JBPayDelegateAllocation[] memory _delegateAllocations;\n uint256 _tokenCount;\n\n // Bundle the amount info into a JBTokenAmount struct.\n JBTokenAmount memory _bundledAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n // Record the payment.\n (_fundingCycle, _tokenCount, _delegateAllocations, _memo) = store.recordPaymentFrom(\n _payer,\n _bundledAmount,\n _projectId,\n baseWeightCurrency,\n _beneficiary,\n _memo,\n _metadata\n );\n\n // Mint the tokens if needed.\n if (_tokenCount > 0)\n // Set token count to be the number of tokens minted for the beneficiary instead of the total amount.\n beneficiaryTokenCount = IJBController(directory.controllerOf(_projectId)).mintTokensOf(\n _projectId,\n _tokenCount,\n _beneficiary,\n '',\n _preferClaimedTokens,\n true\n );\n\n // The token count for the beneficiary must be greater than or equal to the minimum expected.\n if (beneficiaryTokenCount < _minReturnedTokens) revert INADEQUATE_TOKEN_COUNT();\n\n // If delegate allocations were specified by the data source, fulfill them.\n if (_delegateAllocations.length != 0) {\n // Keep a reference to the token amount being forwarded to the delegate.\n JBTokenAmount memory _forwardedAmount = JBTokenAmount(token, _amount, decimals, currency);\n\n JBDidPayData memory _data = JBDidPayData(\n _payer,\n _projectId,\n _fundingCycle.configuration,\n _bundledAmount,\n _forwardedAmount,\n beneficiaryTokenCount,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n\n // Get a reference to the number of delegates to allocate to.\n uint256 _numDelegates = _delegateAllocations.length;\n\n for (uint256 _i; _i < _numDelegates; ) {\n // Get a reference to the delegate being iterated on.\n JBPayDelegateAllocation memory _delegateAllocation = _delegateAllocations[_i];\n\n // Trigger any inherited pre-transfer logic.\n _beforeTransferTo(address(_delegateAllocation.delegate), _delegateAllocation.amount);\n\n // Keep track of the msg.value to use in the delegate call\n uint256 _payableValue;\n\n // If this terminal's token is ETH, send it in msg.value.\n if (token == JBTokens.GAS_TOKEN) _payableValue = _delegateAllocation.amount;\n\n // Pass the correct token forwardedAmount to the delegate\n _data.forwardedAmount.value = _delegateAllocation.amount;\n\n _delegateAllocation.delegate.didPay{value: _payableValue}(_data);\n\n emit DelegateDidPay(\n _delegateAllocation.delegate,\n _data,\n _delegateAllocation.amount,\n msg.sender\n );\n\n unchecked {\n ++_i;\n }\n }\n }\n }\n\n emit Pay(\n _fundingCycle.configuration,\n _fundingCycle.number,\n _projectId,\n _payer,\n _beneficiary,\n _amount,\n beneficiaryTokenCount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /**\n @notice\n Receives funds belonging to the specified project.\n\n @param _projectId The ID of the project to which the funds received belong.\n @param _amount The amount of tokens to add, as a fixed point number with the same number of decimals as this terminal. If this is an ETH terminal, this is ignored and msg.value is used instead.\n @param _shouldRefundHeldFees A flag indicating if held fees should be refunded based on the amount being added.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the emitted event.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n uint256 _amount,\n bool _shouldRefundHeldFees,\n string memory _memo,\n bytes memory _metadata\n ) internal {\n // Refund any held fees to make sure the project doesn't pay double for funds going in and out of the protocol.\n uint256 _refundedFees = _shouldRefundHeldFees ? _refundHeldFees(_projectId, _amount) : 0;\n\n // Record the added funds with any refunded fees.\n store.recordAddedBalanceFor(_projectId, _amount + _refundedFees);\n\n emit AddToBalance(_projectId, _amount, _refundedFees, _memo, _metadata, msg.sender);\n }\n\n /**\n @notice\n Refund fees based on the specified amount.\n\n @param _projectId The project for which fees are being refunded.\n @param _amount The amount to base the refund on, as a fixed point number with the same amount of decimals as this terminal.\n\n @return refundedFees How much fees were refunded, as a fixed point number with the same number of decimals as this terminal\n */\n function _refundHeldFees(uint256 _projectId, uint256 _amount)\n internal\n returns (uint256 refundedFees)\n {\n // Get a reference to the project's held fees.\n JBFee[] memory _heldFees = _heldFeesOf[_projectId];\n\n // Delete the current held fees.\n delete _heldFeesOf[_projectId];\n\n // Get a reference to the leftover amount once all fees have been settled.\n uint256 leftoverAmount = _amount;\n\n // Push length in stack\n uint256 _heldFeesLength = _heldFees.length;\n\n // Process each fee.\n for (uint256 _i; _i < _heldFeesLength; ) {\n if (leftoverAmount == 0) _heldFeesOf[_projectId].push(_heldFees[_i]);\n else if (leftoverAmount >= _heldFees[_i].amount) {\n unchecked {\n leftoverAmount = leftoverAmount - _heldFees[_i].amount;\n refundedFees += _feeAmount(\n _heldFees[_i].amount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount\n );\n }\n } else {\n unchecked {\n _heldFeesOf[_projectId].push(\n JBFee(\n _heldFees[_i].amount - leftoverAmount,\n _heldFees[_i].fee,\n _heldFees[_i].feeDiscount,\n _heldFees[_i].beneficiary\n )\n );\n refundedFees += _feeAmount(leftoverAmount, _heldFees[_i].fee, _heldFees[_i].feeDiscount);\n }\n leftoverAmount = 0;\n }\n\n unchecked {\n ++_i;\n }\n }\n\n emit RefundHeldFees(_projectId, _amount, refundedFees, leftoverAmount, msg.sender);\n }\n\n /** \n @notice \n Returns the fee amount based on the provided amount for the specified project.\n\n @param _amount The amount that the fee is based on, as a fixed point number with the same amount of decimals as this terminal.\n @param _fee The percentage of the fee, out of MAX_FEE. \n @param _feeDiscount The percentage discount that should be applied out of the max amount, out of MAX_FEE_DISCOUNT.\n\n @return The amount of the fee, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _feeAmount(\n uint256 _amount,\n uint256 _fee,\n uint256 _feeDiscount\n ) internal pure returns (uint256) {\n // Calculate the discounted fee.\n uint256 _discountedFee = _fee -\n PRBMath.mulDiv(_fee, _feeDiscount, JBConstants.MAX_FEE_DISCOUNT);\n\n // The amount of tokens from the `_amount` to pay as a fee.\n return\n _amount - PRBMath.mulDiv(_amount, JBConstants.MAX_FEE, _discountedFee + JBConstants.MAX_FEE);\n }\n\n /** \n @notice\n Get the fee discount from the fee gauge for the specified project.\n\n @param _projectId The ID of the project to get a fee discount for.\n \n @return feeDiscount The fee discount, which should be interpreted as a percentage out MAX_FEE_DISCOUNT.\n */\n function _currentFeeDiscount(uint256 _projectId) internal view returns (uint256) {\n // Can't take a fee if the protocol project doesn't have a terminal that accepts the token.\n if (\n directory.primaryTerminalOf(_FEE_BENEFICIARY_PROJECT_ID, token) ==\n IJBPaymentTerminal(address(0))\n ) return JBConstants.MAX_FEE_DISCOUNT;\n\n // Get the fee discount.\n if (feeGauge != IJBFeeGauge(address(0)))\n // If the guage reverts, keep the discount at 0.\n try feeGauge.currentDiscountFor(_projectId) returns (uint256 discount) {\n // If the fee discount is greater than the max, we ignore the return value\n if (discount <= JBConstants.MAX_FEE_DISCOUNT) return discount;\n } catch {\n return 0;\n }\n\n return 0;\n }\n}\n" }, "contracts/abstract/JBSingleTokenPaymentTerminal.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport './../interfaces/IJBSingleTokenPaymentTerminal.sol';\n\n/**\n @notice\n Generic terminal managing all inflows of funds into the protocol ecosystem for one token.\n\n @dev\n Adheres to -\n IJBSingleTokenPaymentTerminals: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ERC165: Introspection on interface adherance. \n*/\nabstract contract JBSingleTokenPaymentTerminal is ERC165, IJBSingleTokenPaymentTerminal {\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The token that this terminal accepts.\n */\n address public immutable override token;\n\n /**\n @notice\n The number of decimals the token fixed point amounts are expected to have.\n */\n uint256 public immutable override decimals;\n\n /**\n @notice\n The currency to use when resolving price feeds for this terminal.\n */\n uint256 public immutable override currency;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n A flag indicating if this terminal accepts the specified token.\n\n @param _token The token to check if this terminal accepts or not.\n @param _projectId The project ID to check for token acceptance.\n\n @return The flag.\n */\n function acceptsToken(address _token, uint256 _projectId) external view override returns (bool) {\n _projectId; // Prevents unused var compiler and natspec complaints.\n\n return _token == token;\n }\n\n /** \n @notice\n The decimals that should be used in fixed number accounting for the specified token.\n\n @param _token The token to check for the decimals of.\n\n @return The number of decimals for the token.\n */\n function decimalsForToken(address _token) external view override returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return decimals;\n }\n\n /** \n @notice\n The currency that should be used for the specified token.\n\n @param _token The token to check for the currency of.\n\n @return The currency index.\n */\n function currencyForToken(address _token) external view override returns (uint256) {\n _token; // Prevents unused var compiler and natspec complaints.\n\n return currency;\n }\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBPaymentTerminal).interfaceId ||\n _interfaceId == type(IJBSingleTokenPaymentTerminal).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _decimals The number of decimals the token fixed point amounts are expected to have.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n */\n constructor(\n address _token,\n uint256 _decimals,\n uint256 _currency\n ) {\n token = _token;\n decimals = _decimals;\n currency = _currency;\n }\n}\n" @@ -133,11 +133,11 @@ "contracts/interfaces/IJBDirectory.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBFundingCycleStore.sol';\nimport './IJBPaymentTerminal.sol';\nimport './IJBProjects.sol';\n\ninterface IJBDirectory {\n event SetController(uint256 indexed projectId, address indexed controller, address caller);\n\n event AddTerminal(uint256 indexed projectId, IJBPaymentTerminal indexed terminal, address caller);\n\n event SetTerminals(uint256 indexed projectId, IJBPaymentTerminal[] terminals, address caller);\n\n event SetPrimaryTerminal(\n uint256 indexed projectId,\n address indexed token,\n IJBPaymentTerminal indexed terminal,\n address caller\n );\n\n event SetIsAllowedToSetFirstController(address indexed addr, bool indexed flag, address caller);\n\n function projects() external view returns (IJBProjects);\n\n function fundingCycleStore() external view returns (IJBFundingCycleStore);\n\n function controllerOf(uint256 _projectId) external view returns (address);\n\n function isAllowedToSetFirstController(address _address) external view returns (bool);\n\n function terminalsOf(uint256 _projectId) external view returns (IJBPaymentTerminal[] memory);\n\n function isTerminalOf(uint256 _projectId, IJBPaymentTerminal _terminal)\n external\n view\n returns (bool);\n\n function primaryTerminalOf(uint256 _projectId, address _token)\n external\n view\n returns (IJBPaymentTerminal);\n\n function setControllerOf(uint256 _projectId, address _controller) external;\n\n function setTerminalsOf(uint256 _projectId, IJBPaymentTerminal[] calldata _terminals) external;\n\n function setPrimaryTerminalOf(\n uint256 _projectId,\n address _token,\n IJBPaymentTerminal _terminal\n ) external;\n\n function setIsAllowedToSetFirstController(address _address, bool _flag) external;\n}\n" }, - "contracts/interfaces/IJBETHERC20ProjectPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBDirectory.sol';\nimport './IJBProjectPayer.sol';\n\ninterface IJBETHERC20ProjectPayerDeployer {\n event DeployProjectPayer(\n IJBProjectPayer indexed projectPayer,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n IJBDirectory directory,\n address owner,\n address caller\n );\n\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external returns (IJBProjectPayer projectPayer);\n}\n" + "contracts/interfaces/IJBGasTokenERC20ProjectPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBDirectory.sol';\nimport './IJBProjectPayer.sol';\n\ninterface IJBGasTokenERC20ProjectPayerDeployer {\n event DeployProjectPayer(\n IJBProjectPayer indexed projectPayer,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n IJBDirectory directory,\n address owner,\n address caller\n );\n\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external returns (IJBProjectPayer projectPayer);\n}\n" }, - "contracts/interfaces/IJBETHERC20SplitsPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBSplitsPayer.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBETHERC20SplitsPayerDeployer {\n event DeploySplitsPayer(\n IJBSplitsPayer indexed splitsPayer,\n uint256 defaultSplitsProjectId,\n uint256 defaultSplitsDomain,\n uint256 defaultSplitsGroup,\n IJBSplitsStore splitsStore,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n address owner,\n address caller\n );\n\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string calldata _defaultMemo,\n bytes calldata _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n}\n" + "contracts/interfaces/IJBGasTokenERC20SplitsPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport './IJBSplitsPayer.sol';\nimport './IJBSplitsStore.sol';\n\ninterface IJBGasTokenERC20SplitsPayerDeployer {\n event DeploySplitsPayer(\n IJBSplitsPayer indexed splitsPayer,\n uint256 defaultSplitsProjectId,\n uint256 defaultSplitsDomain,\n uint256 defaultSplitsGroup,\n IJBSplitsStore splitsStore,\n uint256 defaultProjectId,\n address defaultBeneficiary,\n bool defaultPreferClaimedTokens,\n string defaultMemo,\n bytes defaultMetadata,\n bool preferAddToBalance,\n address owner,\n address caller\n );\n\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string calldata _defaultMemo,\n bytes calldata _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external returns (IJBSplitsPayer splitsPayer);\n}\n" }, "contracts/interfaces/IJBFeeGauge.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IJBFeeGauge {\n function currentDiscountFor(uint256 _projectId) external view returns (uint256);\n}\n" @@ -250,23 +250,23 @@ "contracts/JBERC20PaymentTerminal3_1.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal3_1.sol';\n\n/** \n @notice \n Manages the inflows and outflows of an ERC-20 token.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\ncontract JBERC20PaymentTerminal3_1 is JBPayoutRedemptionPaymentTerminal3_1 {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return IERC20(token).balanceOf(address(this));\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _token The token that this terminal manages.\n @param _currency The currency that this terminal's token adheres to for price feeds.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _payoutSplitsGroup The group that denotes payout splits from this terminal in the splits store.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n IERC20Metadata _token,\n uint256 _currency,\n uint256 _baseWeightCurrency,\n uint256 _payoutSplitsGroup,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal3_1(\n address(_token),\n _token.decimals(),\n _currency,\n _baseWeightCurrency,\n _payoutSplitsGroup,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from == address(this)\n ? IERC20(token).safeTransfer(_to, _amount)\n : IERC20(token).safeTransferFrom(_from, _to, _amount);\n }\n\n /** \n @notice\n Logic to be triggered before transferring tokens from this terminal.\n\n @param _to The address to which the transfer is going.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _beforeTransferTo(address _to, uint256 _amount) internal override {\n IERC20(token).safeIncreaseAllowance(_to, _amount);\n }\n\n /** \n @notice\n Logic to be triggered if a transfer should be undone\n\n @param _to The address to which the transfer went.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _cancelTransferTo(address _to, uint256 _amount) internal override {\n IERC20(token).safeDecreaseAllowance(_to, _amount);\n }\n}\n" }, - "contracts/JBETHERC20ProjectPayer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport './interfaces/IJBProjectPayer.sol';\nimport './libraries/JBTokens.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ERC165: Introspection on interface adherance. \n*/\ncontract JBETHERC20ProjectPayer is Ownable, ERC165, IJBProjectPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // -------------------------- custom errors -------------------------- //\n //*********************************************************************//\n error INCORRECT_DECIMAL_AMOUNT();\n error NO_MSG_VALUE_ALLOWED();\n error TERMINAL_NOT_FOUND();\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice \n A contract storing directories of terminals and controllers for each project.\n */\n IJBDirectory public immutable override directory;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The ID of the project that should be used to forward this contract's received payments.\n */\n uint256 public override defaultProjectId;\n\n /** \n @notice \n The beneficiary that should be used in the payment made when this contract receives payments.\n */\n address payable public override defaultBeneficiary;\n\n /** \n @notice \n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\n */\n bool public override defaultPreferClaimedTokens;\n\n /** \n @notice \n The memo that should be used in the payment made when this contract receives payments.\n */\n string public override defaultMemo;\n\n /** \n @notice \n The metadata that should be used in the payment made when this contract receives payments.\n */\n bytes public override defaultMetadata;\n\n /**\n @notice \n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n bool public override defaultPreferAddToBalance;\n\n //*********************************************************************//\n // ------------------------- public views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) {\n defaultProjectId = _defaultProjectId;\n defaultBeneficiary = _defaultBeneficiary;\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\n defaultMemo = _defaultMemo;\n defaultMetadata = _defaultMetadata;\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n directory = _directory;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default project ID using the stored default properties.\n\n @dev\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override {\n if (defaultPreferAddToBalance)\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.ETH,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n defaultProjectId,\n JBTokens.ETH,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultBeneficiary == address(0) ? tx.origin : defaultBeneficiary,\n 0, // Can't determine expectation of returned tokens ahead of time.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\n\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _beneficiary The address that'll receive the project's tokens. \n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _memo The memo that'll be used. \n @param _metadata The metadata that'll be sent. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external virtual override onlyOwner {\n // Set the default project ID if it has changed.\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\n\n // Set the default beneficiary if it has changed.\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\n\n // Set the default claimed token preference if it has changed.\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\n defaultPreferClaimedTokens = _preferClaimedTokens;\n\n // Set the default memo if it has changed.\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\n defaultMemo = _memo;\n\n // Set the default metadata if it has changed.\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\n defaultMetadata = _metadata;\n\n // Set the add to balance preference if it has changed.\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n\n emit SetDefaultValues(\n _projectId,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata,\n _defaultPreferAddToBalance,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _pay(\n _projectId,\n _token,\n _amount,\n _decimals,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. \n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source and delegate, if provided.\n */\n function _pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.ETH) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\n\n // Send funds to the terminal.\n // If the token is ETH, send it in msg.value.\n _terminal.pay{value: _payableValue}(\n _projectId,\n _amount, // ignored if the token is JBTokens.ETH.\n _token,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.ETH) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _amount : 0;\n\n // Add to balance so tokens don't get issued.\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\n }\n}\n" + "contracts/JBGasTokenERC20ProjectPayer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/access/Ownable.sol';\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport './interfaces/IJBProjectPayer.sol';\nimport './libraries/JBTokens.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to project treasuries from within other contracts.\n\n @dev\n Adheres to -\n IJBProjectPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n Ownable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n ERC165: Introspection on interface adherance. \n*/\ncontract JBGasTokenERC20ProjectPayer is Ownable, ERC165, IJBProjectPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // -------------------------- custom errors -------------------------- //\n //*********************************************************************//\n error INCORRECT_DECIMAL_AMOUNT();\n error NO_MSG_VALUE_ALLOWED();\n error TERMINAL_NOT_FOUND();\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice \n A contract storing directories of terminals and controllers for each project.\n */\n IJBDirectory public immutable override directory;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n The ID of the project that should be used to forward this contract's received payments.\n */\n uint256 public override defaultProjectId;\n\n /** \n @notice \n The beneficiary that should be used in the payment made when this contract receives payments.\n */\n address payable public override defaultBeneficiary;\n\n /** \n @notice \n A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. Leaving tokens unclaimed saves gas.\n */\n bool public override defaultPreferClaimedTokens;\n\n /** \n @notice \n The memo that should be used in the payment made when this contract receives payments.\n */\n string public override defaultMemo;\n\n /** \n @notice \n The metadata that should be used in the payment made when this contract receives payments.\n */\n bytes public override defaultMetadata;\n\n /**\n @notice \n A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n bool public override defaultPreferAddToBalance;\n\n //*********************************************************************//\n // ------------------------- public views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBProjectPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultProjectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) {\n defaultProjectId = _defaultProjectId;\n defaultBeneficiary = _defaultBeneficiary;\n defaultPreferClaimedTokens = _defaultPreferClaimedTokens;\n defaultMemo = _defaultMemo;\n defaultMetadata = _defaultMetadata;\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n directory = _directory;\n\n _transferOwnership(_owner);\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default project ID using the stored default properties.\n\n @dev\n Use the `addToBalance` function if there's a preference to do so. Otherwise use `pay`.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override {\n if (defaultPreferAddToBalance)\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // balance is a fixed point number with 18 decimals.\n defaultBeneficiary == address(0) ? tx.origin : defaultBeneficiary,\n 0, // Can't determine expectation of returned tokens ahead of time.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets the default values that determine how to interact with a protocol treasury when this contract receives ETH directly.\n\n @param _projectId The ID of the project whose treasury should be forwarded this contract's received payments.\n @param _beneficiary The address that'll receive the project's tokens. \n @param _preferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _memo The memo that'll be used. \n @param _metadata The metadata that'll be sent. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n */\n function setDefaultValues(\n uint256 _projectId,\n address payable _beneficiary,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata,\n bool _defaultPreferAddToBalance\n ) external virtual override onlyOwner {\n // Set the default project ID if it has changed.\n if (_projectId != defaultProjectId) defaultProjectId = _projectId;\n\n // Set the default beneficiary if it has changed.\n if (_beneficiary != defaultBeneficiary) defaultBeneficiary = _beneficiary;\n\n // Set the default claimed token preference if it has changed.\n if (_preferClaimedTokens != defaultPreferClaimedTokens)\n defaultPreferClaimedTokens = _preferClaimedTokens;\n\n // Set the default memo if it has changed.\n if (keccak256(abi.encodePacked(_memo)) != keccak256(abi.encodePacked(defaultMemo)))\n defaultMemo = _memo;\n\n // Set the default metadata if it has changed.\n if (keccak256(abi.encodePacked(_metadata)) != keccak256(abi.encodePacked(defaultMetadata)))\n defaultMetadata = _metadata;\n\n // Set the add to balance preference if it has changed.\n if (_defaultPreferAddToBalance != defaultPreferAddToBalance)\n defaultPreferAddToBalance = _defaultPreferAddToBalance;\n\n emit SetDefaultValues(\n _projectId,\n _beneficiary,\n _preferClaimedTokens,\n _memo,\n _metadata,\n _defaultPreferAddToBalance,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _pay(\n _projectId,\n _token,\n _amount,\n _decimals,\n _beneficiary,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n _addToBalanceOf(_projectId, _token, _amount, _decimals, _memo, _metadata);\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Make a payment to the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. \n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _beneficiary The address who will receive tokens from the payment.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source and delegate, if provided.\n */\n function _pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Send funds to the terminal.\n // If the token is ETH, send it in msg.value.\n _terminal.pay{value: _payableValue}(\n _projectId,\n _amount, // ignored if the token is JBTokens.GAS_TOKEN.\n _token,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project.\n\n @param _projectId The ID of the project that is being paid.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Extra data to pass along to the terminal.\n */\n function _addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string memory _memo,\n bytes memory _metadata\n ) internal virtual {\n // Find the terminal for the specified project.\n IJBPaymentTerminal _terminal = directory.primaryTerminalOf(_projectId, _token);\n\n // There must be a terminal.\n if (_terminal == IJBPaymentTerminal(address(0))) revert TERMINAL_NOT_FOUND();\n\n // The amount's decimals must match the terminal's expected decimals.\n if (_terminal.decimalsForToken(_token) != _decimals) revert INCORRECT_DECIMAL_AMOUNT();\n\n // Approve the `_amount` of tokens from the destination terminal to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN) IERC20(_token).safeApprove(address(_terminal), _amount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _amount : 0;\n\n // Add to balance so tokens don't get issued.\n _terminal.addToBalanceOf{value: _payableValue}(_projectId, _amount, _token, _memo, _metadata);\n }\n}\n" }, - "contracts/JBETHERC20ProjectPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './interfaces/IJBETHERC20ProjectPayerDeployer.sol';\nimport './JBETHERC20ProjectPayer.sol';\n\n/** \n @notice \n Deploys project payer contracts.\n\n @dev\n Adheres to -\n IJBETHERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBETHERC20ProjectPayerDeployer is IJBETHERC20ProjectPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new project payer contract.\n\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the project payer contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the project payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the project payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the project payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the project payer.\n\n @return projectPayer The project payer contract.\n */\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external override returns (IJBProjectPayer projectPayer) {\n // Deploy the project payer.\n projectPayer = new JBETHERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner\n );\n\n emit DeployProjectPayer(\n projectPayer,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner,\n msg.sender\n );\n }\n}\n" + "contracts/JBGasTokenERC20ProjectPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './interfaces/IJBGasTokenERC20ProjectPayerDeployer.sol';\nimport './JBGasTokenERC20ProjectPayer.sol';\n\n/** \n @notice \n Deploys project payer contracts.\n\n @dev\n Adheres to -\n IJBGasTokenERC20ProjectPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBGasTokenERC20ProjectPayerDeployer is IJBGasTokenERC20ProjectPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new project payer contract.\n\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the project payer contract's received payments.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the project payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the project payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the project payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the project payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _owner The address that will own the project payer.\n\n @return projectPayer The project payer contract.\n */\n function deployProjectPayer(\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n IJBDirectory _directory,\n address _owner\n ) external override returns (IJBProjectPayer projectPayer) {\n // Deploy the project payer.\n projectPayer = new JBGasTokenERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner\n );\n\n emit DeployProjectPayer(\n projectPayer,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _directory,\n _owner,\n msg.sender\n );\n }\n}\n" }, - "contracts/JBETHERC20SplitsPayer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBSplitsPayer.sol';\nimport './interfaces/IJBSplitsStore.sol';\nimport './libraries/JBConstants.sol';\nimport './JBETHERC20ProjectPayer.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\n\n @dev\n Adheres to -\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBETHERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBETHERC20SplitsPayer is JBETHERC20ProjectPayer, ReentrancyGuard, IJBSplitsPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The ID of project for which the default splits are stored. \n */\n uint256 public override defaultSplitsProjectId;\n\n /**\n @notice\n The domain within which the default splits are stored. \n */\n uint256 public override defaultSplitsDomain;\n\n /**\n @notice\n The group within which the default splits are stored. \n */\n uint256 public override defaultSplitsGroup;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBETHERC20ProjectPayer, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n )\n JBETHERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _preferAddToBalance,\n _splitsStore.directory(),\n _owner\n )\n {\n defaultSplitsProjectId = _defaultSplitsProjectId;\n defaultSplitsDomain = _defaultSplitsDomain;\n defaultSplitsGroup = _defaultSplitsGroup;\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default split group using the stored default properties.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override nonReentrant {\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n JBTokens.ETH,\n address(this).balance,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // If there is no leftover amount, nothing left to pay.\n if (_leftoverAmount == 0) return;\n\n // If there's a default project ID, try to pay it.\n if (defaultProjectId != 0)\n if (defaultPreferAddToBalance)\n // Pay the project by adding to its balance if prefered.\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.ETH,\n _leftoverAmount,\n 18, // decimals.\n defaultMemo,\n defaultMetadata\n );\n // Otherwise, issue a payment to the project.\n else\n _pay(\n defaultProjectId,\n JBTokens.ETH,\n _leftoverAmount,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n 0, // min returned tokens.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else\n Address.sendValue(\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(tx.origin),\n _leftoverAmount\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the splits in the splits store that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n @param _groupedSplits The split groups to set.\n */\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n JBGroupedSplits[] memory _groupedSplits\n ) external virtual override onlyOwner {\n // Set the splits in the store.\n splitsStore.set(_projectId, _domain, _groupedSplits);\n\n // Set the splits reference.\n setDefaultSplitsReference(_projectId, _domain, _group);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the location of the splits that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n */\n function setDefaultSplitsReference(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) public virtual override onlyOwner {\n // Set the default splits project ID if it's changing.\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\n\n // Set the default splits domain if it's changing.\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\n\n // Set the default splits group if it's changing.\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\n\n emit SetDefaultSplitsReference(_projectId, _domain, _group, msg.sender);\n }\n\n /** \n @notice \n Make a payment to the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Pay any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to pay it.\n if (_projectId != 0) {\n _pay(\n _projectId,\n _token,\n _leftoverAmount,\n _decimals,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? payable(_beneficiary) : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit Pay(\n _projectId,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event. \n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (address(_token) != JBTokens.ETH) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Distribute any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to add to its balance.\n if (_projectId != 0)\n // Add to the project's balance.\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\n\n // Otherwise, send a payment to the beneficiary.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit AddToBalance(\n _projectId,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splitsProjectId The ID of the project to which the splits belong.\n @param _splitsDomain The splits domain to which the group belongs.\n @param _splitsGroup The splits group to pay.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payToSplits(\n uint256 _splitsProjectId,\n uint256 _splitsDomain,\n uint256 _splitsGroup,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Pay the splits.\n leftoverAmount = _payTo(\n splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup),\n _token,\n _amount,\n _decimals,\n _defaultBeneficiary\n );\n emit DistributeToSplitGroup(_splitsProjectId, _splitsDomain, _splitsGroup, msg.sender);\n }\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splits The splits.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payTo(\n JBSplit[] memory _splits,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Set the leftover amount to the initial balance.\n leftoverAmount = _amount;\n\n // Settle between all splits.\n for (uint256 i; i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[i];\n\n // The amount to send towards the split.\n uint256 _splitAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n if (_splitAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n _token,\n _splitAmount,\n _decimals,\n defaultProjectId,\n 0,\n _split\n );\n\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\n if (_token != JBTokens.ETH)\n IERC20(_token).safeApprove(address(_split.allocator), _splitAmount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.ETH ? _splitAmount : 0;\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n if (_split.preferAddToBalance)\n _addToBalanceOf(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n 0,\n _split.preferClaimed,\n defaultMemo,\n defaultMetadata\n );\n } else {\n // Transfer the ETH.\n if (_token == JBTokens.ETH)\n Address.sendValue(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : payable(_defaultBeneficiary),\n _splitAmount\n );\n // Or, transfer the ERC20.\n else {\n IERC20(_token).safeTransfer(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n _splitAmount\n );\n }\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _splitAmount;\n }\n\n emit DistributeToSplit(_split, _splitAmount, _defaultBeneficiary, msg.sender);\n\n unchecked {\n ++i;\n }\n }\n }\n}\n" + "contracts/JBGasTokenERC20SplitsPayer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBSplitsPayer.sol';\nimport './interfaces/IJBSplitsStore.sol';\nimport './libraries/JBConstants.sol';\nimport './JBGasTokenERC20ProjectPayer.sol';\n\n/** \n @notice \n Sends ETH or ERC20's to a group of splits as it receives direct payments or has its functions called.\n\n @dev\n Inherit from this contract or borrow from its logic to forward ETH or ERC20's to a group of splits from within other contracts.\n\n @dev\n Adheres to -\n IJBSplitsPayer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBGasTokenERC20ProjectPayer: Sends ETH or ERC20's to a project treasury as it receives direct payments or has it's functions called.\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBGasTokenERC20SplitsPayer is JBGasTokenERC20ProjectPayer, ReentrancyGuard, IJBSplitsPayer {\n using SafeERC20 for IERC20;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The contract that stores splits for each project.\n */\n IJBSplitsStore public immutable override splitsStore;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The ID of project for which the default splits are stored. \n */\n uint256 public override defaultSplitsProjectId;\n\n /**\n @notice\n The domain within which the default splits are stored. \n */\n uint256 public override defaultSplitsDomain;\n\n /**\n @notice\n The group within which the default splits are stored. \n */\n uint256 public override defaultSplitsGroup;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(JBGasTokenERC20ProjectPayer, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBSplitsPayer).interfaceId || super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _defaultMetadata Bytes to send along to the project's data source and delegate, if provided.\n @param _preferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the contract.\n */\n constructor(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _preferAddToBalance,\n address _owner\n )\n JBGasTokenERC20ProjectPayer(\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _preferAddToBalance,\n _splitsStore.directory(),\n _owner\n )\n {\n defaultSplitsProjectId = _defaultSplitsProjectId;\n defaultSplitsDomain = _defaultSplitsDomain;\n defaultSplitsGroup = _defaultSplitsGroup;\n splitsStore = _splitsStore;\n }\n\n //*********************************************************************//\n // ------------------------- default receive ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Received funds are paid to the default split group using the stored default properties.\n\n @dev\n This function is called automatically when the contract receives an ETH payment.\n */\n receive() external payable virtual override nonReentrant {\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n JBTokens.GAS_TOKEN,\n address(this).balance,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // If there is no leftover amount, nothing left to pay.\n if (_leftoverAmount == 0) return;\n\n // If there's a default project ID, try to pay it.\n if (defaultProjectId != 0)\n if (defaultPreferAddToBalance)\n // Pay the project by adding to its balance if prefered.\n _addToBalanceOf(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n _leftoverAmount,\n 18, // decimals.\n defaultMemo,\n defaultMetadata\n );\n // Otherwise, issue a payment to the project.\n else\n _pay(\n defaultProjectId,\n JBTokens.GAS_TOKEN,\n _leftoverAmount,\n 18, // decimals.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n 0, // min returned tokens.\n defaultPreferClaimedTokens,\n defaultMemo,\n defaultMetadata\n );\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else\n Address.sendValue(\n defaultBeneficiary != address(0) ? payable(defaultBeneficiary) : payable(tx.origin),\n _leftoverAmount\n );\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the splits in the splits store that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n @param _groupedSplits The split groups to set.\n */\n function setDefaultSplits(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n JBGroupedSplits[] memory _groupedSplits\n ) external virtual override onlyOwner {\n // Set the splits in the store.\n splitsStore.set(_projectId, _domain, _groupedSplits);\n\n // Set the splits reference.\n setDefaultSplitsReference(_projectId, _domain, _group);\n }\n\n //*********************************************************************//\n // ----------------------- public transactions ----------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Sets the location of the splits that payments this contract receives will be split between.\n\n @param _projectId The ID of project for which the default splits are stored. \n @param _domain The domain within which the default splits are stored. \n @param _group The group within which the default splits are stored. \n */\n function setDefaultSplitsReference(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) public virtual override onlyOwner {\n // Set the default splits project ID if it's changing.\n if (_projectId != defaultSplitsProjectId) defaultSplitsProjectId = _projectId;\n\n // Set the default splits domain if it's changing.\n if (_domain != defaultSplitsDomain) defaultSplitsDomain = _domain;\n\n // Set the default splits group if it's changing.\n if (_group != defaultSplitsGroup) defaultSplitsGroup = _group;\n\n emit SetDefaultSplitsReference(_projectId, _domain, _group, msg.sender);\n }\n\n /** \n @notice \n Make a payment to the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _beneficiary The address who will receive tokens from the payment made with leftover funds.\n @param _minReturnedTokens The minimum number of project tokens expected in return, as a fixed point number with 18 decimals.\n @param _preferClaimedTokens A flag indicating whether the request prefers 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. Leaving them unclaimed saves gas.\n @param _memo A memo to pass along to the emitted event, and passed along the the funding cycle's data source and delegate. A data source can alter the memo before emitting in the event and forwarding to the delegate.\n @param _metadata Bytes to send along to the data source, delegate, and emitted event, if provided.\n */\n function pay(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _beneficiary,\n uint256 _minReturnedTokens,\n bool _preferClaimedTokens,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if the token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Pay any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to pay it.\n if (_projectId != 0) {\n _pay(\n _projectId,\n _token,\n _leftoverAmount,\n _decimals,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata\n );\n }\n // If no project was specified, send the funds directly to the beneficiary or the tx.origin.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? payable(_beneficiary) : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit Pay(\n _projectId,\n _beneficiary != address(0) ? _beneficiary : defaultBeneficiary != address(0)\n ? defaultBeneficiary\n : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _minReturnedTokens,\n _preferClaimedTokens,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n /** \n @notice \n Add to the balance of the specified project after first splitting the amount among the stored default splits.\n\n @param _projectId The ID of the project that is being paid after.\n @param _token The token being paid in.\n @param _amount The amount of tokens being paid, as a fixed point number. If the token is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. If the token is ETH, this is ignored and 18 is used in its place, which corresponds to the amount of decimals expected in msg.value.\n @param _memo A memo to pass along to the emitted event. \n @param _metadata Extra data to pass along to the terminal.\n */\n function addToBalanceOf(\n uint256 _projectId,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n string calldata _memo,\n bytes calldata _metadata\n ) public payable virtual override nonReentrant {\n // ETH shouldn't be sent if this terminal's token isn't ETH.\n if (address(_token) != JBTokens.GAS_TOKEN) {\n if (msg.value > 0) revert NO_MSG_VALUE_ALLOWED();\n\n // Get a reference to the balance before receiving tokens.\n uint256 _balanceBefore = IERC20(_token).balanceOf(address(this));\n\n // Transfer tokens to this contract from the msg sender.\n IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n\n // The amount should reflect the change in balance.\n _amount = IERC20(_token).balanceOf(address(this)) - _balanceBefore;\n } else {\n // If ETH is being paid, set the amount to the message value, and decimals to 18.\n _amount = msg.value;\n _decimals = 18;\n }\n\n // Pay the splits and get a reference to the amount leftover.\n uint256 _leftoverAmount = _payToSplits(\n defaultSplitsProjectId,\n defaultSplitsDomain,\n defaultSplitsGroup,\n _token,\n _amount,\n _decimals,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin\n );\n\n // Distribute any leftover amount.\n if (_leftoverAmount > 0) {\n // If there's a default project ID, try to add to its balance.\n if (_projectId != 0)\n // Add to the project's balance.\n _addToBalanceOf(_projectId, _token, _leftoverAmount, _decimals, _memo, _metadata);\n\n // Otherwise, send a payment to the beneficiary.\n else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : payable(tx.origin),\n _leftoverAmount\n );\n // Or, transfer the ERC20.\n else\n IERC20(_token).safeTransfer(\n // If there's a default beneficiary, send the funds directly to the beneficiary. Otherwise send to the tx.origin.\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _leftoverAmount\n );\n }\n }\n\n emit AddToBalance(\n _projectId,\n defaultBeneficiary != address(0) ? defaultBeneficiary : tx.origin,\n _token,\n _amount,\n _decimals,\n _leftoverAmount,\n _memo,\n _metadata,\n msg.sender\n );\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splitsProjectId The ID of the project to which the splits belong.\n @param _splitsDomain The splits domain to which the group belongs.\n @param _splitsGroup The splits group to pay.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payToSplits(\n uint256 _splitsProjectId,\n uint256 _splitsDomain,\n uint256 _splitsGroup,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Pay the splits.\n leftoverAmount = _payTo(\n splitsStore.splitsOf(_splitsProjectId, _splitsDomain, _splitsGroup),\n _token,\n _amount,\n _decimals,\n _defaultBeneficiary\n );\n emit DistributeToSplitGroup(_splitsProjectId, _splitsDomain, _splitsGroup, msg.sender);\n }\n\n /** \n @notice \n Split an amount between all splits.\n\n @param _splits The splits.\n @param _token The token the amonut being split is in.\n @param _amount The amount of tokens being split, as a fixed point number. If the `_token` is ETH, this is ignored and msg.value is used in its place.\n @param _decimals The number of decimals in the `_amount` fixed point number. \n @param _defaultBeneficiary The address that will benefit from any non-specified beneficiaries in splits.\n\n @return leftoverAmount The amount leftover after all splits were paid.\n */\n function _payTo(\n JBSplit[] memory _splits,\n address _token,\n uint256 _amount,\n uint256 _decimals,\n address _defaultBeneficiary\n ) internal virtual returns (uint256 leftoverAmount) {\n // Set the leftover amount to the initial balance.\n leftoverAmount = _amount;\n\n // Settle between all splits.\n for (uint256 i; i < _splits.length; ) {\n // Get a reference to the split being iterated on.\n JBSplit memory _split = _splits[i];\n\n // The amount to send towards the split.\n uint256 _splitAmount = PRBMath.mulDiv(\n _amount,\n _split.percent,\n JBConstants.SPLITS_TOTAL_PERCENT\n );\n\n if (_splitAmount > 0) {\n // Transfer tokens to the split.\n // If there's an allocator set, transfer to its `allocate` function.\n if (_split.allocator != IJBSplitAllocator(address(0))) {\n // Create the data to send to the allocator.\n JBSplitAllocationData memory _data = JBSplitAllocationData(\n _token,\n _splitAmount,\n _decimals,\n defaultProjectId,\n 0,\n _split\n );\n\n // Approve the `_amount` of tokens for the split allocator to transfer tokens from this contract.\n if (_token != JBTokens.GAS_TOKEN)\n IERC20(_token).safeApprove(address(_split.allocator), _splitAmount);\n\n // If the token is ETH, send it in msg.value.\n uint256 _payableValue = _token == JBTokens.GAS_TOKEN ? _splitAmount : 0;\n\n // Trigger the allocator's `allocate` function.\n _split.allocator.allocate{value: _payableValue}(_data);\n\n // Otherwise, if a project is specified, make a payment to it.\n } else if (_split.projectId != 0) {\n if (_split.preferAddToBalance)\n _addToBalanceOf(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n defaultMemo,\n defaultMetadata\n );\n else\n _pay(\n _split.projectId,\n _token,\n _splitAmount,\n _decimals,\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n 0,\n _split.preferClaimed,\n defaultMemo,\n defaultMetadata\n );\n } else {\n // Transfer the ETH.\n if (_token == JBTokens.GAS_TOKEN)\n Address.sendValue(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : payable(_defaultBeneficiary),\n _splitAmount\n );\n // Or, transfer the ERC20.\n else {\n IERC20(_token).safeTransfer(\n // Get a reference to the address receiving the tokens. If there's a beneficiary, send the funds directly to the beneficiary. Otherwise send to _defaultBeneficiary.\n _split.beneficiary != address(0) ? _split.beneficiary : _defaultBeneficiary,\n _splitAmount\n );\n }\n }\n\n // Subtract from the amount to be sent to the beneficiary.\n leftoverAmount = leftoverAmount - _splitAmount;\n }\n\n emit DistributeToSplit(_split, _splitAmount, _defaultBeneficiary, msg.sender);\n\n unchecked {\n ++i;\n }\n }\n }\n}\n" }, - "contracts/JBETHERC20SplitsPayerDeployer.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './interfaces/IJBETHERC20SplitsPayerDeployer.sol';\nimport './structs/JBSplit.sol';\nimport './structs/JBGroupedSplits.sol';\nimport './JBETHERC20SplitsPayer.sol';\n\n/** \n @notice \n Deploys splits payer contracts.\n\n @dev\n Adheres to -\n IJBETHERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBETHERC20SplitsPayerDeployer is IJBETHERC20SplitsPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @dev\n This contract must have Operator permissions over the SET_SPLITS permission of the specified `_defaultSplitsProjectId`.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplits The splits to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBSplitsPayer splitsPayer) {\n // Use this contract's address as the domain.\n uint256 _domain = uint256(uint160(address(this)));\n\n // Create the random hash using data unique to this instance that'll be used as the storage domain.\n uint256 _group = uint256(keccak256(abi.encodePacked(msg.sender, block.number)));\n\n // Set the splits in the store.\n JBGroupedSplits[] memory _groupedSplits;\n _groupedSplits = new JBGroupedSplits[](1);\n _groupedSplits[0] = JBGroupedSplits(_group, _defaultSplits);\n _splitsStore.set(_defaultSplitsProjectId, _domain, _groupedSplits);\n\n return\n deploySplitsPayer(\n _defaultSplitsProjectId,\n _domain,\n _group,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n }\n\n //*********************************************************************//\n // ---------------------- public transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) public override returns (IJBSplitsPayer splitsPayer) {\n // Deploy the splits payer.\n splitsPayer = new JBETHERC20SplitsPayer(\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeploySplitsPayer(\n splitsPayer,\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner,\n msg.sender\n );\n }\n}\n" + "contracts/JBGasTokenERC20SplitsPayerDeployer.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './interfaces/IJBGasTokenERC20SplitsPayerDeployer.sol';\nimport './structs/JBSplit.sol';\nimport './structs/JBGroupedSplits.sol';\nimport './JBGasTokenERC20SplitsPayer.sol';\n\n/** \n @notice \n Deploys splits payer contracts.\n\n @dev\n Adheres to -\n IJBGasTokenERC20SplitsPayerDeployer: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n*/\ncontract JBGasTokenERC20SplitsPayerDeployer is IJBGasTokenERC20SplitsPayerDeployer {\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @dev\n This contract must have Operator permissions over the SET_SPLITS permission of the specified `_defaultSplitsProjectId`.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplits The splits to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayerWithSplits(\n uint256 _defaultSplitsProjectId,\n JBSplit[] memory _defaultSplits,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) external override returns (IJBSplitsPayer splitsPayer) {\n // Use this contract's address as the domain.\n uint256 _domain = uint256(uint160(address(this)));\n\n // Create the random hash using data unique to this instance that'll be used as the storage domain.\n uint256 _group = uint256(keccak256(abi.encodePacked(msg.sender, block.number)));\n\n // Set the splits in the store.\n JBGroupedSplits[] memory _groupedSplits;\n _groupedSplits = new JBGroupedSplits[](1);\n _groupedSplits[0] = JBGroupedSplits(_group, _defaultSplits);\n _splitsStore.set(_defaultSplitsProjectId, _domain, _groupedSplits);\n\n return\n deploySplitsPayer(\n _defaultSplitsProjectId,\n _domain,\n _group,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n }\n\n //*********************************************************************//\n // ---------------------- public transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Allows anyone to deploy a new splits payer contract.\n\n @param _defaultSplitsProjectId The ID of project for which the default splits are stored.\n @param _defaultSplitsDomain The splits domain to payout when this contract receives direct payments.\n @param _defaultSplitsGroup The splits group to payout when this contract receives direct payments.\n @param _splitsStore A contract that stores splits for each project.\n @param _defaultProjectId The ID of the project whose treasury should be forwarded the splits payer contract's received payment leftovers after distributing to the default splits group.\n @param _defaultBeneficiary The address that'll receive the project's tokens when the splits payer receives payments. \n @param _defaultPreferClaimedTokens A flag indicating whether issued tokens from the splits payer's received payments should be automatically claimed into the beneficiary's wallet. \n @param _defaultMemo The memo that'll be forwarded with the splits payer's received payments. \n @param _defaultMetadata The metadata that'll be forwarded with the splits payer's received payments. \n @param _defaultPreferAddToBalance A flag indicating if received payments should call the `pay` function or the `addToBalance` function of a project.\n @param _owner The address that will own the splits payer.\n\n @return splitsPayer The splits payer contract.\n */\n function deploySplitsPayer(\n uint256 _defaultSplitsProjectId,\n uint256 _defaultSplitsDomain,\n uint256 _defaultSplitsGroup,\n IJBSplitsStore _splitsStore,\n uint256 _defaultProjectId,\n address payable _defaultBeneficiary,\n bool _defaultPreferClaimedTokens,\n string memory _defaultMemo,\n bytes memory _defaultMetadata,\n bool _defaultPreferAddToBalance,\n address _owner\n ) public override returns (IJBSplitsPayer splitsPayer) {\n // Deploy the splits payer.\n splitsPayer = new JBGasTokenERC20SplitsPayer(\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner\n );\n\n emit DeploySplitsPayer(\n splitsPayer,\n _defaultSplitsProjectId,\n _defaultSplitsDomain,\n _defaultSplitsGroup,\n _splitsStore,\n _defaultProjectId,\n _defaultBeneficiary,\n _defaultPreferClaimedTokens,\n _defaultMemo,\n _defaultMetadata,\n _defaultPreferAddToBalance,\n _owner,\n msg.sender\n );\n }\n}\n" }, "contracts/JBETHPaymentTerminal.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\nimport './libraries/JBSplitsGroups.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return address(this).balance;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n JBTokens.ETH,\n 18, // 18 decimals.\n JBCurrencies.ETH,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal.sol';\nimport './libraries/JBSplitsGroups.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal is JBPayoutRedemptionPaymentTerminal {\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return address(this).balance;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal(\n JBTokens.GAS_TOKEN,\n 18, // 18 decimals.\n JBCurrencies.GAS_CURRENCY,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n}\n" }, "contracts/JBETHPaymentTerminal3_1.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal3_1.sol';\nimport './libraries/JBSplitsGroups.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal3_1: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal3_1 is JBPayoutRedemptionPaymentTerminal3_1 {\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return address(this).balance;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal3_1(\n JBTokens.ETH,\n 18, // 18 decimals.\n JBCurrencies.ETH,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/Address.sol';\nimport './abstract/JBPayoutRedemptionPaymentTerminal3_1.sol';\nimport './libraries/JBSplitsGroups.sol';\n\n/**\n @notice\n Manages all inflows and outflows of ETH funds into the protocol ecosystem.\n\n @dev\n Inherits from -\n JBPayoutRedemptionPaymentTerminal3_1: Generic terminal managing all inflows and outflows of funds into the protocol ecosystem.\n*/\ncontract JBETHPaymentTerminal3_1 is JBPayoutRedemptionPaymentTerminal3_1 {\n //*********************************************************************//\n // -------------------------- internal views ------------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Checks the balance of tokens in this contract.\n\n @return The contract's balance, as a fixed point number with the same amount of decimals as this terminal.\n */\n function _balance() internal view override returns (uint256) {\n return address(this).balance;\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _splitsStore A contract that stores splits for each project.\n @param _prices A contract that exposes price feeds.\n @param _store A contract that stores the terminal's data.\n @param _owner The address that will own this contract.\n */\n constructor(\n uint256 _baseWeightCurrency,\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory,\n IJBSplitsStore _splitsStore,\n IJBPrices _prices,\n IJBSingleTokenPaymentTerminalStore _store,\n address _owner\n )\n JBPayoutRedemptionPaymentTerminal3_1(\n JBTokens.GAS_TOKEN,\n 18, // 18 decimals.\n JBCurrencies.GAS_CURRENCY,\n _baseWeightCurrency,\n JBSplitsGroups.ETH_PAYOUT,\n _operatorStore,\n _projects,\n _directory,\n _splitsStore,\n _prices,\n _store,\n _owner\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n //*********************************************************************//\n // ---------------------- internal transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice\n Transfers tokens.\n\n @param _from The address from which the transfer should originate.\n @param _to The address to which the transfer should go.\n @param _amount The amount of the transfer, as a fixed point number with the same number of decimals as this terminal.\n */\n function _transferFrom(\n address _from,\n address payable _to,\n uint256 _amount\n ) internal override {\n _from; // Prevents unused var compiler and natspec complaints.\n\n Address.sendValue(_to, _amount);\n }\n}\n" }, "contracts/JBFundAccessConstraintsStore.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport './abstract/JBControllerUtility.sol';\nimport './interfaces/IJBFundAccessConstraintsStore.sol';\n\n/**\n @notice\n Information pertaining to how much funds can be accessed by a project from each payment terminal.\n \n @dev\n Adheres to -\n IJBFundAccessConstraintsStore: General interface for the generic controller methods in this contract that interacts with funding cycles and tokens according to the protocol's rules.\n\n @dev\n Inherits from -\n JBControllerUtility: Several functions in this contract can only be accessed by a project owner, or an address that has been preconfifigured to be an operator of the project.\n ERC165: Introspection on interface adherance. \n*/\ncontract JBFundAccessConstraintsStore is\n JBControllerUtility,\n ERC165,\n IJBFundAccessConstraintsStore\n{\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n\n error INVALID_DISTRIBUTION_LIMIT();\n error INVALID_DISTRIBUTION_LIMIT_CURRENCY();\n error INVALID_OVERFLOW_ALLOWANCE();\n error INVALID_OVERFLOW_ALLOWANCE_CURRENCY();\n\n //*********************************************************************//\n // --------------------- internal stored properties ------------------ //\n //*********************************************************************//\n\n /**\n @notice\n Data regarding the distribution limit of a project during a configuration.\n\n @dev\n bits 0-231: The amount of token that a project can distribute per funding cycle.\n\n @dev\n bits 232-255: The currency of amount that a project can distribute.\n\n _projectId The ID of the project to get the packed distribution limit data of.\n _configuration The configuration during which the packed distribution limit data applies.\n _terminal The terminal from which distributions are being limited.\n _token The token for which distributions are being limited.\n */\n mapping(uint256 => mapping(uint256 => mapping(IJBPaymentTerminal => mapping(address => uint256))))\n internal _packedDistributionLimitDataOf;\n\n /**\n @notice\n Data regarding the overflow allowance of a project during a configuration.\n\n @dev\n bits 0-231: The amount of overflow that a project is allowed to tap into on-demand throughout the configuration.\n\n @dev\n bits 232-255: The currency of the amount of overflow that a project is allowed to tap.\n\n _projectId The ID of the project to get the packed overflow allowance data of.\n _configuration The configuration during which the packed overflow allowance data applies.\n _terminal The terminal managing the overflow.\n _token The token for which overflow is being allowed.\n */\n mapping(uint256 => mapping(uint256 => mapping(IJBPaymentTerminal => mapping(address => uint256))))\n internal _packedOverflowAllowanceDataOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of token that a project can distribute per funding cycle, and the currency it's in terms of.\n\n @dev\n The number of decimals in the returned fixed point amount is the same as that of the specified terminal. \n\n @param _projectId The ID of the project to get the distribution limit of.\n @param _configuration The configuration during which the distribution limit applies.\n @param _terminal The terminal from which distributions are being limited.\n @param _token The token for which the distribution limit applies.\n\n @return The distribution limit, as a fixed point number with the same number of decimals as the provided terminal.\n @return The currency of the distribution limit.\n */\n function distributionLimitOf(\n uint256 _projectId,\n uint256 _configuration,\n IJBPaymentTerminal _terminal,\n address _token\n ) external view override returns (uint256, uint256) {\n // Get a reference to the packed data.\n uint256 _data = _packedDistributionLimitDataOf[_projectId][_configuration][_terminal][_token];\n\n // The limit is in bits 0-231. The currency is in bits 232-255.\n return (uint256(uint232(_data)), _data >> 232);\n }\n\n /**\n @notice\n The amount of overflow that a project is allowed to tap into on-demand throughout a configuration, and the currency it's in terms of.\n\n @dev\n The number of decimals in the returned fixed point amount is the same as that of the specified terminal. \n\n @param _projectId The ID of the project to get the overflow allowance of.\n @param _configuration The configuration of the during which the allowance applies.\n @param _terminal The terminal managing the overflow.\n @param _token The token for which the overflow allowance applies.\n\n @return The overflow allowance, as a fixed point number with the same number of decimals as the provided terminal.\n @return The currency of the overflow allowance.\n */\n function overflowAllowanceOf(\n uint256 _projectId,\n uint256 _configuration,\n IJBPaymentTerminal _terminal,\n address _token\n ) external view override returns (uint256, uint256) {\n // Get a reference to the packed data.\n uint256 _data = _packedOverflowAllowanceDataOf[_projectId][_configuration][_terminal][_token];\n\n // The allowance is in bits 0-231. The currency is in bits 232-255.\n return (uint256(uint232(_data)), _data >> 232);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _directory A contract storing directories of terminals and controllers for each project.\n */\n // solhint-disable-next-line no-empty-blocks\n constructor(IJBDirectory _directory) JBControllerUtility(_directory) {}\n\n //*********************************************************************//\n // --------------------- external transactions ----------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Sets a project's constraints for accessing treasury funds.\n\n @dev\n Only a project's current controller can set its fund access constraints.\n\n @param _projectId The ID of the project whose fund access constraints are being set.\n @param _configuration The funding cycle configuration the constraints apply within.\n @param _fundAccessConstraints An array containing amounts that a project can use from its treasury for each payment terminal. Amounts are fixed point numbers using the same number of decimals as the accompanying terminal. The `_distributionLimit` and `_overflowAllowance` parameters must fit in a `uint232`.\n */\n function setFor(\n uint256 _projectId,\n uint256 _configuration,\n JBFundAccessConstraints[] calldata _fundAccessConstraints\n ) external override onlyController(_projectId) {\n // Save the number of constraints.\n uint256 _numberOfFundAccessConstraints = _fundAccessConstraints.length;\n\n // Set distribution limits if there are any.\n for (uint256 _i; _i < _numberOfFundAccessConstraints; ) {\n // If distribution limit value is larger than 232 bits, revert.\n if (_fundAccessConstraints[_i].distributionLimit > type(uint232).max) revert INVALID_DISTRIBUTION_LIMIT();\n\n // If distribution limit currency value is larger than 24 bits, revert.\n if (_fundAccessConstraints[_i].distributionLimitCurrency > type(uint24).max)\n revert INVALID_DISTRIBUTION_LIMIT_CURRENCY();\n\n // If overflow allowance value is larger than 232 bits, revert.\n if (_fundAccessConstraints[_i].overflowAllowance > type(uint232).max) revert INVALID_OVERFLOW_ALLOWANCE();\n\n // If overflow allowance currency value is larger than 24 bits, revert.\n if (_fundAccessConstraints[_i].overflowAllowanceCurrency > type(uint24).max)\n revert INVALID_OVERFLOW_ALLOWANCE_CURRENCY();\n\n // Set the distribution limit if there is one.\n if (_fundAccessConstraints[_i].distributionLimit > 0)\n _packedDistributionLimitDataOf[_projectId][_configuration][_fundAccessConstraints[_i].terminal][\n _fundAccessConstraints[_i].token\n ] = _fundAccessConstraints[_i].distributionLimit | (_fundAccessConstraints[_i].distributionLimitCurrency << 232);\n\n // Set the overflow allowance if there is one.\n if (_fundAccessConstraints[_i].overflowAllowance > 0)\n _packedOverflowAllowanceDataOf[_projectId][_configuration][_fundAccessConstraints[_i].terminal][\n _fundAccessConstraints[_i].token\n ] = _fundAccessConstraints[_i].overflowAllowance | (_fundAccessConstraints[_i].overflowAllowanceCurrency << 232);\n\n emit SetFundAccessConstraints(_configuration, _projectId, _fundAccessConstraints[_i], msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n }\n}\n" @@ -290,10 +290,10 @@ "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/utils/introspection/ERC165.sol';\nimport './interfaces/IJBFundingCycleBallot.sol';\nimport './structs/JBFundingCycle.sol';\n\n/** \n @notice \n Manages approving funding cycle reconfigurations automatically after a buffer period.\n\n @dev\n Adheres to -\n IJBFundingCycleBallot: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ERC165: Introspection on interface adherance. \n*/\ncontract JBReconfigurationBufferBallot is ERC165, IJBFundingCycleBallot {\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice \n The number of seconds that must pass for a funding cycle reconfiguration to become either `Approved` or `Failed`.\n */\n uint256 public immutable override duration;\n\n //*********************************************************************//\n // -------------------------- public views --------------------------- //\n //*********************************************************************//\n\n /**\n @notice \n The approval state of a particular funding cycle.\n\n @param _projectId The ID of the project to which the funding cycle being checked belongs.\n @param _configured The configuration of the funding cycle to check the state of.\n @param _start The start timestamp of the funding cycle to check the state of.\n\n @return The state of the provided ballot. \n */\n function stateOf(\n uint256 _projectId,\n uint256 _configured,\n uint256 _start\n ) public view override returns (JBBallotState) {\n _projectId; // Prevents unused var compiler and natspec complaints.\n\n // If the provided configured timestamp is after the start timestamp, the ballot is Failed.\n if (_configured > _start) return JBBallotState.Failed;\n\n unchecked {\n // If there was sufficient time between configuration and the start of the cycle, it is approved. Otherwise, it is failed.\n return (_start - _configured < duration) ? JBBallotState.Failed : JBBallotState.Approved;\n }\n }\n\n /**\n @notice\n Indicates if this contract adheres to the specified interface.\n\n @dev \n See {IERC165-supportsInterface}.\n\n @param _interfaceId The ID of the interface to check for adherance to.\n\n @return A flag indicating if this contract adheres to the specified interface.\n */\n function supportsInterface(bytes4 _interfaceId)\n public\n view\n virtual\n override(ERC165, IERC165)\n returns (bool)\n {\n return\n _interfaceId == type(IJBFundingCycleBallot).interfaceId ||\n super.supportsInterface(_interfaceId);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _duration The number of seconds to wait until a reconfiguration can be either `Approved` or `Failed`.\n */\n constructor(uint256 _duration) {\n duration = _duration;\n }\n}\n" }, "contracts/JBSingleTokenPaymentTerminalStore.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController.sol';\nimport './interfaces/IJBFundingCycleDataSource.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './structs/JBPayDelegateAllocation.sol';\nimport './structs/JBPayParamsData.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBSingleTokenPaymentTerminalStore is ReentrancyGuard, IJBSingleTokenPaymentTerminalStore {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n JBPayDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .payParams(_data);\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\n {\n // Keep a reference to the amount that should be added to the project's balance.\n uint256 _balanceDiff = _amount.value;\n\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\n if (delegateAllocations.length != 0) {\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0) {\n // Can't delegate more than was paid.\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\n\n // Decrement the total amount being added to the balance.\n _balanceDiff = _balanceDiff - _delegatedAmount;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Add the correct balance difference to the token balance of the project.\n if (_balanceDiff != 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _balanceDiff;\n }\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\n _projectId,\n fundingCycle.reservedRate()\n );\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow != 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\n {\n // Get a reference to the ballot state.\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\n\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n _state == JBBallotState.Active\n ? fundingCycle.ballotRedemptionRate()\n : fundingCycle.redemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\n fundingCycle.dataSource()\n ).redeemParams(_data);\n }\n } else {\n memo = _memo;\n }\n }\n\n // Keep a reference to the amount that should be subtracted from the project's balance.\n uint256 _balanceDiff = reclaimAmount;\n\n if (delegateAllocations.length != 0) {\n // Validate all delegated amounts.\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0)\n // Increment the total amount being subtracted from the balance.\n _balanceDiff = _balanceDiff + _delegatedAmount;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (_balanceDiff != 0) {\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n _balanceDiff;\n }\n }\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n unchecked {\n return\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i; _i < _terminals.length; ) {\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n unchecked {\n ++_i;\n }\n }\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.ETH\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.ETH, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController.sol';\nimport './interfaces/IJBFundingCycleDataSource.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './structs/JBPayDelegateAllocation.sol';\nimport './structs/JBPayParamsData.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n*/\ncontract JBSingleTokenPaymentTerminalStore is ReentrancyGuard, IJBSingleTokenPaymentTerminalStore {\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId, _fundingCycle.reservedRate());\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n JBPayDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .payParams(_data);\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\n {\n // Keep a reference to the amount that should be added to the project's balance.\n uint256 _balanceDiff = _amount.value;\n\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\n if (delegateAllocations.length != 0) {\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0) {\n // Can't delegate more than was paid.\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\n\n // Decrement the total amount being added to the balance.\n _balanceDiff = _balanceDiff - _delegatedAmount;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Add the correct balance difference to the token balance of the project.\n if (_balanceDiff != 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _balanceDiff;\n }\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController(directory.controllerOf(_projectId)).totalOutstandingTokensOf(\n _projectId,\n fundingCycle.reservedRate()\n );\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow != 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\n {\n // Get a reference to the ballot state.\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\n\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n _state == JBBallotState.Active\n ? fundingCycle.ballotRedemptionRate()\n : fundingCycle.redemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\n fundingCycle.dataSource()\n ).redeemParams(_data);\n }\n } else {\n memo = _memo;\n }\n }\n\n // Keep a reference to the amount that should be subtracted from the project's balance.\n uint256 _balanceDiff = reclaimAmount;\n\n if (delegateAllocations.length != 0) {\n // Validate all delegated amounts.\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0)\n // Increment the total amount being subtracted from the balance.\n _balanceDiff = _balanceDiff + _delegatedAmount;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (_balanceDiff != 0) {\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n _balanceDiff;\n }\n }\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController(\n directory.controllerOf(_projectId)\n ).distributionLimitOf(_projectId, _fundingCycle.configuration, _terminal, _terminal.token());\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n unchecked {\n return\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i; _i < _terminals.length; ) {\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n unchecked {\n ++_i;\n }\n }\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.GAS_CURRENCY\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.GAS_CURRENCY, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" }, "contracts/JBSingleTokenPaymentTerminalStore3_1.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController3_1.sol';\nimport './interfaces/IJBFundingCycleDataSource.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './structs/JBPayDelegateAllocation.sol';\nimport './structs/JBPayParamsData.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n\n @dev\n This Store expects a project's controller to be an IJBController3_1. This is the only difference between this version and the original.\n*/\ncontract JBSingleTokenPaymentTerminalStore3_1 is\n ReentrancyGuard,\n IJBSingleTokenPaymentTerminalStore\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId);\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n JBPayDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .payParams(_data);\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\n {\n // Keep a reference to the amount that should be added to the project's balance.\n uint256 _balanceDiff = _amount.value;\n\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\n if (delegateAllocations.length != 0) {\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0) {\n // Can't delegate more than was paid.\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\n\n // Decrement the total amount being added to the balance.\n _balanceDiff = _balanceDiff - _delegatedAmount;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Add the correct balance difference to the token balance of the project.\n if (_balanceDiff != 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _balanceDiff;\n }\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId);\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow != 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\n {\n // Get a reference to the ballot state.\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\n\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n _state == JBBallotState.Active\n ? fundingCycle.ballotRedemptionRate()\n : fundingCycle.redemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\n fundingCycle.dataSource()\n ).redeemParams(_data);\n }\n } else {\n memo = _memo;\n }\n }\n\n // Keep a reference to the amount that should be subtracted from the project's balance.\n uint256 _balanceDiff = reclaimAmount;\n\n if (delegateAllocations.length != 0) {\n // Validate all delegated amounts.\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0)\n // Increment the total amount being subtracted from the balance.\n _balanceDiff = _balanceDiff + _delegatedAmount;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (_balanceDiff != 0) {\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n _balanceDiff;\n }\n }\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).fundAccessConstraintsStore().distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).fundAccessConstraintsStore().overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).fundAccessConstraintsStore().distributionLimitOf(\n _projectId,\n _fundingCycle.configuration,\n _terminal,\n _terminal.token()\n );\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n unchecked {\n return\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i; _i < _terminals.length; ) {\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n unchecked {\n ++_i;\n }\n }\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.ETH\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.ETH, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport '@openzeppelin/contracts/security/ReentrancyGuard.sol';\nimport '@paulrberg/contracts/math/PRBMath.sol';\nimport './interfaces/IJBController3_1.sol';\nimport './interfaces/IJBFundingCycleDataSource.sol';\nimport './interfaces/IJBSingleTokenPaymentTerminalStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBCurrencies.sol';\nimport './libraries/JBFixedPointNumber.sol';\nimport './libraries/JBFundingCycleMetadataResolver.sol';\nimport './structs/JBPayDelegateAllocation.sol';\nimport './structs/JBPayParamsData.sol';\n\n/**\n @notice\n Manages all bookkeeping for inflows and outflows of funds from any ISingleTokenPaymentTerminal.\n\n @dev\n Adheres to:\n IJBSingleTokenPaymentTerminalStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n ReentrancyGuard: Contract module that helps prevent reentrant calls to a function.\n\n @dev\n This Store expects a project's controller to be an IJBController3_1. This is the only difference between this version and the original.\n*/\ncontract JBSingleTokenPaymentTerminalStore3_1 is\n ReentrancyGuard,\n IJBSingleTokenPaymentTerminalStore\n{\n // A library that parses the packed funding cycle metadata into a friendlier format.\n using JBFundingCycleMetadataResolver for JBFundingCycle;\n\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_AMOUNT_TO_SEND_DELEGATE();\n error CURRENCY_MISMATCH();\n error DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n error FUNDING_CYCLE_PAYMENT_PAUSED();\n error FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n error FUNDING_CYCLE_REDEEM_PAUSED();\n error INADEQUATE_CONTROLLER_ALLOWANCE();\n error INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n error INSUFFICIENT_TOKENS();\n error INVALID_FUNDING_CYCLE();\n error PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n //*********************************************************************//\n // -------------------------- private constants ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Ensures a maximum number of decimal points of persisted fidelity on mulDiv operations of fixed point numbers. \n */\n uint256 private constant _MAX_FIXED_POINT_FIDELITY = 18;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /**\n @notice\n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n /**\n @notice\n The contract storing all funding cycle configurations.\n */\n IJBFundingCycleStore public immutable override fundingCycleStore;\n\n /**\n @notice\n The contract that exposes price feeds.\n */\n IJBPrices public immutable override prices;\n\n //*********************************************************************//\n // --------------------- public stored properties -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of tokens that each project has for each terminal, in terms of the terminal's token.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the balance applies.\n _projectId The ID of the project to get the balance of.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => uint256)) public override balanceOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their preconfigured distribution limits.\n\n @dev\n The used distribution limit is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the used distribution limit applies.\n _projectId The ID of the project to get the used distribution limit of.\n _fundingCycleNumber The number of the funding cycle during which the distribution limit was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedDistributionLimitOf;\n\n /**\n @notice\n 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.\n\n @dev\n Increases as projects use their allowance.\n\n @dev\n The used allowance is represented as a fixed point number with the same amount of decimals as its relative terminal.\n\n _terminal The terminal to which the overflow allowance applies.\n _projectId The ID of the project to get the used overflow allowance of.\n _configuration The configuration of the during which the allowance was used.\n */\n mapping(IJBSingleTokenPaymentTerminal => mapping(uint256 => mapping(uint256 => uint256)))\n public\n override usedOverflowAllowanceOf;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Gets the current overflowed amount in a terminal for a specified project.\n\n @dev\n The current overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n\n @return The current amount of overflow that project has in the specified terminal.\n */\n function currentOverflowOf(IJBSingleTokenPaymentTerminal _terminal, uint256 _projectId)\n external\n view\n override\n returns (uint256)\n {\n // Return the overflow during the project's current funding cycle.\n return\n _overflowDuring(\n _terminal,\n _projectId,\n fundingCycleStore.currentOf(_projectId),\n _terminal.currency()\n );\n }\n\n /**\n @notice\n Gets the current overflowed amount for a specified project across all terminals.\n\n @param _projectId The ID of the project to get total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the total overflow should be in terms of.\n\n @return The current total amount of overflow that project has across all terminals.\n */\n function currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) external view override returns (uint256) {\n return _currentTotalOverflowOf(_projectId, _decimals, _currency);\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @dev\n The current reclaimable overflow is returned in terms of the specified terminal's currency.\n\n @dev\n The reclaimable overflow is represented as a fixed point number with the same amount of decimals as the specified terminal.\n\n @param _terminal The terminal from which the reclaimable amount would come.\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @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`.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n uint256 _tokenCount,\n bool _useTotalOverflow\n ) external view override returns (uint256) {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get the amount of current overflow.\n // 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.\n uint256 _currentOverflow = _useTotalOverflow\n ? _currentTotalOverflowOf(_projectId, _terminal.decimals(), _terminal.currency())\n : _overflowDuring(_terminal, _projectId, _fundingCycle, _terminal.currency());\n\n // If there's no overflow, there's no reclaimable overflow.\n if (_currentOverflow == 0) return 0;\n\n // Get the number of outstanding tokens the project has.\n uint256 _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId);\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(\n _projectId,\n _fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n }\n\n /**\n @notice\n 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.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with, as a fixed point number.\n\n @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`.\n */\n function currentReclaimableOverflowOf(\n uint256 _projectId,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) external view override returns (uint256) {\n // If there's no overflow, there's no reclaimable overflow.\n if (_overflow == 0) return 0;\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) return 0;\n\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Return the reclaimable overflow amount.\n return\n _reclaimableOverflowDuring(_projectId, _fundingCycle, _tokenCount, _totalSupply, _overflow);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /**\n @param _directory A contract storing directories of terminals and controllers for each project.\n @param _fundingCycleStore A contract storing all funding cycle configurations.\n @param _prices A contract that exposes price feeds.\n */\n constructor(\n IJBDirectory _directory,\n IJBFundingCycleStore _fundingCycleStore,\n IJBPrices _prices\n ) {\n directory = _directory;\n fundingCycleStore = _fundingCycleStore;\n prices = _prices;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /**\n @notice\n Records newly contributed tokens to a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.sender's tokens.\n\n @param _payer The original address that sent the payment to the terminal.\n @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.\n @param _projectId The ID of the project being paid.\n @param _baseWeightCurrency The currency to base token issuance on.\n @param _beneficiary The specified address that should be the beneficiary of anything that results from the payment.\n @param _memo A memo to pass along to the emitted event, and passed along to the funding cycle's data source.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The project's funding cycle during which payment was made.\n @return tokenCount The number of project tokens that were minted, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of adding to the local balance.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordPaymentFrom(\n address _payer,\n JBTokenAmount calldata _amount,\n uint256 _projectId,\n uint256 _baseWeightCurrency,\n address _beneficiary,\n string calldata _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 tokenCount,\n JBPayDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the current funding cycle for the project.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The project must have a funding cycle configured.\n if (fundingCycle.number == 0) revert INVALID_FUNDING_CYCLE();\n\n // Must not be paused.\n if (fundingCycle.payPaused()) revert FUNDING_CYCLE_PAYMENT_PAUSED();\n\n // The weight according to which new token supply is to be minted, as a fixed point number with 18 decimals.\n uint256 _weight;\n\n // If the funding cycle has configured a data source, use it to derive a weight and memo.\n if (fundingCycle.useDataSourceForPay() && fundingCycle.dataSource() != address(0)) {\n // Create the params that'll be sent to the data source.\n JBPayParamsData memory _data = JBPayParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _payer,\n _amount,\n _projectId,\n fundingCycle.configuration,\n _beneficiary,\n fundingCycle.weight,\n fundingCycle.reservedRate(),\n _memo,\n _metadata\n );\n (_weight, memo, delegateAllocations) = IJBFundingCycleDataSource(fundingCycle.dataSource())\n .payParams(_data);\n }\n // Otherwise use the funding cycle's weight\n else {\n _weight = fundingCycle.weight;\n memo = _memo;\n }\n\n // Scoped section prevents stack too deep. `_balanceDiff` only used within scope.\n {\n // Keep a reference to the amount that should be added to the project's balance.\n uint256 _balanceDiff = _amount.value;\n\n // Validate all delegated amounts. This needs to be done before returning the delegate allocations to ensure valid delegated amounts.\n if (delegateAllocations.length != 0) {\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0) {\n // Can't delegate more than was paid.\n if (_delegatedAmount > _balanceDiff) revert INVALID_AMOUNT_TO_SEND_DELEGATE();\n\n // Decrement the total amount being added to the balance.\n _balanceDiff = _balanceDiff - _delegatedAmount;\n }\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // If there's no amount being recorded, there's nothing left to do.\n if (_amount.value == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Add the correct balance difference to the token balance of the project.\n if (_balanceDiff != 0)\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _balanceDiff;\n }\n\n // If there's no weight, token count must be 0 so there's nothing left to do.\n if (_weight == 0) return (fundingCycle, 0, delegateAllocations, memo);\n\n // Get a reference to the number of decimals in the amount. (prevents stack too deep).\n uint256 _decimals = _amount.decimals;\n\n // If the terminal should base its weight on a different currency from the terminal's currency, determine the factor.\n // 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`.\n uint256 _weightRatio = _amount.currency == _baseWeightCurrency\n ? 10**_decimals\n : prices.priceFor(_amount.currency, _baseWeightCurrency, _decimals);\n\n // Find the number of tokens to mint, as a fixed point number with as many decimals as `weight` has.\n tokenCount = PRBMath.mulDiv(_amount.value, _weight, _weightRatio);\n }\n\n /**\n @notice\n Records newly redeemed tokens of a project.\n\n @dev\n 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.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount specified in the params is in terms of the msg.senders tokens.\n\n @param _holder The account that is having its tokens redeemed.\n @param _projectId The ID of the project to which the tokens being redeemed belong.\n @param _tokenCount The number of project tokens to redeem, as a fixed point number with 18 decimals.\n @param _memo A memo to pass along to the emitted event.\n @param _metadata Bytes to send along to the data source, if one is provided.\n\n @return fundingCycle The funding cycle during which the redemption was made.\n @return reclaimAmount The amount of terminal tokens reclaimed, as a fixed point number with 18 decimals.\n @return delegateAllocations The amount to send to delegates instead of sending to the beneficiary.\n @return memo A memo that should be passed along to the emitted event.\n */\n function recordRedemptionFor(\n address _holder,\n uint256 _projectId,\n uint256 _tokenCount,\n string memory _memo,\n bytes memory _metadata\n )\n external\n override\n nonReentrant\n returns (\n JBFundingCycle memory fundingCycle,\n uint256 reclaimAmount,\n JBRedemptionDelegateAllocation[] memory delegateAllocations,\n string memory memo\n )\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The current funding cycle must not be paused.\n if (fundingCycle.redeemPaused()) revert FUNDING_CYCLE_REDEEM_PAUSED();\n\n // Scoped section prevents stack too deep. `_reclaimedTokenAmount`, `_currentOverflow`, and `_totalSupply` only used within scope.\n {\n // Get a reference to the reclaimed token amount struct, the current overflow, and the total token supply.\n JBTokenAmount memory _reclaimedTokenAmount;\n uint256 _currentOverflow;\n uint256 _totalSupply;\n\n // Another scoped section prevents stack too deep. `_token`, `_decimals`, and `_currency` only used within scope.\n {\n // Get a reference to the terminal's tokens.\n address _token = IJBSingleTokenPaymentTerminal(msg.sender).token();\n\n // Get a reference to the terminal's decimals.\n uint256 _decimals = IJBSingleTokenPaymentTerminal(msg.sender).decimals();\n\n // Get areference to the terminal's currency.\n uint256 _currency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Get the amount of current overflow.\n // 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.\n _currentOverflow = fundingCycle.useTotalOverflowForRedemptions()\n ? _currentTotalOverflowOf(_projectId, _decimals, _currency)\n : _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _currency\n );\n\n // Get the number of outstanding tokens the project has.\n _totalSupply = IJBController3_1(directory.controllerOf(_projectId))\n .totalOutstandingTokensOf(_projectId);\n\n // Can't redeem more tokens that is in the supply.\n if (_tokenCount > _totalSupply) revert INSUFFICIENT_TOKENS();\n\n if (_currentOverflow != 0)\n // Calculate reclaim amount using the current overflow amount.\n reclaimAmount = _reclaimableOverflowDuring(\n _projectId,\n fundingCycle,\n _tokenCount,\n _totalSupply,\n _currentOverflow\n );\n\n _reclaimedTokenAmount = JBTokenAmount(_token, reclaimAmount, _decimals, _currency);\n }\n\n // If the funding cycle has configured a data source, use it to derive a claim amount and memo.\n if (fundingCycle.useDataSourceForRedeem() && fundingCycle.dataSource() != address(0)) {\n // Yet another scoped section prevents stack too deep. `_state` only used within scope.\n {\n // Get a reference to the ballot state.\n JBBallotState _state = fundingCycleStore.currentBallotStateOf(_projectId);\n\n // Create the params that'll be sent to the data source.\n JBRedeemParamsData memory _data = JBRedeemParamsData(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _holder,\n _projectId,\n fundingCycle.configuration,\n _tokenCount,\n _totalSupply,\n _currentOverflow,\n _reclaimedTokenAmount,\n fundingCycle.useTotalOverflowForRedemptions(),\n _state == JBBallotState.Active\n ? fundingCycle.ballotRedemptionRate()\n : fundingCycle.redemptionRate(),\n _memo,\n _metadata\n );\n (reclaimAmount, memo, delegateAllocations) = IJBFundingCycleDataSource(\n fundingCycle.dataSource()\n ).redeemParams(_data);\n }\n } else {\n memo = _memo;\n }\n }\n\n // Keep a reference to the amount that should be subtracted from the project's balance.\n uint256 _balanceDiff = reclaimAmount;\n\n if (delegateAllocations.length != 0) {\n // Validate all delegated amounts.\n for (uint256 _i; _i < delegateAllocations.length; ) {\n // Get a reference to the amount to be delegated.\n uint256 _delegatedAmount = delegateAllocations[_i].amount;\n\n // Validate if non-zero.\n if (_delegatedAmount != 0)\n // Increment the total amount being subtracted from the balance.\n _balanceDiff = _balanceDiff + _delegatedAmount;\n\n unchecked {\n ++_i;\n }\n }\n }\n\n // The amount being reclaimed must be within the project's balance.\n if (_balanceDiff > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Remove the reclaimed funds from the project's balance.\n if (_balanceDiff != 0) {\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n _balanceDiff;\n }\n }\n }\n\n /**\n @notice\n Records newly distributed funds for a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project that is having funds distributed.\n @param _amount The amount to use from the distribution limit, as a fixed point number.\n @param _currency The currency of the `_amount`. This must match the project's current funding cycle's currency.\n\n @return fundingCycle The funding cycle during which the distribution was made.\n @return distributedAmount The amount of terminal tokens distributed, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordDistributionFor(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 distributedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // The funding cycle must not be configured to have distributions paused.\n if (fundingCycle.distributionsPaused()) revert FUNDING_CYCLE_DISTRIBUTION_PAUSED();\n\n // The new total amount that has been distributed during this funding cycle.\n uint256 _newUsedDistributionLimitOf = usedDistributionLimitOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.number] + _amount;\n\n // Amount must be within what is still distributable.\n (uint256 _distributionLimitOf, uint256 _distributionLimitCurrencyOf) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).fundAccessConstraintsStore().distributionLimitOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the distribution limit.\n if (_newUsedDistributionLimitOf > _distributionLimitOf || _distributionLimitOf == 0)\n revert DISTRIBUTION_AMOUNT_LIMIT_REACHED();\n\n // Make sure the currencies match.\n if (_currency != _distributionLimitCurrencyOf) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to the balance's currency.\n distributedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available.\n if (distributedAmount > balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId])\n revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the new amount.\n usedDistributionLimitOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.number\n ] = _newUsedDistributionLimitOf;\n\n // Removed the distributed funds from the project's token balance.\n unchecked {\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n distributedAmount;\n }\n }\n\n /**\n @notice\n Records newly used allowance funds of a project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to use the allowance of.\n @param _amount The amount to use from the allowance, as a fixed point number. \n @param _currency The currency of the `_amount`. Must match the currency of the overflow allowance.\n\n @return fundingCycle The funding cycle during which the overflow allowance is being used.\n @return usedAmount The amount of terminal tokens used, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordUsedAllowanceOf(\n uint256 _projectId,\n uint256 _amount,\n uint256 _currency\n )\n external\n override\n nonReentrant\n returns (JBFundingCycle memory fundingCycle, uint256 usedAmount)\n {\n // Get a reference to the project's current funding cycle.\n fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Get a reference to the new used overflow allowance for this funding cycle configuration.\n uint256 _newUsedOverflowAllowanceOf = usedOverflowAllowanceOf[\n IJBSingleTokenPaymentTerminal(msg.sender)\n ][_projectId][fundingCycle.configuration] + _amount;\n\n // There must be sufficient allowance available.\n (uint256 _overflowAllowanceOf, uint256 _overflowAllowanceCurrency) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).fundAccessConstraintsStore().overflowAllowanceOf(\n _projectId,\n fundingCycle.configuration,\n IJBSingleTokenPaymentTerminal(msg.sender),\n IJBSingleTokenPaymentTerminal(msg.sender).token()\n );\n\n // Make sure the new used amount is within the allowance.\n if (_newUsedOverflowAllowanceOf > _overflowAllowanceOf || _overflowAllowanceOf == 0)\n revert INADEQUATE_CONTROLLER_ALLOWANCE();\n\n // Make sure the currencies match.\n if (_currency != _overflowAllowanceCurrency) revert CURRENCY_MISMATCH();\n\n // Get a reference to the terminal's currency.\n uint256 _balanceCurrency = IJBSingleTokenPaymentTerminal(msg.sender).currency();\n\n // Convert the amount to this store's terminal's token.\n usedAmount = (_currency == _balanceCurrency)\n ? _amount\n : PRBMath.mulDiv(\n _amount,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_currency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // The amount being distributed must be available in the overflow.\n if (\n usedAmount >\n _overflowDuring(\n IJBSingleTokenPaymentTerminal(msg.sender),\n _projectId,\n fundingCycle,\n _balanceCurrency\n )\n ) revert INADEQUATE_PAYMENT_TERMINAL_STORE_BALANCE();\n\n // Store the incremented value.\n usedOverflowAllowanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId][\n fundingCycle.configuration\n ] = _newUsedOverflowAllowanceOf;\n\n // Update the project's balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] -\n usedAmount;\n }\n\n /**\n @notice\n Records newly added funds for the project.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. \n\n @param _projectId The ID of the project to which the funds being added belong.\n @param _amount The amount of terminal tokens added, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordAddedBalanceFor(uint256 _projectId, uint256 _amount) external override {\n // Increment the balance.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] =\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] +\n _amount;\n }\n\n /**\n @notice\n Records the migration of funds from this store.\n\n @dev\n The msg.sender must be an IJBSingleTokenPaymentTerminal. The amount returned is in terms of the msg.senders tokens.\n\n @param _projectId The ID of the project being migrated.\n\n @return balance The project's migrated balance, as a fixed point number with the same amount of decimals as its relative terminal.\n */\n function recordMigration(uint256 _projectId)\n external\n override\n nonReentrant\n returns (uint256 balance)\n {\n // Get a reference to the project's current funding cycle.\n JBFundingCycle memory _fundingCycle = fundingCycleStore.currentOf(_projectId);\n\n // Migration must be allowed.\n if (!_fundingCycle.terminalMigrationAllowed()) revert PAYMENT_TERMINAL_MIGRATION_NOT_ALLOWED();\n\n // Return the current balance.\n balance = balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId];\n\n // Set the balance to 0.\n balanceOf[IJBSingleTokenPaymentTerminal(msg.sender)][_projectId] = 0;\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /**\n @notice\n The amount of overflowed tokens from a terminal that can be reclaimed by the specified number of tokens when measured from the specified.\n\n @dev \n If the project has an active funding cycle reconfiguration ballot, the project's ballot redemption rate is used.\n\n @param _projectId The ID of the project to get the reclaimable overflow amount for.\n @param _fundingCycle The funding cycle during which reclaimable overflow is being calculated.\n @param _tokenCount The number of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _totalSupply The total supply of tokens to make the calculation with, as a fixed point number with 18 decimals.\n @param _overflow The amount of overflow to make the calculation with.\n\n @return The amount of overflowed tokens that can be reclaimed.\n */\n function _reclaimableOverflowDuring(\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _tokenCount,\n uint256 _totalSupply,\n uint256 _overflow\n ) private view returns (uint256) {\n // If the amount being redeemed is the total supply, return the rest of the overflow.\n if (_tokenCount == _totalSupply) return _overflow;\n\n // Use the ballot redemption rate if the queued cycle is pending approval according to the previous funding cycle's ballot.\n uint256 _redemptionRate = fundingCycleStore.currentBallotStateOf(_projectId) ==\n JBBallotState.Active\n ? _fundingCycle.ballotRedemptionRate()\n : _fundingCycle.redemptionRate();\n\n // If the redemption rate is 0, nothing is claimable.\n if (_redemptionRate == 0) return 0;\n\n // Get a reference to the linear proportion.\n uint256 _base = PRBMath.mulDiv(_overflow, _tokenCount, _totalSupply);\n\n // These conditions are all part of the same curve. Edge conditions are separated because fewer operation are necessary.\n if (_redemptionRate == JBConstants.MAX_REDEMPTION_RATE) return _base;\n\n return\n PRBMath.mulDiv(\n _base,\n _redemptionRate +\n PRBMath.mulDiv(\n _tokenCount,\n JBConstants.MAX_REDEMPTION_RATE - _redemptionRate,\n _totalSupply\n ),\n JBConstants.MAX_REDEMPTION_RATE\n );\n }\n\n /**\n @notice\n Gets the amount that is overflowing when measured from the specified funding cycle.\n\n @dev\n This amount changes as the value of the balance changes in relation to the currency being used to measure the distribution limit.\n\n @param _terminal The terminal for which the overflow is being calculated.\n @param _projectId The ID of the project to get overflow for.\n @param _fundingCycle The ID of the funding cycle to base the overflow on.\n @param _balanceCurrency The currency that the stored balance is expected to be in terms of.\n\n @return overflow The overflow of funds, as a fixed point number with 18 decimals.\n */\n function _overflowDuring(\n IJBSingleTokenPaymentTerminal _terminal,\n uint256 _projectId,\n JBFundingCycle memory _fundingCycle,\n uint256 _balanceCurrency\n ) private view returns (uint256) {\n // Get the current balance of the project.\n uint256 _balanceOf = balanceOf[_terminal][_projectId];\n\n // If there's no balance, there's no overflow.\n if (_balanceOf == 0) return 0;\n\n // Get a reference to the distribution limit during the funding cycle.\n (uint256 _distributionLimit, uint256 _distributionLimitCurrency) = IJBController3_1(\n directory.controllerOf(_projectId)\n ).fundAccessConstraintsStore().distributionLimitOf(\n _projectId,\n _fundingCycle.configuration,\n _terminal,\n _terminal.token()\n );\n\n // Get a reference to the amount still distributable during the funding cycle.\n uint256 _distributionLimitRemaining = _distributionLimit -\n usedDistributionLimitOf[_terminal][_projectId][_fundingCycle.number];\n\n // Convert the _distributionRemaining to be in terms of the provided currency.\n if (_distributionLimitRemaining != 0 && _distributionLimitCurrency != _balanceCurrency)\n _distributionLimitRemaining = PRBMath.mulDiv(\n _distributionLimitRemaining,\n 10**_MAX_FIXED_POINT_FIDELITY, // Use _MAX_FIXED_POINT_FIDELITY to keep as much of the `_amount.value`'s fidelity as possible when converting.\n prices.priceFor(_distributionLimitCurrency, _balanceCurrency, _MAX_FIXED_POINT_FIDELITY)\n );\n\n // Overflow is the balance of this project minus the amount that can still be distributed.\n unchecked {\n return\n _balanceOf > _distributionLimitRemaining ? _balanceOf - _distributionLimitRemaining : 0;\n }\n }\n\n /**\n @notice\n Gets the amount that is currently overflowing across all of a project's terminals. \n\n @dev\n This amount changes as the value of the balances changes in relation to the currency being used to measure the project's distribution limits.\n\n @param _projectId The ID of the project to get the total overflow for.\n @param _decimals The number of decimals that the fixed point overflow should include.\n @param _currency The currency that the overflow should be in terms of.\n\n @return overflow The total overflow of a project's funds.\n */\n function _currentTotalOverflowOf(\n uint256 _projectId,\n uint256 _decimals,\n uint256 _currency\n ) private view returns (uint256) {\n // Get a reference to the project's terminals.\n IJBPaymentTerminal[] memory _terminals = directory.terminalsOf(_projectId);\n\n // Keep a reference to the ETH overflow across all terminals, as a fixed point number with 18 decimals.\n uint256 _ethOverflow;\n\n // Add the current ETH overflow for each terminal.\n for (uint256 _i; _i < _terminals.length; ) {\n _ethOverflow = _ethOverflow + _terminals[_i].currentEthOverflowOf(_projectId);\n unchecked {\n ++_i;\n }\n }\n\n // Convert the ETH overflow to the specified currency if needed, maintaining a fixed point number with 18 decimals.\n uint256 _totalOverflow18Decimal = _currency == JBCurrencies.GAS_CURRENCY\n ? _ethOverflow\n : PRBMath.mulDiv(_ethOverflow, 10**18, prices.priceFor(JBCurrencies.GAS_CURRENCY, _currency, 18));\n\n // Adjust the decimals of the fixed point number if needed to match the target decimals.\n return\n (_decimals == 18)\n ? _totalOverflow18Decimal\n : JBFixedPointNumber.adjustDecimals(_totalOverflow18Decimal, 18, _decimals);\n }\n}\n" }, "contracts/JBSplitsStore.sol": { "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport './abstract/JBOperatable.sol';\nimport './interfaces/IJBDirectory.sol';\nimport './interfaces/IJBSplitsStore.sol';\nimport './libraries/JBConstants.sol';\nimport './libraries/JBOperations.sol';\n\n/**\n @notice\n Stores splits for each project.\n\n @dev\n Adheres to -\n IJBSplitsStore: General interface for the methods in this contract that interact with the blockchain's state according to the protocol's rules.\n\n @dev\n Inherits from -\n JBOperatable: Includes convenience functionality for checking a message sender's permissions before executing certain transactions.\n*/\ncontract JBSplitsStore is JBOperatable, IJBSplitsStore {\n //*********************************************************************//\n // --------------------------- custom errors ------------------------- //\n //*********************************************************************//\n error INVALID_LOCKED_UNTIL();\n error INVALID_PROJECT_ID();\n error INVALID_SPLIT_PERCENT();\n error INVALID_TOTAL_PERCENT();\n error PREVIOUS_LOCKED_SPLITS_NOT_INCLUDED();\n\n //*********************************************************************//\n // --------------------- private stored properties ------------------- //\n //*********************************************************************//\n\n /** \n @notice\n The number of splits currently set for each project ID's configurations.\n\n _projectId The ID of the project to get the split count for.\n _domain An identifier within which the returned splits should be considered active.\n _group The identifying group of the splits.\n */\n mapping(uint256 => mapping(uint256 => mapping(uint256 => uint256))) private _splitCountOf;\n\n /** \n @notice\n Packed data of splits for each project ID's configurations.\n\n _projectId The ID of the project to get packed splits data for.\n _domain An identifier within which the returned splits should be considered active.\n _group The identifying group of the splits.\n _index The indexed order that the split was set at.\n */\n mapping(uint256 => mapping(uint256 => mapping(uint256 => mapping(uint256 => uint256))))\n private _packedSplitParts1Of;\n\n /** \n @notice\n More packed data of splits for each project ID's configurations.\n\n @dev\n This packed data is often 0.\n\n _projectId The ID of the project to get packed splits data for.\n _domain An identifier within which the returned splits should be considered active.\n _group The identifying group of the splits.\n _index The indexed order that the split was set at.\n */\n mapping(uint256 => mapping(uint256 => mapping(uint256 => mapping(uint256 => uint256))))\n private _packedSplitParts2Of;\n\n //*********************************************************************//\n // ---------------- public immutable stored properties --------------- //\n //*********************************************************************//\n\n /** \n @notice \n Mints ERC-721's that represent project ownership and transfers.\n */\n IJBProjects public immutable override projects;\n\n /** \n @notice \n The directory of terminals and controllers for projects.\n */\n IJBDirectory public immutable override directory;\n\n //*********************************************************************//\n // ------------------------- external views -------------------------- //\n //*********************************************************************//\n\n /**\n @notice \n Get all splits for the specified project ID, within the specified domain, for the specified group.\n\n @param _projectId The ID of the project to get splits for.\n @param _domain An identifier within which the returned splits should be considered active.\n @param _group The identifying group of the splits.\n\n @return An array of all splits for the project.\n*/\n function splitsOf(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) external view override returns (JBSplit[] memory) {\n return _getStructsFor(_projectId, _domain, _group);\n }\n\n //*********************************************************************//\n // -------------------------- constructor ---------------------------- //\n //*********************************************************************//\n\n /** \n @param _operatorStore A contract storing operator assignments.\n @param _projects A contract which mints ERC-721's that represent project ownership and transfers.\n @param _directory A contract storing directories of terminals and controllers for each project.\n */\n constructor(\n IJBOperatorStore _operatorStore,\n IJBProjects _projects,\n IJBDirectory _directory\n ) JBOperatable(_operatorStore) {\n projects = _projects;\n directory = _directory;\n }\n\n //*********************************************************************//\n // ---------------------- external transactions ---------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets a project's splits.\n\n @dev\n Only the owner or operator of a project, or the current controller contract of the project, can set its splits.\n\n @dev\n The new splits must include any currently set splits that are locked.\n\n @param _projectId The ID of the project for which splits are being added.\n @param _domain An identifier within which the splits should be considered active.\n @param _groupedSplits An array of splits to set for any number of groups. \n */\n function set(\n uint256 _projectId,\n uint256 _domain,\n JBGroupedSplits[] calldata _groupedSplits\n )\n external\n override\n requirePermissionAllowingOverride(\n projects.ownerOf(_projectId),\n _projectId,\n JBOperations.SET_SPLITS,\n address(directory.controllerOf(_projectId)) == msg.sender\n )\n {\n // Push array length in stack\n uint256 _groupedSplitsLength = _groupedSplits.length;\n\n // Set each grouped splits.\n for (uint256 _i; _i < _groupedSplitsLength; ) {\n // Get a reference to the grouped split being iterated on.\n JBGroupedSplits memory _groupedSplit = _groupedSplits[_i];\n\n // Set the splits for the group.\n _set(_projectId, _domain, _groupedSplit.group, _groupedSplit.splits);\n\n unchecked {\n ++_i;\n }\n }\n }\n\n //*********************************************************************//\n // --------------------- private helper functions -------------------- //\n //*********************************************************************//\n\n /** \n @notice \n Sets a project's splits.\n\n @dev\n The new splits must include any currently set splits that are locked.\n\n @param _projectId The ID of the project for which splits are being added.\n @param _domain An identifier within which the splits should be considered active.\n @param _group An identifier between of splits being set. All splits within this _group must add up to within 100%.\n @param _splits The splits to set.\n */\n function _set(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group,\n JBSplit[] memory _splits\n ) internal {\n // Get a reference to the project's current splits.\n JBSplit[] memory _currentSplits = _getStructsFor(_projectId, _domain, _group);\n\n // Keep a reference to the number of splits.\n uint256 _currentSplitsLength = _currentSplits.length;\n\n // Check to see if all locked splits are included.\n for (uint256 _i; _i < _currentSplitsLength; ) {\n // If not locked, continue.\n if (\n block.timestamp < _currentSplits[_i].lockedUntil &&\n !_includesLocked(_splits, _currentSplits[_i])\n ) revert PREVIOUS_LOCKED_SPLITS_NOT_INCLUDED();\n\n unchecked {\n ++_i;\n }\n }\n\n // Add up all the percents to make sure they cumulatively are under 100%.\n uint256 _percentTotal;\n\n // Keep a reference to the number of splits.\n uint256 _splitsLength = _splits.length;\n\n for (uint256 _i; _i < _splitsLength; ) {\n // The percent should be greater than 0.\n if (_splits[_i].percent == 0) revert INVALID_SPLIT_PERCENT();\n\n // ProjectId should be within a uint56\n if (_splits[_i].projectId > type(uint56).max) revert INVALID_PROJECT_ID();\n\n // Add to the total percents.\n _percentTotal = _percentTotal + _splits[_i].percent;\n\n // Validate the total does not exceed the expected value.\n if (_percentTotal > JBConstants.SPLITS_TOTAL_PERCENT) revert INVALID_TOTAL_PERCENT();\n\n uint256 _packedSplitParts1;\n\n // prefer claimed in bit 0.\n if (_splits[_i].preferClaimed) _packedSplitParts1 = 1;\n // prefer add to balance in bit 1.\n if (_splits[_i].preferAddToBalance) _packedSplitParts1 |= 1 << 1;\n // percent in bits 2-33.\n _packedSplitParts1 |= _splits[_i].percent << 2;\n // projectId in bits 32-89.\n _packedSplitParts1 |= _splits[_i].projectId << 34;\n // beneficiary in bits 90-249.\n _packedSplitParts1 |= uint256(uint160(address(_splits[_i].beneficiary))) << 90;\n\n // Store the first split part.\n _packedSplitParts1Of[_projectId][_domain][_group][_i] = _packedSplitParts1;\n\n // If there's data to store in the second packed split part, pack and store.\n if (_splits[_i].lockedUntil > 0 || _splits[_i].allocator != IJBSplitAllocator(address(0))) {\n // Locked until should be within a uint48\n if (_splits[_i].lockedUntil > type(uint48).max) revert INVALID_LOCKED_UNTIL();\n\n // lockedUntil in bits 0-47.\n uint256 _packedSplitParts2 = uint48(_splits[_i].lockedUntil);\n // allocator in bits 48-207.\n _packedSplitParts2 |= uint256(uint160(address(_splits[_i].allocator))) << 48;\n\n // Store the second split part.\n _packedSplitParts2Of[_projectId][_domain][_group][_i] = _packedSplitParts2;\n\n // Otherwise if there's a value stored in the indexed position, delete it.\n } else if (_packedSplitParts2Of[_projectId][_domain][_group][_i] > 0)\n delete _packedSplitParts2Of[_projectId][_domain][_group][_i];\n\n emit SetSplit(_projectId, _domain, _group, _splits[_i], msg.sender);\n\n unchecked {\n ++_i;\n }\n }\n\n // Set the new length of the splits.\n _splitCountOf[_projectId][_domain][_group] = _splitsLength;\n }\n\n /** \n @notice\n A flag indiciating if the provided splits array includes the locked split. \n\n @param _splits The array of splits to check within.\n @param _lockedSplit The locked split.\n\n @return A flag indicating if the `_lockedSplit` is contained in the `_splits`.\n */\n function _includesLocked(JBSplit[] memory _splits, JBSplit memory _lockedSplit)\n private\n pure\n returns (bool)\n {\n // Keep a reference to the number of splits.\n uint256 _numberOfSplits = _splits.length;\n\n for (uint256 _i; _i < _numberOfSplits; ) {\n // Check for sameness.\n if (\n _splits[_i].percent == _lockedSplit.percent &&\n _splits[_i].beneficiary == _lockedSplit.beneficiary &&\n _splits[_i].allocator == _lockedSplit.allocator &&\n _splits[_i].projectId == _lockedSplit.projectId &&\n _splits[_i].preferClaimed == _lockedSplit.preferClaimed &&\n _splits[_i].preferAddToBalance == _lockedSplit.preferAddToBalance &&\n // Allow lock extention.\n _splits[_i].lockedUntil >= _lockedSplit.lockedUntil\n ) return true;\n\n unchecked {\n ++_i;\n }\n }\n\n return false;\n }\n\n /**\n @notice \n Unpack splits' packed stored values into easy-to-work-with split structs.\n\n @param _projectId The ID of the project to which the split belongs.\n @param _domain The identifier within which the returned splits should be considered active.\n @param _group The identifying group of the splits.\n\n @return splits The split structs.\n */\n function _getStructsFor(\n uint256 _projectId,\n uint256 _domain,\n uint256 _group\n ) private view returns (JBSplit[] memory) {\n // Get a reference to the number of splits that need to be added to the returned array.\n uint256 _splitCount = _splitCountOf[_projectId][_domain][_group];\n\n // Initialize an array to be returned that has the set length.\n JBSplit[] memory _splits = new JBSplit[](_splitCount);\n\n // Loop through each split and unpack the values into structs.\n for (uint256 _i; _i < _splitCount; ) {\n // Get a reference to the fist packed data.\n uint256 _packedSplitPart1 = _packedSplitParts1Of[_projectId][_domain][_group][_i];\n\n // Populate the split struct.\n JBSplit memory _split;\n\n // prefer claimed in bit 0.\n _split.preferClaimed = _packedSplitPart1 & 1 == 1;\n // prefer add to balance in bit 1.\n _split.preferAddToBalance = (_packedSplitPart1 >> 1) & 1 == 1;\n // percent in bits 2-33.\n _split.percent = uint256(uint32(_packedSplitPart1 >> 2));\n // projectId in bits 32-89.\n _split.projectId = uint256(uint56(_packedSplitPart1 >> 34));\n // beneficiary in bits 90-249.\n _split.beneficiary = payable(address(uint160(_packedSplitPart1 >> 90)));\n\n // Get a reference to the second packed data.\n uint256 _packedSplitPart2 = _packedSplitParts2Of[_projectId][_domain][_group][_i];\n\n // If there's anything in it, unpack.\n if (_packedSplitPart2 > 0) {\n // lockedUntil in bits 0-47.\n _split.lockedUntil = uint256(uint48(_packedSplitPart2));\n // allocator in bits 48-207.\n _split.allocator = IJBSplitAllocator(address(uint160(_packedSplitPart2 >> 48)));\n }\n\n // Add the split to the value being returned.\n _splits[_i] = _split;\n\n unchecked {\n ++_i;\n }\n }\n\n return _splits;\n }\n}\n" diff --git a/forge_tests/TestController3_0_1.sol b/forge_tests/TestController3_0_1.sol index 54ffda689..e4a3c1db6 100644 --- a/forge_tests/TestController3_0_1.sol +++ b/forge_tests/TestController3_0_1.sol @@ -124,7 +124,7 @@ contract TestController31_Fork is Test { fundAccessConstraints.push( JBFundAccessConstraints({ terminal: jbEthTerminal, - token: JBTokens.ETH, + token: JBTokens.GAS_TOKEN, distributionLimit: targetInWei, // 10 ETH target overflowAllowance: 5 ether, distributionLimitCurrency: 1, // Currency = ETH diff --git a/forge_tests/TestDelegates.sol b/forge_tests/TestDelegates.sol index fdfa98dd6..d85114b5e 100644 --- a/forge_tests/TestDelegates.sol +++ b/forge_tests/TestDelegates.sol @@ -114,13 +114,13 @@ contract TestDelegates_Local is TestBaseWorkflow { _projectId, fundingCycle.configuration, JBTokenAmount( - JBTokens.ETH, + JBTokens.GAS_TOKEN, _paySum, JBSingleTokenPaymentTerminal(address(_terminals[0])).decimals(), JBSingleTokenPaymentTerminal(address(_terminals[0])).currency() ), JBTokenAmount( - JBTokens.ETH, + JBTokens.GAS_TOKEN, payDelegateAmounts[i], JBSingleTokenPaymentTerminal(address(_terminals[0])).decimals(), JBSingleTokenPaymentTerminal(address(_terminals[0])).currency() diff --git a/forge_tests/TestEIP165.sol b/forge_tests/TestEIP165.sol index 5af53fee3..bfbc7c80b 100644 --- a/forge_tests/TestEIP165.sol +++ b/forge_tests/TestEIP165.sol @@ -1,143 +1,151 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.6; -import "./helpers/TestBaseWorkflow.sol"; -import "@juicebox/JBReconfigurationBufferBallot.sol"; -import "@juicebox/JBETHERC20SplitsPayer.sol"; -import "@juicebox/JBETHERC20SplitsPayerDeployer.sol"; +import './helpers/TestBaseWorkflow.sol'; +import '@juicebox/JBReconfigurationBufferBallot.sol'; +import '@juicebox/JBGasTokenERC20SplitsPayer.sol'; +import '@juicebox/JBGasTokenERC20SplitsPayerDeployer.sol'; contract TestEIP165_Local is TestBaseWorkflow { - bytes4 constant notSupportedInterface = 0xffffffff; - - uint256 constant projectId = 2; - uint256 constant splitsProjectID = 3; - address payable constant splitsBeneficiary = payable(address(420)); - uint256 constant splitsDomain = 1; - uint256 constant splitsGroup = 1; - bool constant splitsPreferClaimedTokens = false; - string constant splitsMemo = ""; - bytes constant splitsMetadata = ""; - bool constant splitsPreferAddToBalance = true; - address constant splitsOwner = address(420); - - function testJBController() public { - JBController controller = jbController(); - - // Should support these interfaces - assertTrue(controller.supportsInterface(type(IERC165).interfaceId)); - assertTrue(controller.supportsInterface(type(IJBMigratable).interfaceId)); - assertTrue(controller.supportsInterface(type(IJBOperatable).interfaceId)); - - if (isUsingJbController3_0()) { - assertTrue(controller.supportsInterface(type(IJBController).interfaceId)); - } else { - assertTrue(controller.supportsInterface(type(IJBController3_1).interfaceId)); - } - - // Make sure it doesn't always return true - assertTrue(!controller.supportsInterface(notSupportedInterface)); + bytes4 constant notSupportedInterface = 0xffffffff; + + uint256 constant projectId = 2; + uint256 constant splitsProjectID = 3; + address payable constant splitsBeneficiary = payable(address(420)); + uint256 constant splitsDomain = 1; + uint256 constant splitsGroup = 1; + bool constant splitsPreferClaimedTokens = false; + string constant splitsMemo = ''; + bytes constant splitsMetadata = ''; + bool constant splitsPreferAddToBalance = true; + address constant splitsOwner = address(420); + + function testJBController() public { + JBController controller = jbController(); + + // Should support these interfaces + assertTrue(controller.supportsInterface(type(IERC165).interfaceId)); + assertTrue(controller.supportsInterface(type(IJBMigratable).interfaceId)); + assertTrue(controller.supportsInterface(type(IJBOperatable).interfaceId)); + + if (isUsingJbController3_0()) { + assertTrue(controller.supportsInterface(type(IJBController).interfaceId)); + } else { + assertTrue(controller.supportsInterface(type(IJBController3_1).interfaceId)); } - function testJBERC20PaymentTerminal() public { - JBERC20PaymentTerminal terminal = jbERC20PaymentTerminal(); - - // Should support these interfaces - assertTrue(terminal.supportsInterface(type(IERC165).interfaceId)); - assertTrue(terminal.supportsInterface(type(IJBPaymentTerminal).interfaceId)); - assertTrue(terminal.supportsInterface(type(IJBRedemptionTerminal).interfaceId)); - assertTrue(terminal.supportsInterface(type(IJBSingleTokenPaymentTerminal).interfaceId)); - assertTrue(terminal.supportsInterface(type(IJBOperatable).interfaceId)); - - if (isUsingJbController3_0()) { - assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal).interfaceId)); - assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal).interfaceId)); - assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal).interfaceId)); - } else { - assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal3_1).interfaceId)); - assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal3_1).interfaceId)); - assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal3_1).interfaceId)); - } - - // Make sure it doesn't always return true - assertTrue(!terminal.supportsInterface(notSupportedInterface)); + // Make sure it doesn't always return true + assertTrue(!controller.supportsInterface(notSupportedInterface)); + } + + function testJBERC20PaymentTerminal() public { + JBERC20PaymentTerminal terminal = jbERC20PaymentTerminal(); + + // Should support these interfaces + assertTrue(terminal.supportsInterface(type(IERC165).interfaceId)); + assertTrue(terminal.supportsInterface(type(IJBPaymentTerminal).interfaceId)); + assertTrue(terminal.supportsInterface(type(IJBRedemptionTerminal).interfaceId)); + assertTrue(terminal.supportsInterface(type(IJBSingleTokenPaymentTerminal).interfaceId)); + assertTrue(terminal.supportsInterface(type(IJBOperatable).interfaceId)); + + if (isUsingJbController3_0()) { + assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal).interfaceId)); + assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal).interfaceId)); + assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal).interfaceId)); + } else { + assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal3_1).interfaceId)); + assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal3_1).interfaceId)); + assertTrue( + terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal3_1).interfaceId) + ); } - function testJBETHPaymentTerminal() public { - JBETHPaymentTerminal terminal = jbETHPaymentTerminal(); - - // Should support these interfaces - assertTrue(terminal.supportsInterface(type(IERC165).interfaceId)); - assertTrue(terminal.supportsInterface(type(IJBPaymentTerminal).interfaceId)); - assertTrue(terminal.supportsInterface(type(IJBRedemptionTerminal).interfaceId)); - assertTrue(terminal.supportsInterface(type(IJBSingleTokenPaymentTerminal).interfaceId)); - assertTrue(terminal.supportsInterface(type(IJBOperatable).interfaceId)); - - if (isUsingJbController3_0()) { - assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal).interfaceId)); - assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal).interfaceId)); - assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal).interfaceId)); - } else { - assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal3_1).interfaceId)); - assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal3_1).interfaceId)); - assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal3_1).interfaceId)); - } - // Make sure it doesn't always return true - assertTrue(!terminal.supportsInterface(notSupportedInterface)); - } - - function testJBProjects() public { - JBProjects projects = jbProjects(); - - // Should support these interfaces - assertTrue(projects.supportsInterface(type(IERC165).interfaceId)); - assertTrue(projects.supportsInterface(type(IERC721).interfaceId)); - assertTrue(projects.supportsInterface(type(IERC721Metadata).interfaceId)); - assertTrue(projects.supportsInterface(type(IJBProjects).interfaceId)); - assertTrue(projects.supportsInterface(type(IJBOperatable).interfaceId)); - - // Make sure it doesn't always return true - assertTrue(!projects.supportsInterface(notSupportedInterface)); - } - - function testJBReconfigurationBufferBallot() public { - JBReconfigurationBufferBallot ballot = new JBReconfigurationBufferBallot(3000); - - // Should support these interfaces - assertTrue(ballot.supportsInterface(type(IERC165).interfaceId)); - // TODO: Add interface - //assertTrue(ballot.supportsInterface(type(IJBReconfigurationBufferBallot).interfaceId)); - assertTrue(ballot.supportsInterface(type(IJBFundingCycleBallot).interfaceId)); - - // Make sure it doesn't always return true - assertTrue(!ballot.supportsInterface(notSupportedInterface)); - } - - function testJBETHERC20SplitsPayer() public { - - JBETHERC20SplitsPayerDeployer deployer = new JBETHERC20SplitsPayerDeployer(jbSplitsStore()); - - JBETHERC20SplitsPayer splitsPayer = JBETHERC20SplitsPayer( - payable( - address( - deployer.deploySplitsPayer( - splitsProjectID, - splitsDomain, - splitsGroup, - projectId, - splitsBeneficiary, - splitsPreferClaimedTokens, - splitsMemo, - splitsMetadata, - splitsPreferAddToBalance, - splitsOwner - )))); - - // Should support these interfaces - assertTrue(splitsPayer.supportsInterface(type(IERC165).interfaceId)); - assertTrue(splitsPayer.supportsInterface(type(IJBSplitsPayer).interfaceId)); - assertTrue(splitsPayer.supportsInterface(type(IJBProjectPayer).interfaceId)); - - // Make sure it doesn't always return true - assertTrue(!splitsPayer.supportsInterface(notSupportedInterface)); + // Make sure it doesn't always return true + assertTrue(!terminal.supportsInterface(notSupportedInterface)); + } + + function testJBETHPaymentTerminal() public { + JBETHPaymentTerminal terminal = jbETHPaymentTerminal(); + + // Should support these interfaces + assertTrue(terminal.supportsInterface(type(IERC165).interfaceId)); + assertTrue(terminal.supportsInterface(type(IJBPaymentTerminal).interfaceId)); + assertTrue(terminal.supportsInterface(type(IJBRedemptionTerminal).interfaceId)); + assertTrue(terminal.supportsInterface(type(IJBSingleTokenPaymentTerminal).interfaceId)); + assertTrue(terminal.supportsInterface(type(IJBOperatable).interfaceId)); + + if (isUsingJbController3_0()) { + assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal).interfaceId)); + assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal).interfaceId)); + assertTrue(terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal).interfaceId)); + } else { + assertTrue(terminal.supportsInterface(type(IJBPayoutTerminal3_1).interfaceId)); + assertTrue(terminal.supportsInterface(type(IJBAllowanceTerminal3_1).interfaceId)); + assertTrue( + terminal.supportsInterface(type(IJBPayoutRedemptionPaymentTerminal3_1).interfaceId) + ); } + // Make sure it doesn't always return true + assertTrue(!terminal.supportsInterface(notSupportedInterface)); + } + + function testJBProjects() public { + JBProjects projects = jbProjects(); + + // Should support these interfaces + assertTrue(projects.supportsInterface(type(IERC165).interfaceId)); + assertTrue(projects.supportsInterface(type(IERC721).interfaceId)); + assertTrue(projects.supportsInterface(type(IERC721Metadata).interfaceId)); + assertTrue(projects.supportsInterface(type(IJBProjects).interfaceId)); + assertTrue(projects.supportsInterface(type(IJBOperatable).interfaceId)); + + // Make sure it doesn't always return true + assertTrue(!projects.supportsInterface(notSupportedInterface)); + } + + function testJBReconfigurationBufferBallot() public { + JBReconfigurationBufferBallot ballot = new JBReconfigurationBufferBallot(3000); + + // Should support these interfaces + assertTrue(ballot.supportsInterface(type(IERC165).interfaceId)); + // TODO: Add interface + //assertTrue(ballot.supportsInterface(type(IJBReconfigurationBufferBallot).interfaceId)); + assertTrue(ballot.supportsInterface(type(IJBFundingCycleBallot).interfaceId)); + + // Make sure it doesn't always return true + assertTrue(!ballot.supportsInterface(notSupportedInterface)); + } + + function testJBGasTokenERC20SplitsPayer() public { + JBGasTokenERC20SplitsPayerDeployer deployer = new JBGasTokenERC20SplitsPayerDeployer( + jbSplitsStore() + ); + + JBGasTokenERC20SplitsPayer splitsPayer = JBGasTokenERC20SplitsPayer( + payable( + address( + deployer.deploySplitsPayer( + splitsProjectID, + splitsDomain, + splitsGroup, + projectId, + splitsBeneficiary, + splitsPreferClaimedTokens, + splitsMemo, + splitsMetadata, + splitsPreferAddToBalance, + splitsOwner + ) + ) + ) + ); + + // Should support these interfaces + assertTrue(splitsPayer.supportsInterface(type(IERC165).interfaceId)); + assertTrue(splitsPayer.supportsInterface(type(IJBSplitsPayer).interfaceId)); + assertTrue(splitsPayer.supportsInterface(type(IJBProjectPayer).interfaceId)); + + // Make sure it doesn't always return true + assertTrue(!splitsPayer.supportsInterface(notSupportedInterface)); + } } diff --git a/forge_tests/TestMigrationOperator.sol b/forge_tests/TestMigrationOperator.sol index 7b9916656..685208205 100644 --- a/forge_tests/TestMigrationOperator.sol +++ b/forge_tests/TestMigrationOperator.sol @@ -141,7 +141,7 @@ contract TestMigrationOperator_Local is TestBaseWorkflow { // Check: the project must use the new terminal as primary terminal assertEq( - address(jbDirectory().primaryTerminalOf(projectId, JBTokens.ETH)), + address(jbDirectory().primaryTerminalOf(projectId, JBTokens.GAS_TOKEN)), address(jbEthTerminal3_1) ); @@ -279,7 +279,7 @@ contract TestMigrationOperator_Local is TestBaseWorkflow { fundAccessConstraints.push( JBFundAccessConstraints({ terminal: jbETHPaymentTerminal(), - token: JBTokens.ETH, + token: JBTokens.GAS_TOKEN, distributionLimit: 10 ether, overflowAllowance: 5 ether, distributionLimitCurrency: 1, // Currency = ETH @@ -387,7 +387,7 @@ contract TestMigrationOperator_Fork is Test { // Check: the project must use the new terminal as primary terminal assertEq( - address(jbDirectory.primaryTerminalOf(_projectId, JBTokens.ETH)), + address(jbDirectory.primaryTerminalOf(_projectId, JBTokens.GAS_TOKEN)), address(jbEthPaymentTerminal3_1) ); } @@ -483,7 +483,7 @@ contract TestMigrationOperator_Fork is Test { fundAccessConstraints.push( JBFundAccessConstraints({ terminal: jbEthTerminal, - token: JBTokens.ETH, + token: JBTokens.GAS_TOKEN, distributionLimit: 10 ether, overflowAllowance: 5 ether, distributionLimitCurrency: 1, diff --git a/forge_tests/TestPlanetable.sol b/forge_tests/TestPlanetable.sol index ac51b2228..0e7ddf4b7 100644 --- a/forge_tests/TestPlanetable.sol +++ b/forge_tests/TestPlanetable.sol @@ -76,7 +76,7 @@ contract TestPlanetable_Fork is Test { jbSplitsStore = jbController3_1.splitsStore(); uint256 _projectId = 471; - jbEthTerminal = IJBPayoutRedemptionPaymentTerminal(address(jbDirectory.primaryTerminalOf(_projectId, JBTokens.ETH))); + jbEthTerminal = IJBPayoutRedemptionPaymentTerminal(address(jbDirectory.primaryTerminalOf(_projectId, JBTokens.GAS_TOKEN))); address _projectOwner = jbProjects.ownerOf(_projectId); JBFundingCycle memory fundingCycle = jbFundingCycleStore.currentOf(_projectId); @@ -95,11 +95,11 @@ contract TestPlanetable_Fork is Test { JBFundAccessConstraints memory fundAccessConstraint; fundAccessConstraint.terminal = jbEthTerminal3_1; - fundAccessConstraint.token = JBTokens.ETH; + fundAccessConstraint.token = JBTokens.GAS_TOKEN; fundAccessConstraint.distributionLimit = 2 ether; - fundAccessConstraint.distributionLimitCurrency = JBCurrencies.ETH; + fundAccessConstraint.distributionLimitCurrency = JBCurrencies.GAS_CURRENCY; fundAccessConstraint.overflowAllowance = 0; - fundAccessConstraint.overflowAllowanceCurrency = JBCurrencies.ETH; + fundAccessConstraint.overflowAllowanceCurrency = JBCurrencies.GAS_CURRENCY; fundAccessConstraints.push(fundAccessConstraint); @@ -126,11 +126,11 @@ contract TestPlanetable_Fork is Test { jbEthTerminal.migrate(_projectId, jbEthTerminal3_1); // Check: New terminal is the primary? - assertEq(address(jbDirectory.primaryTerminalOf(_projectId, JBTokens.ETH)), address(jbEthTerminal3_1)); + assertEq(address(jbDirectory.primaryTerminalOf(_projectId, JBTokens.GAS_TOKEN)), address(jbEthTerminal3_1)); // Check: distribute? uint256 _balanceBefore = _groupedSplits[0].splits[0].beneficiary.balance; - jbEthTerminal3_1.distributePayoutsOf(_projectId, 2 ether, 1, JBTokens.ETH, 0, ''); + jbEthTerminal3_1.distributePayoutsOf(_projectId, 2 ether, 1, JBTokens.GAS_TOKEN, 0, ''); assertApproxEqRel(_balanceBefore + 2 ether, _groupedSplits[0].splits[0].beneficiary.balance, 0.025 ether); } @@ -147,7 +147,7 @@ contract TestPlanetable_Fork is Test { jbSplitsStore = jbController3_1.splitsStore(); uint256 _projectId = 471; - jbEthTerminal = IJBPayoutRedemptionPaymentTerminal(address(jbDirectory.primaryTerminalOf(_projectId, JBTokens.ETH))); + jbEthTerminal = IJBPayoutRedemptionPaymentTerminal(address(jbDirectory.primaryTerminalOf(_projectId, JBTokens.GAS_TOKEN))); address _projectOwner = jbProjects.ownerOf(_projectId); JBFundingCycle memory fundingCycle = jbFundingCycleStore.currentOf(_projectId); @@ -178,11 +178,11 @@ contract TestPlanetable_Fork is Test { jbEthTerminal.migrate(_projectId, jbEthTerminal3_1); // Check: New terminal is the primary? - assertEq(address(jbDirectory.primaryTerminalOf(_projectId, JBTokens.ETH)), address(jbEthTerminal3_1)); + assertEq(address(jbDirectory.primaryTerminalOf(_projectId, JBTokens.GAS_TOKEN)), address(jbEthTerminal3_1)); // Check: distribute? uint256 _balanceBefore = _groupedSplits[0].splits[0].beneficiary.balance; - jbEthTerminal3_1.distributePayoutsOf(_projectId, 2 ether, 1, JBTokens.ETH, 0, ''); + jbEthTerminal3_1.distributePayoutsOf(_projectId, 2 ether, 1, JBTokens.GAS_TOKEN, 0, ''); assertApproxEqRel(_balanceBefore + 2 ether, _groupedSplits[0].splits[0].beneficiary.balance, 0.025 ether); } } \ No newline at end of file diff --git a/forge_tests/TestTerminal3_1.sol b/forge_tests/TestTerminal3_1.sol index ff8cc5982..758286406 100644 --- a/forge_tests/TestTerminal3_1.sol +++ b/forge_tests/TestTerminal3_1.sol @@ -150,7 +150,7 @@ contract TestTerminal31_Fork is Test { assertEq(address(jbEthTerminal).balance, _ETHBalanceJbOldTerminal - _balanceJbOldTerminal); // Check: New terminal is the primary? - assertEq(address(jbDirectory.primaryTerminalOf(1, JBTokens.ETH)), address(jbEthTerminal3_1)); + assertEq(address(jbDirectory.primaryTerminalOf(1, JBTokens.GAS_TOKEN)), address(jbEthTerminal3_1)); } /** @@ -190,7 +190,7 @@ contract TestTerminal31_Fork is Test { // Check: New terminal is the primary? assertEq( - address(jbDirectory.primaryTerminalOf(_projectId, JBTokens.ETH)), + address(jbDirectory.primaryTerminalOf(_projectId, JBTokens.GAS_TOKEN)), address(jbEthTerminal3_1) ); } @@ -265,7 +265,7 @@ contract TestTerminal31_Fork is Test { // Reconfigure with new distribution limit, in the new controller fundAccessConstraints[0] = JBFundAccessConstraints({ terminal: jbEthTerminal3_1, - token: JBTokens.ETH, + token: JBTokens.GAS_TOKEN, distributionLimit: 0, // Only overflow overflowAllowance: 0, distributionLimitCurrency: 2, // Currency = ETH @@ -452,7 +452,7 @@ contract TestTerminal31_Fork is Test { // Reconfigure with new distribution limit, in the new controller fundAccessConstraints[0] = JBFundAccessConstraints({ terminal: jbEthTerminal3_1, - token: JBTokens.ETH, + token: JBTokens.GAS_TOKEN, distributionLimit: targetInUSD, overflowAllowance: 0, distributionLimitCurrency: 2, // Currency = ETH @@ -475,7 +475,7 @@ contract TestTerminal31_Fork is Test { // Distribute all the target available (uint256 _distributionLimit, uint256 _distributionCurrency) = jbFundsAccessConstraintsStore - .distributionLimitOf(1, fundingCycle.configuration, jbEthTerminal3_1, JBTokens.ETH); + .distributionLimitOf(1, fundingCycle.configuration, jbEthTerminal3_1, JBTokens.GAS_TOKEN); vm.prank(_caller); jbEthTerminal3_1.distributePayoutsOf( @@ -500,7 +500,7 @@ contract TestTerminal31_Fork is Test { uint256 _shareInTerminalToken = PRBMath.mulDiv( _shareInDistributionCurrency, 10 ** 18, - jbPrices.priceFor(_distributionCurrency, JBCurrencies.ETH, 18) + jbPrices.priceFor(_distributionCurrency, JBCurrencies.GAS_CURRENCY, 18) ); if (_split[i].projectId != 0) { @@ -537,7 +537,7 @@ contract TestTerminal31_Fork is Test { uint256 _totalDistributed = PRBMath.mulDiv( _distributionLimit, 10 ** 18, - jbPrices.priceFor(_distributionCurrency, JBCurrencies.ETH, 18) + jbPrices.priceFor(_distributionCurrency, JBCurrencies.GAS_CURRENCY, 18) ); assertApproxEqRel( @@ -578,7 +578,7 @@ contract TestTerminal31_Fork is Test { "tap(uint256,uint256,uint256,uint256)", 1, _amount, - JBCurrencies.ETH, + JBCurrencies.GAS_CURRENCY, _minAmountReturned ) ); @@ -725,7 +725,7 @@ contract TestTerminal31_Fork is Test { fundAccessConstraints.push( JBFundAccessConstraints({ terminal: jbEthTerminal, - token: JBTokens.ETH, + token: JBTokens.GAS_TOKEN, distributionLimit: targetInUSD, overflowAllowance: 5 ether, distributionLimitCurrency: 1, // Currency = ETH diff --git a/forge_tests/helpers/AccessJBLib.sol b/forge_tests/helpers/AccessJBLib.sol index 707d16ee7..3c168797a 100644 --- a/forge_tests/helpers/AccessJBLib.sol +++ b/forge_tests/helpers/AccessJBLib.sol @@ -1,44 +1,44 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.6; -import "@juicebox/libraries/JBCurrencies.sol"; -import "@juicebox/libraries/JBConstants.sol"; -import "@juicebox/libraries/JBTokens.sol"; +import '@juicebox/libraries/JBCurrencies.sol'; +import '@juicebox/libraries/JBConstants.sol'; +import '@juicebox/libraries/JBTokens.sol'; contract AccessJBLib { - function ETH() external pure returns (uint256) { - return JBCurrencies.ETH; - } + function ETH() external pure returns (uint256) { + return JBCurrencies.GAS_CURRENCY; + } - function USD() external pure returns (uint256) { - return JBCurrencies.USD; - } + function USD() external pure returns (uint256) { + return JBCurrencies.USD; + } - function ETHToken() external pure returns (address) { - return JBTokens.ETH; - } + function ETHToken() external pure returns (address) { + return JBTokens.GAS_TOKEN; + } - function MAX_FEE() external pure returns (uint256) { - return JBConstants.MAX_FEE; - } + function MAX_FEE() external pure returns (uint256) { + return JBConstants.MAX_FEE; + } - function MAX_RESERVED_RATE() external pure returns (uint256) { - return JBConstants.MAX_RESERVED_RATE; - } + function MAX_RESERVED_RATE() external pure returns (uint256) { + return JBConstants.MAX_RESERVED_RATE; + } - function MAX_REDEMPTION_RATE() external pure returns (uint256) { - return JBConstants.MAX_REDEMPTION_RATE; - } + function MAX_REDEMPTION_RATE() external pure returns (uint256) { + return JBConstants.MAX_REDEMPTION_RATE; + } - function MAX_DISCOUNT_RATE() external pure returns (uint256) { - return JBConstants.MAX_DISCOUNT_RATE; - } + function MAX_DISCOUNT_RATE() external pure returns (uint256) { + return JBConstants.MAX_DISCOUNT_RATE; + } - function SPLITS_TOTAL_PERCENT() external pure returns (uint256) { - return JBConstants.SPLITS_TOTAL_PERCENT; - } + function SPLITS_TOTAL_PERCENT() external pure returns (uint256) { + return JBConstants.SPLITS_TOTAL_PERCENT; + } - function MAX_FEE_DISCOUNT() external pure returns (uint256) { - return JBConstants.MAX_FEE_DISCOUNT; - } + function MAX_FEE_DISCOUNT() external pure returns (uint256) { + return JBConstants.MAX_FEE_DISCOUNT; + } } diff --git a/test/jb_eth_erc20_project_payer/add_to_balance.test.js b/test/jb_eth_erc20_project_payer/add_to_balance.test.js index 645cf79c8..333f2ce32 100644 --- a/test/jb_eth_erc20_project_payer/add_to_balance.test.js +++ b/test/jb_eth_erc20_project_payer/add_to_balance.test.js @@ -9,7 +9,7 @@ import jbTerminal from '../../artifacts/contracts/abstract/JBPayoutRedemptionPay import ierc20 from '../../artifacts/@openzeppelin/contracts/token/ERC20/ERC20.sol/ERC20.json'; import errors from '../helpers/errors.json'; -describe('JBETHERC20ProjectPayer::addToBalanceOf(...)', function () { +describe('JBGasTokenERC20ProjectPayer::addToBalanceOf(...)', function () { const INITIAL_PROJECT_ID = 1; const INITIAL_BENEFICIARY = ethers.Wallet.createRandom().address; const INITIAL_PREFER_CLAIMED_TOKENS = false; @@ -30,7 +30,7 @@ describe('JBETHERC20ProjectPayer::addToBalanceOf(...)', function () { let jbTokensFactory = await ethers.getContractFactory('JBTokens'); let jbTokens = await jbTokensFactory.deploy(); - ethToken = await jbTokens.ETH(); + ethToken = await JBTokens.GAS_TOKEN(); }); async function setup() { @@ -40,7 +40,7 @@ describe('JBETHERC20ProjectPayer::addToBalanceOf(...)', function () { let mockJbTerminal = await deployMockContract(deployer, jbTerminal.abi); let mockToken = await smock.fake(ierc20.abi); - let jbProjectPayerFactory = await ethers.getContractFactory('JBETHERC20ProjectPayer'); + let jbProjectPayerFactory = await ethers.getContractFactory('JBGasTokenERC20ProjectPayer'); let jbProjectPayer = await jbProjectPayerFactory .connect(deployer) .deploy(mockJbDirectory.address); diff --git a/test/jb_eth_erc20_project_payer/pay.test.js b/test/jb_eth_erc20_project_payer/pay.test.js index 0fb0c6d14..ace5c99f0 100644 --- a/test/jb_eth_erc20_project_payer/pay.test.js +++ b/test/jb_eth_erc20_project_payer/pay.test.js @@ -9,7 +9,7 @@ import jbTerminal from '../../artifacts/contracts/abstract/JBPayoutRedemptionPay import ierc20 from '../../artifacts/@openzeppelin/contracts/token/ERC20/ERC20.sol/ERC20.json'; import errors from '../helpers/errors.json'; -describe('JBETHERC20ProjectPayer::pay(...)', function () { +describe('JBGasTokenERC20ProjectPayer::pay(...)', function () { const INITIAL_PROJECT_ID = 1; const INITIAL_BENEFICIARY = ethers.Wallet.createRandom().address; const INITIAL_PREFER_CLAIMED_TOKENS = false; @@ -30,7 +30,7 @@ describe('JBETHERC20ProjectPayer::pay(...)', function () { let jbTokensFactory = await ethers.getContractFactory('JBTokens'); let jbTokens = await jbTokensFactory.deploy(); - ethToken = await jbTokens.ETH(); + ethToken = await JBTokens.GAS_TOKEN(); }); async function setup() { @@ -40,7 +40,7 @@ describe('JBETHERC20ProjectPayer::pay(...)', function () { let mockJbTerminal = await deployMockContract(deployer, jbTerminal.abi); let mockToken = await smock.fake(ierc20.abi); - let jbProjectPayerFactory = await ethers.getContractFactory('JBETHERC20ProjectPayer'); + let jbProjectPayerFactory = await ethers.getContractFactory('JBGasTokenERC20ProjectPayer'); let jbProjectPayer = await jbProjectPayerFactory .connect(deployer) .deploy(mockJbDirectory.address); diff --git a/test/jb_eth_erc20_project_payer/set_default_values.test.js b/test/jb_eth_erc20_project_payer/set_default_values.test.js index 719428187..81480fd9b 100644 --- a/test/jb_eth_erc20_project_payer/set_default_values.test.js +++ b/test/jb_eth_erc20_project_payer/set_default_values.test.js @@ -5,7 +5,7 @@ import { deployMockContract } from '@ethereum-waffle/mock-contract'; import jbDirectory from '../../artifacts/contracts/JBDirectory.sol/JBDirectory.json'; -describe('JBETHERC20ProjectPayer::setDefaultValues(...)', function () { +describe('JBGasTokenERC20ProjectPayer::setDefaultValues(...)', function () { const INITIAL_PROJECT_ID = 1; const INITIAL_BENEFICIARY = ethers.Wallet.createRandom().address; const INITIAL_PREFER_CLAIMED_TOKENS = false; @@ -24,7 +24,7 @@ describe('JBETHERC20ProjectPayer::setDefaultValues(...)', function () { let mockJbDirectory = await deployMockContract(deployer, jbDirectory.abi); - let jbProjectPayerFactory = await ethers.getContractFactory('JBETHERC20ProjectPayer'); + let jbProjectPayerFactory = await ethers.getContractFactory('JBGasTokenERC20ProjectPayer'); let jbProjectPayer = await jbProjectPayerFactory .connect(deployer) .deploy(mockJbDirectory.address); diff --git a/test/jb_eth_erc20_project_payer_deployer/add_to_balance.test.js b/test/jb_eth_erc20_project_payer_deployer/add_to_balance.test.js index 96240295e..341fb1eb5 100644 --- a/test/jb_eth_erc20_project_payer_deployer/add_to_balance.test.js +++ b/test/jb_eth_erc20_project_payer_deployer/add_to_balance.test.js @@ -9,7 +9,7 @@ import jbTerminal from '../../artifacts/contracts/abstract/JBPayoutRedemptionPay import ierc20 from '../../artifacts/@openzeppelin/contracts/token/ERC20/ERC20.sol/ERC20.json'; import errors from '../helpers/errors.json'; -describe('JBETHERC20ProjectPayer via Proxy::addToBalanceOf(...)', function () { +describe('JBGasTokenERC20ProjectPayer via Proxy::addToBalanceOf(...)', function () { const INITIAL_PROJECT_ID = 1; const INITIAL_BENEFICIARY = ethers.Wallet.createRandom().address; const INITIAL_PREFER_CLAIMED_TOKENS = false; @@ -30,7 +30,7 @@ describe('JBETHERC20ProjectPayer via Proxy::addToBalanceOf(...)', function () { let jbTokensFactory = await ethers.getContractFactory('JBTokens'); let jbTokens = await jbTokensFactory.deploy(); - ethToken = await jbTokens.ETH(); + ethToken = await JBTokens.GAS_TOKEN(); }); async function setup() { @@ -41,13 +41,13 @@ describe('JBETHERC20ProjectPayer via Proxy::addToBalanceOf(...)', function () { let mockToken = await smock.fake(ierc20.abi); let jbProjectPayerDeployerFactory = await ethers.getContractFactory( - 'JBETHERC20ProjectPayerDeployer', + 'JBGasTokenERC20ProjectPayerDeployer', ); let jbProjectPayerDeployer = await jbProjectPayerDeployerFactory.deploy( mockJbDirectory.address, ); - let jbProjectPayerFactory = await ethers.getContractFactory('JBETHERC20ProjectPayer'); + let jbProjectPayerFactory = await ethers.getContractFactory('JBGasTokenERC20ProjectPayer'); let jbProjectPayer = jbProjectPayerFactory.attach( await jbProjectPayerDeployer.callStatic.deployProjectPayer( INITIAL_PROJECT_ID, diff --git a/test/jb_eth_erc20_project_payer_deployer/deploy_project_payer.test.js b/test/jb_eth_erc20_project_payer_deployer/deploy_project_payer.test.js index 8d646e277..867dba003 100644 --- a/test/jb_eth_erc20_project_payer_deployer/deploy_project_payer.test.js +++ b/test/jb_eth_erc20_project_payer_deployer/deploy_project_payer.test.js @@ -19,13 +19,13 @@ describe('JBProjectPayerDeployer::deployProjectPayer(...)', function () { const mockJbDirectory = await deployMockContract(deployer, jbDirectory.abi); let jbProjectPayerDeployerFactory = await ethers.getContractFactory( - 'JBETHERC20ProjectPayerDeployer', + 'JBGasTokenERC20ProjectPayerDeployer', ); let jbProjectPayerDeployer = await jbProjectPayerDeployerFactory.deploy( mockJbDirectory.address, ); - let jbProjectPayerFactory = await ethers.getContractFactory('JBETHERC20ProjectPayer'); + let jbProjectPayerFactory = await ethers.getContractFactory('JBGasTokenERC20ProjectPayer'); let jbProjectPayer = jbProjectPayerFactory.attach( await jbProjectPayerDeployer.callStatic.deployProjectPayer( INITIAL_PROJECT_ID, diff --git a/test/jb_eth_erc20_project_payer_deployer/pay.test.js b/test/jb_eth_erc20_project_payer_deployer/pay.test.js index dc6117c6e..8232d8482 100644 --- a/test/jb_eth_erc20_project_payer_deployer/pay.test.js +++ b/test/jb_eth_erc20_project_payer_deployer/pay.test.js @@ -9,7 +9,7 @@ import jbTerminal from '../../artifacts/contracts/abstract/JBPayoutRedemptionPay import ierc20 from '../../artifacts/@openzeppelin/contracts/token/ERC20/ERC20.sol/ERC20.json'; import errors from '../helpers/errors.json'; -describe('JBETHERC20ProjectPayer via Proxy::pay(...)', function () { +describe('JBGasTokenERC20ProjectPayer via Proxy::pay(...)', function () { const INITIAL_PROJECT_ID = 1; const INITIAL_BENEFICIARY = ethers.Wallet.createRandom().address; const INITIAL_PREFER_CLAIMED_TOKENS = false; @@ -30,7 +30,7 @@ describe('JBETHERC20ProjectPayer via Proxy::pay(...)', function () { let jbTokensFactory = await ethers.getContractFactory('JBTokens'); let jbTokens = await jbTokensFactory.deploy(); - ethToken = await jbTokens.ETH(); + ethToken = await JBTokens.GAS_TOKEN(); }); async function setup() { @@ -41,13 +41,13 @@ describe('JBETHERC20ProjectPayer via Proxy::pay(...)', function () { let mockToken = await smock.fake(ierc20.abi); let jbProjectPayerDeployerFactory = await ethers.getContractFactory( - 'JBETHERC20ProjectPayerDeployer', + 'JBGasTokenERC20ProjectPayerDeployer', ); let jbProjectPayerDeployer = await jbProjectPayerDeployerFactory.deploy( mockJbDirectory.address, ); - let jbProjectPayerFactory = await ethers.getContractFactory('JBETHERC20ProjectPayer'); + let jbProjectPayerFactory = await ethers.getContractFactory('JBGasTokenERC20ProjectPayer'); let jbProjectPayer = jbProjectPayerFactory.attach( await jbProjectPayerDeployer.callStatic.deployProjectPayer( INITIAL_PROJECT_ID, diff --git a/test/jb_eth_erc20_project_payer_deployer/set_default_values.test.js b/test/jb_eth_erc20_project_payer_deployer/set_default_values.test.js index 8766df012..bc10ee880 100644 --- a/test/jb_eth_erc20_project_payer_deployer/set_default_values.test.js +++ b/test/jb_eth_erc20_project_payer_deployer/set_default_values.test.js @@ -5,7 +5,7 @@ import { deployMockContract } from '@ethereum-waffle/mock-contract'; import jbDirectory from '../../artifacts/contracts/JBDirectory.sol/JBDirectory.json'; -describe('JBETHERC20ProjectPayer via Proxy::setDefaultValues(...)', function () { +describe('JBGasTokenERC20ProjectPayer via Proxy::setDefaultValues(...)', function () { const INITIAL_PROJECT_ID = 1; const INITIAL_BENEFICIARY = ethers.Wallet.createRandom().address; const INITIAL_PREFER_CLAIMED_TOKENS = false; @@ -25,13 +25,13 @@ describe('JBETHERC20ProjectPayer via Proxy::setDefaultValues(...)', function () let mockJbDirectory = await deployMockContract(deployer, jbDirectory.abi); let jbProjectPayerDeployerFactory = await ethers.getContractFactory( - 'JBETHERC20ProjectPayerDeployer', + 'JBGasTokenERC20ProjectPayerDeployer', ); let jbProjectPayerDeployer = await jbProjectPayerDeployerFactory.deploy( mockJbDirectory.address, ); - let jbProjectPayerFactory = await ethers.getContractFactory('JBETHERC20ProjectPayer'); + let jbProjectPayerFactory = await ethers.getContractFactory('JBGasTokenERC20ProjectPayer'); let jbProjectPayer = jbProjectPayerFactory.attach( await jbProjectPayerDeployer.callStatic.deployProjectPayer( INITIAL_PROJECT_ID, diff --git a/test/jb_eth_erc20_splits_payer/add_to_balance.test.js b/test/jb_eth_erc20_splits_payer/add_to_balance.test.js index 79c5385a9..5ff64ff22 100644 --- a/test/jb_eth_erc20_splits_payer/add_to_balance.test.js +++ b/test/jb_eth_erc20_splits_payer/add_to_balance.test.js @@ -12,7 +12,7 @@ import jbDirectory from '../../artifacts/contracts/JBDirectory.sol/JBDirectory.j import jbSplitsStore from '../../artifacts/contracts/JBSplitsStore.sol/JBSplitsStore.json'; import jbTerminal from '../../artifacts/contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol/JBPayoutRedemptionPaymentTerminal.json'; -describe('JBETHERC20SplitsPayer::addToBalanceOf(...)', function () { +describe('JBGasTokenERC20SplitsPayer::addToBalanceOf(...)', function () { const DEFAULT_PROJECT_ID = 2; const DEFAULT_SPLITS_PROJECT_ID = 3; const DEFAULT_SPLITS_DOMAIN = 1; @@ -39,7 +39,7 @@ describe('JBETHERC20SplitsPayer::addToBalanceOf(...)', function () { let jbTokensFactory = await ethers.getContractFactory('JBTokens'); let jbTokens = await jbTokensFactory.deploy(); - ethToken = await jbTokens.ETH(); + ethToken = await JBTokens.GAS_TOKEN(); let jbConstantsFactory = await ethers.getContractFactory('JBConstants'); let jbConstants = await jbConstantsFactory.deploy(); @@ -69,7 +69,7 @@ describe('JBETHERC20SplitsPayer::addToBalanceOf(...)', function () { await mockJbSplitsStore.mock.directory.returns(mockJbDirectory.address); let jbSplitsPayerFactory = await ethers.getContractFactory( - 'contracts/JBETHERC20SplitsPayer.sol:JBETHERC20SplitsPayer', + 'contracts/JBGasTokenERC20SplitsPayer.sol:JBGasTokenERC20SplitsPayer', ); let jbSplitsPayer = await jbSplitsPayerFactory .connect(deployer) @@ -77,18 +77,18 @@ describe('JBETHERC20SplitsPayer::addToBalanceOf(...)', function () { await jbSplitsPayer .connect(deployer) - ['initialize(uint256,uint256,uint256,uint256,address,bool,string,bytes,bool,address)']( - DEFAULT_SPLITS_PROJECT_ID, - DEFAULT_SPLITS_DOMAIN, - DEFAULT_SPLITS_GROUP, - DEFAULT_PROJECT_ID, - DEFAULT_BENEFICIARY, - DEFAULT_PREFER_CLAIMED_TOKENS, - DEFAULT_MEMO, - DEFAULT_METADATA, - PREFER_ADD_TO_BALANCE, - owner.address, - ); + ['initialize(uint256,uint256,uint256,uint256,address,bool,string,bytes,bool,address)']( + DEFAULT_SPLITS_PROJECT_ID, + DEFAULT_SPLITS_DOMAIN, + DEFAULT_SPLITS_GROUP, + DEFAULT_PROJECT_ID, + DEFAULT_BENEFICIARY, + DEFAULT_PREFER_CLAIMED_TOKENS, + DEFAULT_MEMO, + DEFAULT_METADATA, + PREFER_ADD_TO_BALANCE, + owner.address, + ); return { beneficiaryOne, @@ -740,18 +740,18 @@ describe('JBETHERC20SplitsPayer::addToBalanceOf(...)', function () { await jbSplitsPayerWithoutDefaultBeneficiary .connect(deployer) - ['initialize(uint256,uint256,uint256,uint256,address,bool,string,bytes,bool,address)']( - DEFAULT_SPLITS_PROJECT_ID, - DEFAULT_SPLITS_DOMAIN, - DEFAULT_SPLITS_GROUP, - DEFAULT_PROJECT_ID, - ethers.constants.AddressZero, - DEFAULT_PREFER_CLAIMED_TOKENS, - DEFAULT_MEMO, - DEFAULT_METADATA, - PREFER_ADD_TO_BALANCE, - owner.address, - ); + ['initialize(uint256,uint256,uint256,uint256,address,bool,string,bytes,bool,address)']( + DEFAULT_SPLITS_PROJECT_ID, + DEFAULT_SPLITS_DOMAIN, + DEFAULT_SPLITS_GROUP, + DEFAULT_PROJECT_ID, + ethers.constants.AddressZero, + DEFAULT_PREFER_CLAIMED_TOKENS, + DEFAULT_MEMO, + DEFAULT_METADATA, + PREFER_ADD_TO_BALANCE, + owner.address, + ); await mockJbSplitsStore.mock.splitsOf .withArgs(DEFAULT_SPLITS_PROJECT_ID, DEFAULT_SPLITS_DOMAIN, DEFAULT_SPLITS_GROUP) @@ -926,18 +926,18 @@ describe('JBETHERC20SplitsPayer::addToBalanceOf(...)', function () { await jbSplitsPayer .connect(deployer) - ['initialize(uint256,uint256,uint256,uint256,address,bool,string,bytes,bool,address)']( - DEFAULT_SPLITS_PROJECT_ID, - DEFAULT_SPLITS_DOMAIN, - DEFAULT_SPLITS_GROUP, - DEFAULT_PROJECT_ID, - beneficiaryThree.address, - DEFAULT_PREFER_CLAIMED_TOKENS, - DEFAULT_MEMO, - DEFAULT_METADATA, - PREFER_ADD_TO_BALANCE, - owner.address, - ); + ['initialize(uint256,uint256,uint256,uint256,address,bool,string,bytes,bool,address)']( + DEFAULT_SPLITS_PROJECT_ID, + DEFAULT_SPLITS_DOMAIN, + DEFAULT_SPLITS_GROUP, + DEFAULT_PROJECT_ID, + beneficiaryThree.address, + DEFAULT_PREFER_CLAIMED_TOKENS, + DEFAULT_MEMO, + DEFAULT_METADATA, + PREFER_ADD_TO_BALANCE, + owner.address, + ); // 50% to beneficiaries let splits = makeSplits({ @@ -1005,18 +1005,18 @@ describe('JBETHERC20SplitsPayer::addToBalanceOf(...)', function () { await jbSplitsPayer .connect(deployer) - ['initialize(uint256,uint256,uint256,uint256,address,bool,string,bytes,bool,address)']( - DEFAULT_SPLITS_PROJECT_ID, - DEFAULT_SPLITS_DOMAIN, - DEFAULT_SPLITS_GROUP, - DEFAULT_PROJECT_ID, - beneficiaryThree.address, - DEFAULT_PREFER_CLAIMED_TOKENS, - DEFAULT_MEMO, - DEFAULT_METADATA, - PREFER_ADD_TO_BALANCE, - owner.address, - ); + ['initialize(uint256,uint256,uint256,uint256,address,bool,string,bytes,bool,address)']( + DEFAULT_SPLITS_PROJECT_ID, + DEFAULT_SPLITS_DOMAIN, + DEFAULT_SPLITS_GROUP, + DEFAULT_PROJECT_ID, + beneficiaryThree.address, + DEFAULT_PREFER_CLAIMED_TOKENS, + DEFAULT_MEMO, + DEFAULT_METADATA, + PREFER_ADD_TO_BALANCE, + owner.address, + ); // 50% to beneficiaries let splits = makeSplits({ @@ -1089,18 +1089,18 @@ describe('JBETHERC20SplitsPayer::addToBalanceOf(...)', function () { await jbSplitsPayer .connect(deployer) - ['initialize(uint256,uint256,uint256,uint256,address,bool,string,bytes,bool,address)']( - DEFAULT_SPLITS_PROJECT_ID, - DEFAULT_SPLITS_DOMAIN, - DEFAULT_SPLITS_GROUP, - DEFAULT_PROJECT_ID, - ethers.constants.AddressZero, - DEFAULT_PREFER_CLAIMED_TOKENS, - DEFAULT_MEMO, - DEFAULT_METADATA, - PREFER_ADD_TO_BALANCE, - owner.address, - ); + ['initialize(uint256,uint256,uint256,uint256,address,bool,string,bytes,bool,address)']( + DEFAULT_SPLITS_PROJECT_ID, + DEFAULT_SPLITS_DOMAIN, + DEFAULT_SPLITS_GROUP, + DEFAULT_PROJECT_ID, + ethers.constants.AddressZero, + DEFAULT_PREFER_CLAIMED_TOKENS, + DEFAULT_MEMO, + DEFAULT_METADATA, + PREFER_ADD_TO_BALANCE, + owner.address, + ); // 50% to beneficiaries let splits = makeSplits({ @@ -1167,18 +1167,18 @@ describe('JBETHERC20SplitsPayer::addToBalanceOf(...)', function () { await jbSplitsPayer .connect(deployer) - ['initialize(uint256,uint256,uint256,uint256,address,bool,string,bytes,bool,address)']( - DEFAULT_SPLITS_PROJECT_ID, - DEFAULT_SPLITS_DOMAIN, - DEFAULT_SPLITS_GROUP, - DEFAULT_PROJECT_ID, - ethers.constants.AddressZero, - DEFAULT_PREFER_CLAIMED_TOKENS, - DEFAULT_MEMO, - DEFAULT_METADATA, - PREFER_ADD_TO_BALANCE, - owner.address, - ); + ['initialize(uint256,uint256,uint256,uint256,address,bool,string,bytes,bool,address)']( + DEFAULT_SPLITS_PROJECT_ID, + DEFAULT_SPLITS_DOMAIN, + DEFAULT_SPLITS_GROUP, + DEFAULT_PROJECT_ID, + ethers.constants.AddressZero, + DEFAULT_PREFER_CLAIMED_TOKENS, + DEFAULT_MEMO, + DEFAULT_METADATA, + PREFER_ADD_TO_BALANCE, + owner.address, + ); // 50% to beneficiaries let splits = makeSplits({ diff --git a/test/jb_eth_erc20_splits_payer/pay.test.js b/test/jb_eth_erc20_splits_payer/pay.test.js index f1b195d55..e7a00cc02 100644 --- a/test/jb_eth_erc20_splits_payer/pay.test.js +++ b/test/jb_eth_erc20_splits_payer/pay.test.js @@ -12,7 +12,7 @@ import jbDirectory from '../../artifacts/contracts/JBDirectory.sol/JBDirectory.j import jbSplitsStore from '../../artifacts/contracts/JBSplitsStore.sol/JBSplitsStore.json'; import jbTerminal from '../../artifacts/contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol/JBPayoutRedemptionPaymentTerminal.json'; -describe('JBETHERC20SplitsPayer::pay(...)', function () { +describe('JBGasTokenERC20SplitsPayer::pay(...)', function () { const DEFAULT_PROJECT_ID = 2; const DEFAULT_SPLITS_PROJECT_ID = 3; const DEFAULT_SPLITS_DOMAIN = 1; @@ -39,7 +39,7 @@ describe('JBETHERC20SplitsPayer::pay(...)', function () { let jbTokensFactory = await ethers.getContractFactory('JBTokens'); let jbTokens = await jbTokensFactory.deploy(); - ethToken = await jbTokens.ETH(); + ethToken = await JBTokens.GAS_TOKEN(); let jbConstantsFactory = await ethers.getContractFactory('JBConstants'); let jbConstants = await jbConstantsFactory.deploy(); @@ -69,7 +69,7 @@ describe('JBETHERC20SplitsPayer::pay(...)', function () { await mockJbSplitsStore.mock.directory.returns(mockJbDirectory.address); let jbSplitsPayerFactory = await ethers.getContractFactory( - 'contracts/JBETHERC20SplitsPayer.sol:JBETHERC20SplitsPayer', + 'contracts/JBGasTokenERC20SplitsPayer.sol:JBGasTokenERC20SplitsPayer', ); let jbSplitsPayer = await jbSplitsPayerFactory .connect(deployer) @@ -77,18 +77,18 @@ describe('JBETHERC20SplitsPayer::pay(...)', function () { await jbSplitsPayer .connect(deployer) - ['initialize(uint256,uint256,uint256,uint256,address,bool,string,bytes,bool,address)']( - DEFAULT_SPLITS_PROJECT_ID, - DEFAULT_SPLITS_DOMAIN, - DEFAULT_SPLITS_GROUP, - DEFAULT_PROJECT_ID, - DEFAULT_BENEFICIARY, - DEFAULT_PREFER_CLAIMED_TOKENS, - DEFAULT_MEMO, - DEFAULT_METADATA, - PREFER_ADD_TO_BALANCE, - owner.address, - ); + ['initialize(uint256,uint256,uint256,uint256,address,bool,string,bytes,bool,address)']( + DEFAULT_SPLITS_PROJECT_ID, + DEFAULT_SPLITS_DOMAIN, + DEFAULT_SPLITS_GROUP, + DEFAULT_PROJECT_ID, + DEFAULT_BENEFICIARY, + DEFAULT_PREFER_CLAIMED_TOKENS, + DEFAULT_MEMO, + DEFAULT_METADATA, + PREFER_ADD_TO_BALANCE, + owner.address, + ); return { beneficiaryOne, @@ -774,18 +774,18 @@ describe('JBETHERC20SplitsPayer::pay(...)', function () { await jbSplitsPayerWithoutDefaultBeneficiary .connect(deployer) - ['initialize(uint256,uint256,uint256,uint256,address,bool,string,bytes,bool,address)']( - DEFAULT_SPLITS_PROJECT_ID, - DEFAULT_SPLITS_DOMAIN, - DEFAULT_SPLITS_GROUP, - DEFAULT_PROJECT_ID, - ethers.constants.AddressZero, - DEFAULT_PREFER_CLAIMED_TOKENS, - DEFAULT_MEMO, - DEFAULT_METADATA, - PREFER_ADD_TO_BALANCE, - owner.address, - ); + ['initialize(uint256,uint256,uint256,uint256,address,bool,string,bytes,bool,address)']( + DEFAULT_SPLITS_PROJECT_ID, + DEFAULT_SPLITS_DOMAIN, + DEFAULT_SPLITS_GROUP, + DEFAULT_PROJECT_ID, + ethers.constants.AddressZero, + DEFAULT_PREFER_CLAIMED_TOKENS, + DEFAULT_MEMO, + DEFAULT_METADATA, + PREFER_ADD_TO_BALANCE, + owner.address, + ); await mockJbSplitsStore.mock.splitsOf .withArgs(DEFAULT_SPLITS_PROJECT_ID, DEFAULT_SPLITS_DOMAIN, DEFAULT_SPLITS_GROUP) @@ -1194,18 +1194,18 @@ describe('JBETHERC20SplitsPayer::pay(...)', function () { await jbSplitsPayerWithoutDefaultBeneficiary .connect(deployer) - ['initialize(uint256,uint256,uint256,uint256,address,bool,string,bytes,bool,address)']( - DEFAULT_SPLITS_PROJECT_ID, - DEFAULT_SPLITS_DOMAIN, - DEFAULT_SPLITS_GROUP, - DEFAULT_PROJECT_ID, - ethers.constants.AddressZero, - DEFAULT_PREFER_CLAIMED_TOKENS, - DEFAULT_MEMO, - DEFAULT_METADATA, - PREFER_ADD_TO_BALANCE, - owner.address, - ); + ['initialize(uint256,uint256,uint256,uint256,address,bool,string,bytes,bool,address)']( + DEFAULT_SPLITS_PROJECT_ID, + DEFAULT_SPLITS_DOMAIN, + DEFAULT_SPLITS_GROUP, + DEFAULT_PROJECT_ID, + ethers.constants.AddressZero, + DEFAULT_PREFER_CLAIMED_TOKENS, + DEFAULT_MEMO, + DEFAULT_METADATA, + PREFER_ADD_TO_BALANCE, + owner.address, + ); await mockJbSplitsStore.mock.splitsOf .withArgs(DEFAULT_SPLITS_PROJECT_ID, DEFAULT_SPLITS_DOMAIN, DEFAULT_SPLITS_GROUP) @@ -1285,18 +1285,18 @@ describe('JBETHERC20SplitsPayer::pay(...)', function () { await jbSplitsPayerWithoutDefaultBeneficiary .connect(deployer) - ['initialize(uint256,uint256,uint256,uint256,address,bool,string,bytes,bool,address)']( - DEFAULT_SPLITS_PROJECT_ID, - DEFAULT_SPLITS_DOMAIN, - DEFAULT_SPLITS_GROUP, - DEFAULT_PROJECT_ID, - ethers.constants.AddressZero, - DEFAULT_PREFER_CLAIMED_TOKENS, - DEFAULT_MEMO, - DEFAULT_METADATA, - PREFER_ADD_TO_BALANCE, - owner.address, - ); + ['initialize(uint256,uint256,uint256,uint256,address,bool,string,bytes,bool,address)']( + DEFAULT_SPLITS_PROJECT_ID, + DEFAULT_SPLITS_DOMAIN, + DEFAULT_SPLITS_GROUP, + DEFAULT_PROJECT_ID, + ethers.constants.AddressZero, + DEFAULT_PREFER_CLAIMED_TOKENS, + DEFAULT_MEMO, + DEFAULT_METADATA, + PREFER_ADD_TO_BALANCE, + owner.address, + ); // Transfer to splitsPayer mockToken.balanceOf.returnsAtCall(0, 0); diff --git a/test/jb_eth_erc20_splits_payer/receive.test.js b/test/jb_eth_erc20_splits_payer/receive.test.js index 6b9ec3f00..8e1e658af 100644 --- a/test/jb_eth_erc20_splits_payer/receive.test.js +++ b/test/jb_eth_erc20_splits_payer/receive.test.js @@ -11,7 +11,7 @@ import jbDirectory from '../../artifacts/contracts/JBDirectory.sol/JBDirectory.j import jbSplitsStore from '../../artifacts/contracts/JBSplitsStore.sol/JBSplitsStore.json'; import jbTerminal from '../../artifacts/contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol/JBPayoutRedemptionPaymentTerminal.json'; -describe('JBETHERC20SplitsPayer::receive()', function () { +describe('JBGasTokenERC20SplitsPayer::receive()', function () { const DEFAULT_PROJECT_ID = 2; const DEFAULT_SPLITS_PROJECT_ID = 3; const DEFAULT_SPLITS_DOMAIN = 1; @@ -36,7 +36,7 @@ describe('JBETHERC20SplitsPayer::receive()', function () { let jbTokensFactory = await ethers.getContractFactory('JBTokens'); let jbTokens = await jbTokensFactory.deploy(); - ethToken = await jbTokens.ETH(); + ethToken = await JBTokens.GAS_TOKEN(); let jbConstantsFactory = await ethers.getContractFactory('JBConstants'); let jbConstants = await jbConstantsFactory.deploy(); @@ -66,7 +66,7 @@ describe('JBETHERC20SplitsPayer::receive()', function () { await mockJbSplitsStore.mock.directory.returns(mockJbDirectory.address); let jbSplitsPayerFactory = await ethers.getContractFactory( - 'contracts/JBETHERC20SplitsPayer.sol:JBETHERC20SplitsPayer', + 'contracts/JBGasTokenERC20SplitsPayer.sol:JBGasTokenERC20SplitsPayer', ); let jbSplitsPayer = await jbSplitsPayerFactory .connect(deployer) @@ -74,18 +74,18 @@ describe('JBETHERC20SplitsPayer::receive()', function () { await jbSplitsPayer .connect(deployer) - ['initialize(uint256,uint256,uint256,uint256,address,bool,string,bytes,bool,address)']( - DEFAULT_SPLITS_PROJECT_ID, - DEFAULT_SPLITS_DOMAIN, - DEFAULT_SPLITS_GROUP, - DEFAULT_PROJECT_ID, - DEFAULT_BENEFICIARY, - DEFAULT_PREFER_CLAIMED_TOKENS, - DEFAULT_MEMO, - DEFAULT_METADATA, - PREFER_ADD_TO_BALANCE, - owner.address, - ); + ['initialize(uint256,uint256,uint256,uint256,address,bool,string,bytes,bool,address)']( + DEFAULT_SPLITS_PROJECT_ID, + DEFAULT_SPLITS_DOMAIN, + DEFAULT_SPLITS_GROUP, + DEFAULT_PROJECT_ID, + DEFAULT_BENEFICIARY, + DEFAULT_PREFER_CLAIMED_TOKENS, + DEFAULT_MEMO, + DEFAULT_METADATA, + PREFER_ADD_TO_BALANCE, + owner.address, + ); return { beneficiaryOne, @@ -299,18 +299,18 @@ describe('JBETHERC20SplitsPayer::receive()', function () { await jbSplitsPayerWithoutDefaultBeneficiary .connect(deployer) - ['initialize(uint256,uint256,uint256,uint256,address,bool,string,bytes,bool,address)']( - DEFAULT_SPLITS_PROJECT_ID, - DEFAULT_SPLITS_DOMAIN, - DEFAULT_SPLITS_GROUP, - DEFAULT_PROJECT_ID, - ethers.constants.AddressZero, - DEFAULT_PREFER_CLAIMED_TOKENS, - DEFAULT_MEMO, - DEFAULT_METADATA, - PREFER_ADD_TO_BALANCE, - owner.address, - ); + ['initialize(uint256,uint256,uint256,uint256,address,bool,string,bytes,bool,address)']( + DEFAULT_SPLITS_PROJECT_ID, + DEFAULT_SPLITS_DOMAIN, + DEFAULT_SPLITS_GROUP, + DEFAULT_PROJECT_ID, + ethers.constants.AddressZero, + DEFAULT_PREFER_CLAIMED_TOKENS, + DEFAULT_MEMO, + DEFAULT_METADATA, + PREFER_ADD_TO_BALANCE, + owner.address, + ); let splits = makeSplits(); @@ -399,18 +399,18 @@ describe('JBETHERC20SplitsPayer::receive()', function () { await jbSplitsPayerPreferAddToBalance .connect(deployer) - ['initialize(uint256,uint256,uint256,uint256,address,bool,string,bytes,bool,address)']( - DEFAULT_SPLITS_PROJECT_ID, - DEFAULT_SPLITS_DOMAIN, - DEFAULT_SPLITS_GROUP, - DEFAULT_PROJECT_ID, - DEFAULT_BENEFICIARY, - DEFAULT_PREFER_CLAIMED_TOKENS, - DEFAULT_MEMO, - DEFAULT_METADATA, - true, - owner.address, - ); + ['initialize(uint256,uint256,uint256,uint256,address,bool,string,bytes,bool,address)']( + DEFAULT_SPLITS_PROJECT_ID, + DEFAULT_SPLITS_DOMAIN, + DEFAULT_SPLITS_GROUP, + DEFAULT_PROJECT_ID, + DEFAULT_BENEFICIARY, + DEFAULT_PREFER_CLAIMED_TOKENS, + DEFAULT_MEMO, + DEFAULT_METADATA, + true, + owner.address, + ); // 50% to beneficiaries let splits = makeSplits({ @@ -467,18 +467,18 @@ describe('JBETHERC20SplitsPayer::receive()', function () { await jbSplitsPayer .connect(deployer) - ['initialize(uint256,uint256,uint256,uint256,address,bool,string,bytes,bool,address)']( - DEFAULT_SPLITS_PROJECT_ID, - DEFAULT_SPLITS_DOMAIN, - DEFAULT_SPLITS_GROUP, - 0, - beneficiaryThree.address, - DEFAULT_PREFER_CLAIMED_TOKENS, - DEFAULT_MEMO, - DEFAULT_METADATA, - true, - owner.address, - ); + ['initialize(uint256,uint256,uint256,uint256,address,bool,string,bytes,bool,address)']( + DEFAULT_SPLITS_PROJECT_ID, + DEFAULT_SPLITS_DOMAIN, + DEFAULT_SPLITS_GROUP, + 0, + beneficiaryThree.address, + DEFAULT_PREFER_CLAIMED_TOKENS, + DEFAULT_MEMO, + DEFAULT_METADATA, + true, + owner.address, + ); // 50% to beneficiaries let splits = makeSplits({ @@ -529,18 +529,18 @@ describe('JBETHERC20SplitsPayer::receive()', function () { await jbSplitsPayer .connect(deployer) - ['initialize(uint256,uint256,uint256,uint256,address,bool,string,bytes,bool,address)']( - DEFAULT_SPLITS_PROJECT_ID, - DEFAULT_SPLITS_DOMAIN, - DEFAULT_SPLITS_GROUP, - 0, - ethers.constants.AddressZero, - DEFAULT_PREFER_CLAIMED_TOKENS, - DEFAULT_MEMO, - DEFAULT_METADATA, - true, - owner.address, - ); + ['initialize(uint256,uint256,uint256,uint256,address,bool,string,bytes,bool,address)']( + DEFAULT_SPLITS_PROJECT_ID, + DEFAULT_SPLITS_DOMAIN, + DEFAULT_SPLITS_GROUP, + 0, + ethers.constants.AddressZero, + DEFAULT_PREFER_CLAIMED_TOKENS, + DEFAULT_MEMO, + DEFAULT_METADATA, + true, + owner.address, + ); // 50% to beneficiaries let splits = makeSplits({ diff --git a/test/jb_eth_erc20_splits_payer/set_default_splits.test.js b/test/jb_eth_erc20_splits_payer/set_default_splits.test.js index 6f3be10fb..ce2f2ea36 100644 --- a/test/jb_eth_erc20_splits_payer/set_default_splits.test.js +++ b/test/jb_eth_erc20_splits_payer/set_default_splits.test.js @@ -7,7 +7,7 @@ import { makeSplits } from '../helpers/utils'; import jbDirectory from '../../artifacts/contracts/JBDirectory.sol/JBDirectory.json'; import jbSplitsStore from '../../artifacts/contracts/JBSplitsStore.sol/JBSplitsStore.json'; -describe('JBETHERC20SplitsPayer::setDefaultSplits()', function () { +describe('JBGasTokenERC20SplitsPayer::setDefaultSplits()', function () { const DEFAULT_PROJECT_ID = 2; const DEFAULT_SPLITS_PROJECT_ID = 3; const DEFAULT_SPLITS_DOMAIN = 1; @@ -32,7 +32,7 @@ describe('JBETHERC20SplitsPayer::setDefaultSplits()', function () { await mockJbSplitsStore.mock.directory.returns(mockJbDirectory.address); let jbSplitsPayerFactory = await ethers.getContractFactory( - 'contracts/JBETHERC20SplitsPayer.sol:JBETHERC20SplitsPayer', + 'contracts/JBGasTokenERC20SplitsPayer.sol:JBGasTokenERC20SplitsPayer', ); let jbSplitsPayer = await jbSplitsPayerFactory .connect(deployer) @@ -40,18 +40,18 @@ describe('JBETHERC20SplitsPayer::setDefaultSplits()', function () { await jbSplitsPayer .connect(deployer) - ['initialize(uint256,uint256,uint256,uint256,address,bool,string,bytes,bool,address)']( - DEFAULT_SPLITS_PROJECT_ID, - DEFAULT_SPLITS_DOMAIN, - DEFAULT_SPLITS_GROUP, - DEFAULT_PROJECT_ID, - DEFAULT_BENEFICIARY, - DEFAULT_PREFER_CLAIMED_TOKENS, - DEFAULT_MEMO, - DEFAULT_METADATA, - PREFER_ADD_TO_BALANCE, - owner.address, - ); + ['initialize(uint256,uint256,uint256,uint256,address,bool,string,bytes,bool,address)']( + DEFAULT_SPLITS_PROJECT_ID, + DEFAULT_SPLITS_DOMAIN, + DEFAULT_SPLITS_GROUP, + DEFAULT_PROJECT_ID, + DEFAULT_BENEFICIARY, + DEFAULT_PREFER_CLAIMED_TOKENS, + DEFAULT_MEMO, + DEFAULT_METADATA, + PREFER_ADD_TO_BALANCE, + owner.address, + ); return { deployer, diff --git a/test/jb_eth_erc20_splits_payer/set_default_splits_reference.test.js b/test/jb_eth_erc20_splits_payer/set_default_splits_reference.test.js index c2ad8c593..e9109b092 100644 --- a/test/jb_eth_erc20_splits_payer/set_default_splits_reference.test.js +++ b/test/jb_eth_erc20_splits_payer/set_default_splits_reference.test.js @@ -6,7 +6,7 @@ import { deployMockContract } from '@ethereum-waffle/mock-contract'; import jbDirectory from '../../artifacts/contracts/JBDirectory.sol/JBDirectory.json'; import jbSplitsStore from '../../artifacts/contracts/JBSplitsStore.sol/JBSplitsStore.json'; -describe('JBETHERC20SplitsPayer::setDefaultSplitsReference()', function () { +describe('JBGasTokenERC20SplitsPayer::setDefaultSplitsReference()', function () { const DEFAULT_PROJECT_ID = 2; const DEFAULT_SPLITS_PROJECT_ID = 3; const DEFAULT_SPLITS_DOMAIN = 1; @@ -30,7 +30,7 @@ describe('JBETHERC20SplitsPayer::setDefaultSplitsReference()', function () { await mockJbSplitsStore.mock.directory.returns(mockJbDirectory.address); let jbSplitsPayerFactory = await ethers.getContractFactory( - 'contracts/JBETHERC20SplitsPayer.sol:JBETHERC20SplitsPayer', + 'contracts/JBGasTokenERC20SplitsPayer.sol:JBGasTokenERC20SplitsPayer', ); let jbSplitsPayer = await jbSplitsPayerFactory .connect(deployer) @@ -38,18 +38,18 @@ describe('JBETHERC20SplitsPayer::setDefaultSplitsReference()', function () { await jbSplitsPayer .connect(deployer) - ['initialize(uint256,uint256,uint256,uint256,address,bool,string,bytes,bool,address)']( - DEFAULT_SPLITS_PROJECT_ID, - DEFAULT_SPLITS_DOMAIN, - DEFAULT_SPLITS_GROUP, - DEFAULT_PROJECT_ID, - DEFAULT_BENEFICIARY, - DEFAULT_PREFER_CLAIMED_TOKENS, - DEFAULT_MEMO, - DEFAULT_METADATA, - PREFER_ADD_TO_BALANCE, - owner.address, - ); + ['initialize(uint256,uint256,uint256,uint256,address,bool,string,bytes,bool,address)']( + DEFAULT_SPLITS_PROJECT_ID, + DEFAULT_SPLITS_DOMAIN, + DEFAULT_SPLITS_GROUP, + DEFAULT_PROJECT_ID, + DEFAULT_BENEFICIARY, + DEFAULT_PREFER_CLAIMED_TOKENS, + DEFAULT_MEMO, + DEFAULT_METADATA, + PREFER_ADD_TO_BALANCE, + owner.address, + ); return { deployer, diff --git a/test/jb_eth_erc20_splits_payer_deployer/add_to_balance.test.js b/test/jb_eth_erc20_splits_payer_deployer/add_to_balance.test.js index c778dde03..a50bcc233 100644 --- a/test/jb_eth_erc20_splits_payer_deployer/add_to_balance.test.js +++ b/test/jb_eth_erc20_splits_payer_deployer/add_to_balance.test.js @@ -12,7 +12,7 @@ import jbDirectory from '../../artifacts/contracts/JBDirectory.sol/JBDirectory.j import jbSplitsStore from '../../artifacts/contracts/JBSplitsStore.sol/JBSplitsStore.json'; import jbTerminal from '../../artifacts/contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol/JBPayoutRedemptionPaymentTerminal.json'; -describe('JBETHERC20SplitsPayer with Proxy::addToBalanceOf(...)', function () { +describe('JBGasTokenERC20SplitsPayer with Proxy::addToBalanceOf(...)', function () { const DEFAULT_PROJECT_ID = 2; const DEFAULT_SPLITS_PROJECT_ID = 3; const DEFAULT_SPLITS_DOMAIN = 1; @@ -39,7 +39,7 @@ describe('JBETHERC20SplitsPayer with Proxy::addToBalanceOf(...)', function () { let jbTokensFactory = await ethers.getContractFactory('JBTokens'); let jbTokens = await jbTokensFactory.deploy(); - ethToken = await jbTokens.ETH(); + ethToken = await JBTokens.GAS_TOKEN(); let jbConstantsFactory = await ethers.getContractFactory('JBConstants'); let jbConstants = await jbConstantsFactory.deploy(); @@ -69,14 +69,14 @@ describe('JBETHERC20SplitsPayer with Proxy::addToBalanceOf(...)', function () { await mockJbSplitsStore.mock.directory.returns(mockJbDirectory.address); let jbSplitsPayerDeployerFactory = await ethers.getContractFactory( - 'contracts/JBETHERC20SplitsPayerDeployer.sol:JBETHERC20SplitsPayerDeployer', + 'contracts/JBGasTokenERC20SplitsPayerDeployer.sol:JBGasTokenERC20SplitsPayerDeployer', ); let jbSplitsPayerDeployer = await jbSplitsPayerDeployerFactory.deploy( mockJbSplitsStore.address, ); - let jbSplitsPayerFactory = await ethers.getContractFactory('JBETHERC20SplitsPayer'); + let jbSplitsPayerFactory = await ethers.getContractFactory('JBGasTokenERC20SplitsPayer'); let jbSplitsPayer = jbSplitsPayerFactory.attach( await jbSplitsPayerDeployer.callStatic.deploySplitsPayer( diff --git a/test/jb_eth_erc20_splits_payer_deployer/deploy_split_payer.test.js b/test/jb_eth_erc20_splits_payer_deployer/deploy_split_payer.test.js index 6d2d2041c..3aff68136 100644 --- a/test/jb_eth_erc20_splits_payer_deployer/deploy_split_payer.test.js +++ b/test/jb_eth_erc20_splits_payer_deployer/deploy_split_payer.test.js @@ -25,7 +25,7 @@ describe('JBSplitsPayerDeployer::deploySplitsPayer(...)', function () { await mockJbSplitsStore.mock.directory.returns(mockJbDirectory.address); let jbSplitsPayerDeployerFactory = await ethers.getContractFactory( - 'contracts/JBETHERC20SplitsPayerDeployer.sol:JBETHERC20SplitsPayerDeployer', + 'contracts/JBGasTokenERC20SplitsPayerDeployer.sol:JBGasTokenERC20SplitsPayerDeployer', ); let jbSplitsPayerDeployer = await jbSplitsPayerDeployerFactory.deploy( diff --git a/test/jb_eth_erc20_splits_payer_deployer/deploy_split_payer_with_splits.test.js b/test/jb_eth_erc20_splits_payer_deployer/deploy_split_payer_with_splits.test.js index 64db59511..c77d2e972 100644 --- a/test/jb_eth_erc20_splits_payer_deployer/deploy_split_payer_with_splits.test.js +++ b/test/jb_eth_erc20_splits_payer_deployer/deploy_split_payer_with_splits.test.js @@ -26,7 +26,7 @@ describe('JBSplitsPayerDeployer::deploySplitsPayerWithSplits(...)', function () await mockJbSplitsStore.mock.directory.returns(mockJbDirectory.address); let jbSplitsPayerDeployerFactory = await ethers.getContractFactory( - 'contracts/JBETHERC20SplitsPayerDeployer.sol:JBETHERC20SplitsPayerDeployer', + 'contracts/JBGasTokenERC20SplitsPayerDeployer.sol:JBGasTokenERC20SplitsPayerDeployer', ); let jbSplitsPayerDeployer = await jbSplitsPayerDeployerFactory.deploy( diff --git a/test/jb_eth_erc20_splits_payer_deployer/pay.test.js b/test/jb_eth_erc20_splits_payer_deployer/pay.test.js index 3304fed2a..0365996c4 100644 --- a/test/jb_eth_erc20_splits_payer_deployer/pay.test.js +++ b/test/jb_eth_erc20_splits_payer_deployer/pay.test.js @@ -12,7 +12,7 @@ import jbDirectory from '../../artifacts/contracts/JBDirectory.sol/JBDirectory.j import jbSplitsStore from '../../artifacts/contracts/JBSplitsStore.sol/JBSplitsStore.json'; import jbTerminal from '../../artifacts/contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol/JBPayoutRedemptionPaymentTerminal.json'; -describe('JBETHERC20SplitsPayer with Proxy::pay(...)', function () { +describe('JBGasTokenERC20SplitsPayer with Proxy::pay(...)', function () { const DEFAULT_PROJECT_ID = 2; const DEFAULT_SPLITS_PROJECT_ID = 3; const DEFAULT_SPLITS_DOMAIN = 1; @@ -39,7 +39,7 @@ describe('JBETHERC20SplitsPayer with Proxy::pay(...)', function () { let jbTokensFactory = await ethers.getContractFactory('JBTokens'); let jbTokens = await jbTokensFactory.deploy(); - ethToken = await jbTokens.ETH(); + ethToken = await JBTokens.GAS_TOKEN(); let jbConstantsFactory = await ethers.getContractFactory('JBConstants'); let jbConstants = await jbConstantsFactory.deploy(); @@ -69,14 +69,14 @@ describe('JBETHERC20SplitsPayer with Proxy::pay(...)', function () { await mockJbSplitsStore.mock.directory.returns(mockJbDirectory.address); let jbSplitsPayerDeployerFactory = await ethers.getContractFactory( - 'contracts/JBETHERC20SplitsPayerDeployer.sol:JBETHERC20SplitsPayerDeployer', + 'contracts/JBGasTokenERC20SplitsPayerDeployer.sol:JBGasTokenERC20SplitsPayerDeployer', ); let jbSplitsPayerDeployer = await jbSplitsPayerDeployerFactory.deploy( mockJbSplitsStore.address, ); - let jbSplitsPayerFactory = await ethers.getContractFactory('JBETHERC20SplitsPayer'); + let jbSplitsPayerFactory = await ethers.getContractFactory('JBGasTokenERC20SplitsPayer'); let jbSplitsPayer = jbSplitsPayerFactory.attach( await jbSplitsPayerDeployer.callStatic.deploySplitsPayer( diff --git a/test/jb_eth_erc20_splits_payer_deployer/receive.test.js b/test/jb_eth_erc20_splits_payer_deployer/receive.test.js index 329377518..2252a9cb5 100644 --- a/test/jb_eth_erc20_splits_payer_deployer/receive.test.js +++ b/test/jb_eth_erc20_splits_payer_deployer/receive.test.js @@ -11,7 +11,7 @@ import jbDirectory from '../../artifacts/contracts/JBDirectory.sol/JBDirectory.j import jbSplitsStore from '../../artifacts/contracts/JBSplitsStore.sol/JBSplitsStore.json'; import jbTerminal from '../../artifacts/contracts/abstract/JBPayoutRedemptionPaymentTerminal.sol/JBPayoutRedemptionPaymentTerminal.json'; -describe('JBETHERC20SplitsPayer with Proxy::receive()', function () { +describe('JBGasTokenERC20SplitsPayer with Proxy::receive()', function () { const DEFAULT_PROJECT_ID = 2; const DEFAULT_SPLITS_PROJECT_ID = 3; const DEFAULT_SPLITS_DOMAIN = 1; @@ -36,7 +36,7 @@ describe('JBETHERC20SplitsPayer with Proxy::receive()', function () { let jbTokensFactory = await ethers.getContractFactory('JBTokens'); let jbTokens = await jbTokensFactory.deploy(); - ethToken = await jbTokens.ETH(); + ethToken = await JBTokens.GAS_TOKEN(); let jbConstantsFactory = await ethers.getContractFactory('JBConstants'); let jbConstants = await jbConstantsFactory.deploy(); @@ -66,14 +66,14 @@ describe('JBETHERC20SplitsPayer with Proxy::receive()', function () { await mockJbSplitsStore.mock.directory.returns(mockJbDirectory.address); let jbSplitsPayerDeployerFactory = await ethers.getContractFactory( - 'contracts/JBETHERC20SplitsPayerDeployer.sol:JBETHERC20SplitsPayerDeployer', + 'contracts/JBGasTokenERC20SplitsPayerDeployer.sol:JBGasTokenERC20SplitsPayerDeployer', ); let jbSplitsPayerDeployer = await jbSplitsPayerDeployerFactory.deploy( mockJbSplitsStore.address, ); - let jbSplitsPayerFactory = await ethers.getContractFactory('JBETHERC20SplitsPayer'); + let jbSplitsPayerFactory = await ethers.getContractFactory('JBGasTokenERC20SplitsPayer'); let jbSplitsPayer = jbSplitsPayerFactory.attach( await jbSplitsPayerDeployer.callStatic.deploySplitsPayer( diff --git a/test/jb_payment_terminal/add_to_balance_of.test.js b/test/jb_payment_terminal/add_to_balance_of.test.js index ed16947e5..a2a0f0073 100644 --- a/test/jb_payment_terminal/add_to_balance_of.test.js +++ b/test/jb_payment_terminal/add_to_balance_of.test.js @@ -37,7 +37,7 @@ describe('JBPayoutRedemptionPaymentTerminal::addToBalanceOf(...)', function () { const jbCurrenciesFactory = await ethers.getContractFactory('JBCurrencies'); const jbCurrencies = await jbCurrenciesFactory.deploy(); - CURRENCY_ETH = await jbCurrencies.ETH(); + CURRENCY_ETH = await JBCurrencies.GAS_CURRENCY(); const jbConstantsFactory = await ethers.getContractFactory('JBConstants'); const jbConstants = await jbConstantsFactory.deploy(); diff --git a/test/jb_payment_terminal/current_eth_overflow_of.test.js b/test/jb_payment_terminal/current_eth_overflow_of.test.js index 7ba0181ae..b911baf2d 100644 --- a/test/jb_payment_terminal/current_eth_overflow_of.test.js +++ b/test/jb_payment_terminal/current_eth_overflow_of.test.js @@ -20,7 +20,7 @@ describe('JBPayoutRedemptionPaymentTerminal::currentEthOverflowOf(...)', functio before(async function () { const jbCurrenciesFactory = await ethers.getContractFactory('JBCurrencies'); const jbCurrencies = await jbCurrenciesFactory.deploy(); - CURRENCY_ETH = await jbCurrencies.ETH(); + CURRENCY_ETH = await JBCurrencies.GAS_CURRENCY(); CURRENCY_USD = await jbCurrencies.USD(); }); diff --git a/test/jb_payment_terminal/distribute_payouts_of.test.js b/test/jb_payment_terminal/distribute_payouts_of.test.js index 110f8dd04..35489dfc1 100644 --- a/test/jb_payment_terminal/distribute_payouts_of.test.js +++ b/test/jb_payment_terminal/distribute_payouts_of.test.js @@ -107,7 +107,7 @@ describe('JBPayoutRedemptionPaymentTerminal::distributePayoutsOf(...)', function const jbCurrenciesFactory = await ethers.getContractFactory('JBCurrencies'); const jbCurrencies = await jbCurrenciesFactory.deploy(); - const CURRENCY_ETH = await jbCurrencies.ETH(); + const CURRENCY_ETH = await JBCurrencies.GAS_CURRENCY(); const CURRENCY_USD = await jbCurrencies.USD(); let jbEthTerminalFactory = await ethers.getContractFactory( diff --git a/test/jb_payment_terminal/migrate.test.js b/test/jb_payment_terminal/migrate.test.js index 77f882602..189544028 100644 --- a/test/jb_payment_terminal/migrate.test.js +++ b/test/jb_payment_terminal/migrate.test.js @@ -54,11 +54,11 @@ describe('JBPayoutRedemptionPaymentTerminal::migrate(...)', function () { const jbCurrenciesFactory = await ethers.getContractFactory('JBCurrencies'); const jbCurrencies = await jbCurrenciesFactory.deploy(); - const CURRENCY_ETH = await jbCurrencies.ETH(); + const CURRENCY_ETH = await JBCurrencies.GAS_CURRENCY(); const jbTokensFactory = await ethers.getContractFactory('JBTokens'); const jbTokens = await jbTokensFactory.deploy(); - const TOKEN_ETH = await jbTokens.ETH(); + const TOKEN_ETH = await JBTokens.GAS_TOKEN(); const NON_ETH_TOKEN = mockJbToken.address; const SPLITS_GROUP = 1; diff --git a/test/jb_payment_terminal/redeem_tokens_of.test.js b/test/jb_payment_terminal/redeem_tokens_of.test.js index 9aa8a0a8a..5e4eddf63 100644 --- a/test/jb_payment_terminal/redeem_tokens_of.test.js +++ b/test/jb_payment_terminal/redeem_tokens_of.test.js @@ -61,7 +61,7 @@ describe('JBPayoutRedemptionPaymentTerminal::redeemTokensOf(...)', function () { const jbCurrenciesFactory = await ethers.getContractFactory('JBCurrencies'); const jbCurrencies = await jbCurrenciesFactory.deploy(); - CURRENCY_ETH = await jbCurrencies.ETH(); + CURRENCY_ETH = await JBCurrencies.GAS_CURRENCY(); const jbTerminalFactory = await ethers.getContractFactory( 'contracts/JBETHPaymentTerminal.sol:JBETHPaymentTerminal', @@ -146,7 +146,7 @@ describe('JBPayoutRedemptionPaymentTerminal::redeemTokensOf(...)', function () { .returns( fundingCycle, /* reclaimAmount */ RECLAIM_AMOUNT, - /* delegateAllocation */ [], + /* delegateAllocation */[], ADJUSTED_MEMO, ); @@ -207,7 +207,7 @@ describe('JBPayoutRedemptionPaymentTerminal::redeemTokensOf(...)', function () { .returns( fundingCycle, /* reclaimAmount */ RECLAIM_AMOUNT, - /* delegateAllocation */ [], + /* delegateAllocation */[], ADJUSTED_MEMO, ); @@ -278,7 +278,7 @@ describe('JBPayoutRedemptionPaymentTerminal::redeemTokensOf(...)', function () { .returns( fundingCycle, /* reclaimAmount */ redeemedAmount, - /* delegateAllocations */ [ + /* delegateAllocations */[ { delegate: mockJbRedemptionDelegate.address, amount: delegateAmount }, ], ADJUSTED_MEMO, @@ -412,7 +412,7 @@ describe('JBPayoutRedemptionPaymentTerminal::redeemTokensOf(...)', function () { .returns( fundingCycle, /* reclaimAmount */ redeemedAmount, - /* delegate */ [ + /* delegate */[ { delegate: mockJbRedemptionDelegate.address, amount: delegate1Amount }, { delegate: mockJbRedemptionDelegate2.address, amount: delegate2Amount }, ], @@ -569,7 +569,7 @@ describe('JBPayoutRedemptionPaymentTerminal::redeemTokensOf(...)', function () { // Keep it simple and let 1 token exchange for 1 wei await mockJBPaymentTerminalStore.mock.recordRedemptionFor .withArgs(holder.address, PROJECT_ID, /* tokenCount */ AMOUNT, MEMO, METADATA) - .returns(fundingCycle, /* reclaimAmount */ 0, /* delegateAllocation */ [], ADJUSTED_MEMO); // Set reclaimAmount to 0 + .returns(fundingCycle, /* reclaimAmount */ 0, /* delegateAllocation */[], ADJUSTED_MEMO); // Set reclaimAmount to 0 await setBalance(jbEthPaymentTerminal.address, AMOUNT); @@ -672,7 +672,7 @@ describe('JBPayoutRedemptionPaymentTerminal::redeemTokensOf(...)', function () { // Keep it simple and let 1 token exchange for 1 wei await mockJBPaymentTerminalStore.mock.recordRedemptionFor .withArgs(holder.address, PROJECT_ID, /* tokenCount */ AMOUNT, MEMO, METADATA) - .returns(fundingCycle, /* reclaimAmount */ 0, /* delegateAllocation */ [], ADJUSTED_MEMO); // Set reclaimAmount to 0 + .returns(fundingCycle, /* reclaimAmount */ 0, /* delegateAllocation */[], ADJUSTED_MEMO); // Set reclaimAmount to 0 await expect( jbEthPaymentTerminal diff --git a/test/jb_payment_terminal/set_fee.test.js b/test/jb_payment_terminal/set_fee.test.js index 227e2b9bd..7474a1998 100644 --- a/test/jb_payment_terminal/set_fee.test.js +++ b/test/jb_payment_terminal/set_fee.test.js @@ -35,7 +35,7 @@ describe('JBPayoutRedemptionPaymentTerminal::setFee(...)', function () { const jbCurrenciesFactory = await ethers.getContractFactory('JBCurrencies'); const jbCurrencies = await jbCurrenciesFactory.deploy(); - const CURRENCY_ETH = await jbCurrencies.ETH(); + const CURRENCY_ETH = await JBCurrencies.GAS_CURRENCY(); let jbTerminalFactory = await ethers.getContractFactory( 'contracts/JBETHPaymentTerminal.sol:JBETHPaymentTerminal', diff --git a/test/jb_payment_terminal/set_fee_gauge.test.js b/test/jb_payment_terminal/set_fee_gauge.test.js index cf8ff79e6..8b0f9c38c 100644 --- a/test/jb_payment_terminal/set_fee_gauge.test.js +++ b/test/jb_payment_terminal/set_fee_gauge.test.js @@ -35,7 +35,7 @@ describe('JBPayoutRedemptionPaymentTerminal::setFeeGauge(...)', function () { const jbCurrenciesFactory = await ethers.getContractFactory('JBCurrencies'); const jbCurrencies = await jbCurrenciesFactory.deploy(); - const CURRENCY_ETH = await jbCurrencies.ETH(); + const CURRENCY_ETH = await JBCurrencies.GAS_CURRENCY(); let jbTerminalFactory = await ethers.getContractFactory( 'contracts/JBETHPaymentTerminal.sol:JBETHPaymentTerminal', diff --git a/test/jb_payment_terminal/set_feeless_terminal.test.js b/test/jb_payment_terminal/set_feeless_terminal.test.js index 3905e7c93..bc2b87a83 100644 --- a/test/jb_payment_terminal/set_feeless_terminal.test.js +++ b/test/jb_payment_terminal/set_feeless_terminal.test.js @@ -35,7 +35,7 @@ describe('JBPayoutRedemptionPaymentTerminal::setFeelessAddress(...)', function ( const jbCurrenciesFactory = await ethers.getContractFactory('JBCurrencies'); const jbCurrencies = await jbCurrenciesFactory.deploy(); - const CURRENCY_ETH = await jbCurrencies.ETH(); + const CURRENCY_ETH = await JBCurrencies.GAS_CURRENCY(); let jbTerminalFactory = await ethers.getContractFactory( 'contracts/JBETHPaymentTerminal.sol:JBETHPaymentTerminal', diff --git a/test/jb_payment_terminal/use_allowance_of.test.js b/test/jb_payment_terminal/use_allowance_of.test.js index a517bfc5e..af89b5409 100644 --- a/test/jb_payment_terminal/use_allowance_of.test.js +++ b/test/jb_payment_terminal/use_allowance_of.test.js @@ -68,7 +68,7 @@ describe('JBPayoutRedemptionPaymentTerminal::useAllowanceOf(...)', function () { const jbCurrenciesFactory = await ethers.getContractFactory('JBCurrencies'); const jbCurrencies = await jbCurrenciesFactory.deploy(); - const CURRENCY_ETH = await jbCurrencies.ETH(); + const CURRENCY_ETH = await JBCurrencies.GAS_CURRENCY(); const jbTerminalFactory = await ethers.getContractFactory( 'contracts/JBETHPaymentTerminal.sol:JBETHPaymentTerminal', @@ -340,7 +340,7 @@ describe('JBPayoutRedemptionPaymentTerminal::useAllowanceOf(...)', function () { /* memo */ '', '0x', ) - .returns(fundingCycle, 0, /* delegateAllocation */ [], ''); + .returns(fundingCycle, 0, /* delegateAllocation */[], ''); await mockJbDirectory.mock.primaryTerminalOf .withArgs(1, ETH_ADDRESS) @@ -431,7 +431,7 @@ describe('JBPayoutRedemptionPaymentTerminal::useAllowanceOf(...)', function () { /* memo */ '', '0x', ) - .returns(fundingCycle, 0, /* delegateAllocation */ [], ''); + .returns(fundingCycle, 0, /* delegateAllocation */[], ''); await mockJbDirectory.mock.primaryTerminalOf .withArgs(1, ETH_ADDRESS) @@ -518,7 +518,7 @@ describe('JBPayoutRedemptionPaymentTerminal::useAllowanceOf(...)', function () { /* memo */ '', '0x', ) - .returns(fundingCycle, 0, /* delegateAllocation */ [], ''); + .returns(fundingCycle, 0, /* delegateAllocation */[], ''); await mockJbDirectory.mock.primaryTerminalOf .withArgs(1, ETH_ADDRESS) @@ -605,7 +605,7 @@ describe('JBPayoutRedemptionPaymentTerminal::useAllowanceOf(...)', function () { /* memo */ '', '0x', ) - .returns(fundingCycle, 0, /* delegateAllocation */ [], ''); + .returns(fundingCycle, 0, /* delegateAllocation */[], ''); await mockJbDirectory.mock.primaryTerminalOf .withArgs(1, ETH_ADDRESS) @@ -700,7 +700,7 @@ describe('JBPayoutRedemptionPaymentTerminal::useAllowanceOf(...)', function () { /* memo */ '', '0x', ) - .returns(newFundingCycle, 0, /* delegateAllocation */ [], ''); + .returns(newFundingCycle, 0, /* delegateAllocation */[], ''); await mockJbDirectory.mock.primaryTerminalOf .withArgs(1, ETH_ADDRESS) @@ -808,7 +808,7 @@ describe('JBPayoutRedemptionPaymentTerminal::useAllowanceOf(...)', function () { /* memo */ '', '0x', ) - .returns(newFundingCycle, 0, /* delegateAllocation */ [], ''); + .returns(newFundingCycle, 0, /* delegateAllocation */[], ''); await mockJbDirectory.mock.primaryTerminalOf .withArgs(1, ETH_ADDRESS) @@ -920,7 +920,7 @@ describe('JBPayoutRedemptionPaymentTerminal::useAllowanceOf(...)', function () { /* memo */ '', '0x', ) - .returns(newFundingCycle, 0, /* delegateAllocation */ [], ''); + .returns(newFundingCycle, 0, /* delegateAllocation */[], ''); await mockJbDirectory.mock.primaryTerminalOf .withArgs(1, ETH_ADDRESS) diff --git a/test/jb_payment_terminal/view.test.js b/test/jb_payment_terminal/view.test.js index e70b6586d..a4773e687 100644 --- a/test/jb_payment_terminal/view.test.js +++ b/test/jb_payment_terminal/view.test.js @@ -21,7 +21,7 @@ describe('JBPayoutRedemptionPaymentTerminal::getters', function () { before(async function () { const jbCurrenciesFactory = await ethers.getContractFactory('JBCurrencies'); const jbCurrencies = await jbCurrenciesFactory.deploy(); - CURRENCY_ETH = await jbCurrencies.ETH(); + CURRENCY_ETH = await JBCurrencies.GAS_CURRENCY(); }); async function setup() { diff --git a/test/jb_payment_terminal_3_1/add_to_balance_of.test.js b/test/jb_payment_terminal_3_1/add_to_balance_of.test.js index 4cdac442f..d9bc9c79b 100644 --- a/test/jb_payment_terminal_3_1/add_to_balance_of.test.js +++ b/test/jb_payment_terminal_3_1/add_to_balance_of.test.js @@ -37,7 +37,7 @@ describe('JBPayoutRedemptionPaymentTerminal3_1::addToBalanceOf(...)', function ( const jbCurrenciesFactory = await ethers.getContractFactory('JBCurrencies'); const jbCurrencies = await jbCurrenciesFactory.deploy(); - CURRENCY_ETH = await jbCurrencies.ETH(); + CURRENCY_ETH = await JBCurrencies.GAS_CURRENCY(); const jbConstantsFactory = await ethers.getContractFactory('JBConstants'); const jbConstants = await jbConstantsFactory.deploy(); @@ -243,15 +243,15 @@ describe('JBPayoutRedemptionPaymentTerminal3_1::addToBalanceOf(...)', function ( expect( await jbEthPaymentTerminal .connect(caller) - ['addToBalanceOf(uint256,uint256,address,bool,string,bytes)']( - PROJECT_ID, - AMOUNT, - ETH_ADDRESS, - true, - MEMO, - METADATA, - { value: AMOUNT }, - ), + ['addToBalanceOf(uint256,uint256,address,bool,string,bytes)']( + PROJECT_ID, + AMOUNT, + ETH_ADDRESS, + true, + MEMO, + METADATA, + { value: AMOUNT }, + ), ) .to.emit(jbEthPaymentTerminal, 'AddToBalance') .withArgs(PROJECT_ID, AMOUNT, feeNetAmount, MEMO, METADATA, caller.address) @@ -313,15 +313,15 @@ describe('JBPayoutRedemptionPaymentTerminal3_1::addToBalanceOf(...)', function ( expect( await jbEthPaymentTerminal .connect(caller) - ['addToBalanceOf(uint256,uint256,address,bool,string,bytes)']( - PROJECT_ID, - AMOUNT, - ETH_ADDRESS, - false, - MEMO, - METADATA, - { value: AMOUNT }, - ), + ['addToBalanceOf(uint256,uint256,address,bool,string,bytes)']( + PROJECT_ID, + AMOUNT, + ETH_ADDRESS, + false, + MEMO, + METADATA, + { value: AMOUNT }, + ), ) .to.emit(jbEthPaymentTerminal, 'AddToBalance') .withArgs(PROJECT_ID, AMOUNT, 0 /*refunded fee*/, MEMO, METADATA, caller.address) @@ -341,14 +341,14 @@ describe('JBPayoutRedemptionPaymentTerminal3_1::addToBalanceOf(...)', function ( await jbEthPaymentTerminal .connect(caller) - ['addToBalanceOf(uint256,uint256,address,string,bytes)']( - PROJECT_ID, - AMOUNT + 1, - ETH_ADDRESS, - MEMO, - METADATA, - { value: AMOUNT }, - ); + ['addToBalanceOf(uint256,uint256,address,string,bytes)']( + PROJECT_ID, + AMOUNT + 1, + ETH_ADDRESS, + MEMO, + METADATA, + { value: AMOUNT }, + ); }); it('Should work with non-eth terminal if no value is sent', async function () { @@ -448,15 +448,15 @@ describe('JBPayoutRedemptionPaymentTerminal3_1::addToBalanceOf(...)', function ( await expect( await jbEthPaymentTerminal .connect(caller) - ['addToBalanceOf(uint256,uint256,address,bool,string,bytes)']( - PROJECT_ID, - 1, - ETH_ADDRESS, - true, - MEMO, - METADATA, - { value: 1 }, - ), + ['addToBalanceOf(uint256,uint256,address,bool,string,bytes)']( + PROJECT_ID, + 1, + ETH_ADDRESS, + true, + MEMO, + METADATA, + { value: 1 }, + ), ) .to.emit(jbEthPaymentTerminal, 'AddToBalance') .withArgs(PROJECT_ID, 1, 1, MEMO, METADATA, caller.address) @@ -548,17 +548,17 @@ describe('JBPayoutRedemptionPaymentTerminal3_1::addToBalanceOf(...)', function ( expect( await jbEthPaymentTerminal .connect(caller) - ['addToBalanceOf(uint256,uint256,address,bool,string,bytes)']( - PROJECT_ID, - AMOUNT.sub('10'), - ETH_ADDRESS, - true, - MEMO, - METADATA, - { - value: AMOUNT.sub('10'), - }, - ), + ['addToBalanceOf(uint256,uint256,address,bool,string,bytes)']( + PROJECT_ID, + AMOUNT.sub('10'), + ETH_ADDRESS, + true, + MEMO, + METADATA, + { + value: AMOUNT.sub('10'), + }, + ), ) .to.emit(jbEthPaymentTerminal, 'AddToBalance') .withArgs( @@ -670,17 +670,17 @@ describe('JBPayoutRedemptionPaymentTerminal3_1::addToBalanceOf(...)', function ( expect( await jbEthPaymentTerminal .connect(caller) - ['addToBalanceOf(uint256,uint256,address,bool,string,bytes)']( - PROJECT_ID, - amountToAdd, - ETH_ADDRESS, - true, - MEMO, - METADATA, - { - value: amountToAdd, - }, - ), + ['addToBalanceOf(uint256,uint256,address,bool,string,bytes)']( + PROJECT_ID, + amountToAdd, + ETH_ADDRESS, + true, + MEMO, + METADATA, + { + value: amountToAdd, + }, + ), ) .to.emit(jbEthPaymentTerminal, 'AddToBalance') .withArgs(PROJECT_ID, amountToAdd, feeNetAmount, MEMO, METADATA, caller.address) @@ -752,17 +752,17 @@ describe('JBPayoutRedemptionPaymentTerminal3_1::addToBalanceOf(...)', function ( expect( await jbEthPaymentTerminal .connect(caller) - ['addToBalanceOf(uint256,uint256,address,bool,string,bytes)']( - PROJECT_ID, - AMOUNT.mul(2), - ETH_ADDRESS, - true, - MEMO, - METADATA, - { - value: AMOUNT.mul(2), - }, - ), + ['addToBalanceOf(uint256,uint256,address,bool,string,bytes)']( + PROJECT_ID, + AMOUNT.mul(2), + ETH_ADDRESS, + true, + MEMO, + METADATA, + { + value: AMOUNT.mul(2), + }, + ), ) .to.emit(jbEthPaymentTerminal, 'AddToBalance') .withArgs(PROJECT_ID, AMOUNT.mul(2), netHeldFee, MEMO, METADATA, caller.address) @@ -803,14 +803,14 @@ describe('JBPayoutRedemptionPaymentTerminal3_1::addToBalanceOf(...)', function ( await expect( jbEthPaymentTerminal .connect(caller) - ['addToBalanceOf(uint256,uint256,address,string,bytes)']( - otherProjectId, - AMOUNT, - ETH_ADDRESS, - MEMO, - METADATA, - { value: 0 }, - ), + ['addToBalanceOf(uint256,uint256,address,string,bytes)']( + otherProjectId, + AMOUNT, + ETH_ADDRESS, + MEMO, + METADATA, + { value: 0 }, + ), ).to.be.revertedWith(errors.PROJECT_TERMINAL_MISMATCH); }); }); diff --git a/test/jb_payment_terminal_3_1/current_eth_overflow_of.test.js b/test/jb_payment_terminal_3_1/current_eth_overflow_of.test.js index 66fa8a20f..9888b1fc4 100644 --- a/test/jb_payment_terminal_3_1/current_eth_overflow_of.test.js +++ b/test/jb_payment_terminal_3_1/current_eth_overflow_of.test.js @@ -20,7 +20,7 @@ describe('JBPayoutRedemptionPaymentTerminal3_1::currentEthOverflowOf(...)', func before(async function () { const jbCurrenciesFactory = await ethers.getContractFactory('JBCurrencies'); const jbCurrencies = await jbCurrenciesFactory.deploy(); - CURRENCY_ETH = await jbCurrencies.ETH(); + CURRENCY_ETH = await JBCurrencies.GAS_CURRENCY(); CURRENCY_USD = await jbCurrencies.USD(); }); diff --git a/test/jb_payment_terminal_3_1/distribute_payouts_of.test.js b/test/jb_payment_terminal_3_1/distribute_payouts_of.test.js index c57ea0c50..3521ee35c 100644 --- a/test/jb_payment_terminal_3_1/distribute_payouts_of.test.js +++ b/test/jb_payment_terminal_3_1/distribute_payouts_of.test.js @@ -107,7 +107,7 @@ describe('JBPayoutRedemptionPaymentTerminal3_1::distributePayoutsOf(...)', funct const jbCurrenciesFactory = await ethers.getContractFactory('JBCurrencies'); const jbCurrencies = await jbCurrenciesFactory.deploy(); - const CURRENCY_ETH = await jbCurrencies.ETH(); + const CURRENCY_ETH = await JBCurrencies.GAS_CURRENCY(); const CURRENCY_USD = await jbCurrencies.USD(); let jbEthTerminalFactory = await ethers.getContractFactory( @@ -156,8 +156,8 @@ describe('JBPayoutRedemptionPaymentTerminal3_1::distributePayoutsOf(...)', funct // JBDAO await mockJbDirectory.mock.isTerminalOf - .withArgs(1, jbEthPaymentTerminal.address) - .returns(true); + .withArgs(1, jbEthPaymentTerminal.address) + .returns(true); await mockJbDirectory.mock.isTerminalOf .withArgs(OTHER_PROJECT_ID, jbEthPaymentTerminal.address) @@ -182,11 +182,11 @@ describe('JBPayoutRedemptionPaymentTerminal3_1::distributePayoutsOf(...)', funct // Mock the JBAllocator supports interface check await mockJbAllocator.mock.supportsInterface.withArgs("0x01ffc9a7") - .returns(true); + .returns(true); await mockJbAllocator.mock.supportsInterface.withArgs("0x9d740bfa") - .returns(true); + .returns(true); await mockJbAllocator.mock.supportsInterface.withArgs("0xffffffff") - .returns(false); + .returns(false); await setBalance(jbEthPaymentTerminal.address, AMOUNT_DISTRIBUTED); @@ -324,8 +324,8 @@ describe('JBPayoutRedemptionPaymentTerminal3_1::distributePayoutsOf(...)', funct [ /*token*/ '0x000000000000000000000000000000000000eeee', /*amount paid*/ Math.floor( - (AMOUNT_DISTRIBUTED * split.percent) / SPLITS_TOTAL_PERCENT, - ), + (AMOUNT_DISTRIBUTED * split.percent) / SPLITS_TOTAL_PERCENT, + ), /*decimal*/ 18, CURRENCY, ], @@ -335,7 +335,7 @@ describe('JBPayoutRedemptionPaymentTerminal3_1::distributePayoutsOf(...)', funct '', ethers.utils.hexZeroPad(ethers.utils.hexlify(PROJECT_ID), 32), ) - .returns(fundingCycle, /*count*/ 0, /* delegateAllocation */ [], ''); + .returns(fundingCycle, /*count*/ 0, /* delegateAllocation */[], ''); }), ); @@ -443,8 +443,8 @@ describe('JBPayoutRedemptionPaymentTerminal3_1::distributePayoutsOf(...)', funct [ /*token*/ '0x000000000000000000000000000000000000eeee', /*amount paid*/ Math.floor( - (AMOUNT_DISTRIBUTED * split.percent) / SPLITS_TOTAL_PERCENT, - ), + (AMOUNT_DISTRIBUTED * split.percent) / SPLITS_TOTAL_PERCENT, + ), /*decimal*/ 18, CURRENCY, ], @@ -454,7 +454,7 @@ describe('JBPayoutRedemptionPaymentTerminal3_1::distributePayoutsOf(...)', funct '', ethers.utils.hexZeroPad(ethers.utils.hexlify(PROJECT_ID), 32), ) - .returns(fundingCycle, 0, /* delegateAllocation */ [], ''); + .returns(fundingCycle, 0, /* delegateAllocation */[], ''); }), ); @@ -1253,7 +1253,7 @@ describe('JBPayoutRedemptionPaymentTerminal3_1::distributePayoutsOf(...)', funct '', ethers.utils.hexZeroPad(ethers.utils.hexlify(PROJECT_ID), 32), ) - .returns(fundingCycle, 0, /* delegateAllocation */ [], ''); + .returns(fundingCycle, 0, /* delegateAllocation */[], ''); await Promise.all( splits.map(async (split) => { @@ -1263,8 +1263,8 @@ describe('JBPayoutRedemptionPaymentTerminal3_1::distributePayoutsOf(...)', funct [ /*token*/ '0x000000000000000000000000000000000000eeee', /*amount paid*/ Math.floor( - (AMOUNT_MINUS_FEES * split.percent) / SPLITS_TOTAL_PERCENT, - ), + (AMOUNT_MINUS_FEES * split.percent) / SPLITS_TOTAL_PERCENT, + ), /*decimal*/ 18, CURRENCY, ], @@ -1274,7 +1274,7 @@ describe('JBPayoutRedemptionPaymentTerminal3_1::distributePayoutsOf(...)', funct '', '0x', ) - .returns(fundingCycle, 0, /* delegateAllocation */ [], ''); + .returns(fundingCycle, 0, /* delegateAllocation */[], ''); }), ); @@ -2587,8 +2587,8 @@ describe('JBPayoutRedemptionPaymentTerminal3_1::distributePayoutsOf(...)', funct [ /*token*/ '0x000000000000000000000000000000000000eeee', /*amount paid*/ Math.floor( - (AMOUNT_DISTRIBUTED * split.percent) / SPLITS_TOTAL_PERCENT, - ), + (AMOUNT_DISTRIBUTED * split.percent) / SPLITS_TOTAL_PERCENT, + ), /*decimal*/ 18, CURRENCY, ], @@ -2598,7 +2598,7 @@ describe('JBPayoutRedemptionPaymentTerminal3_1::distributePayoutsOf(...)', funct '', ethers.utils.hexZeroPad(ethers.utils.hexlify(PROJECT_ID), 32), ) - .returns(fundingCycle, 0, /* delegateAllocation */ [], ''); + .returns(fundingCycle, 0, /* delegateAllocation */[], ''); }), ); @@ -2843,7 +2843,7 @@ describe('JBPayoutRedemptionPaymentTerminal3_1::distributePayoutsOf(...)', funct /*_distributedAmount*/ AMOUNT_DISTRIBUTED, /*_feeAmount*/ 0, /*_leftoverDistributionAmount*/ AMOUNT_DISTRIBUTED - - ((AMOUNT_DISTRIBUTED * PERCENT) / SPLITS_TOTAL_PERCENT) * splits.length, + ((AMOUNT_DISTRIBUTED * PERCENT) / SPLITS_TOTAL_PERCENT) * splits.length, METADATA, caller.address, ); @@ -2903,7 +2903,7 @@ describe('JBPayoutRedemptionPaymentTerminal3_1::distributePayoutsOf(...)', funct // '', // ethers.utils.hexZeroPad(ethers.utils.hexlify(PROJECT_ID), 32), // ) - .returns(fundingCycle, /*count*/ 0, /* delegateAllocation */ [], ''); + .returns(fundingCycle, /*count*/ 0, /* delegateAllocation */[], ''); }), ); @@ -2923,7 +2923,7 @@ describe('JBPayoutRedemptionPaymentTerminal3_1::distributePayoutsOf(...)', funct '', ethers.utils.hexZeroPad(ethers.utils.hexlify(PROJECT_ID), 32), ) - .returns(fundingCycle, /*count*/ 0, /* delegateAllocation */ [], ''); + .returns(fundingCycle, /*count*/ 0, /* delegateAllocation */[], ''); let tx = await jbEthPaymentTerminal .connect(caller) diff --git a/test/jb_payment_terminal_3_1/migrate.test.js b/test/jb_payment_terminal_3_1/migrate.test.js index ddacfb038..7601e98e1 100644 --- a/test/jb_payment_terminal_3_1/migrate.test.js +++ b/test/jb_payment_terminal_3_1/migrate.test.js @@ -54,11 +54,11 @@ describe('JBPayoutRedemptionPaymentTerminal3_1::migrate(...)', function () { const jbCurrenciesFactory = await ethers.getContractFactory('JBCurrencies'); const jbCurrencies = await jbCurrenciesFactory.deploy(); - const CURRENCY_ETH = await jbCurrencies.ETH(); + const CURRENCY_ETH = await JBCurrencies.GAS_CURRENCY(); const jbTokensFactory = await ethers.getContractFactory('JBTokens'); const jbTokens = await jbTokensFactory.deploy(); - const TOKEN_ETH = await jbTokens.ETH(); + const TOKEN_ETH = await JBTokens.GAS_TOKEN(); const NON_ETH_TOKEN = mockJbToken.address; const SPLITS_GROUP = 1; diff --git a/test/jb_payment_terminal_3_1/redeem_tokens_of.test.js b/test/jb_payment_terminal_3_1/redeem_tokens_of.test.js index cad29cd97..94502bdc5 100644 --- a/test/jb_payment_terminal_3_1/redeem_tokens_of.test.js +++ b/test/jb_payment_terminal_3_1/redeem_tokens_of.test.js @@ -61,7 +61,7 @@ describe('JBPayoutRedemptionPaymentTerminal3_1::redeemTokensOf(...)', function ( const jbCurrenciesFactory = await ethers.getContractFactory('JBCurrencies'); const jbCurrencies = await jbCurrenciesFactory.deploy(); - CURRENCY_ETH = await jbCurrencies.ETH(); + CURRENCY_ETH = await JBCurrencies.GAS_CURRENCY(); const jbTerminalFactory = await ethers.getContractFactory( 'contracts/JBETHPaymentTerminal3_1.sol:JBETHPaymentTerminal3_1', @@ -146,7 +146,7 @@ describe('JBPayoutRedemptionPaymentTerminal3_1::redeemTokensOf(...)', function ( .returns( fundingCycle, /* reclaimAmount */ RECLAIM_AMOUNT, - /* delegateAllocation */ [], + /* delegateAllocation */[], ADJUSTED_MEMO, ); @@ -207,7 +207,7 @@ describe('JBPayoutRedemptionPaymentTerminal3_1::redeemTokensOf(...)', function ( .returns( fundingCycle, /* reclaimAmount */ RECLAIM_AMOUNT, - /* delegateAllocation */ [], + /* delegateAllocation */[], ADJUSTED_MEMO, ); @@ -278,7 +278,7 @@ describe('JBPayoutRedemptionPaymentTerminal3_1::redeemTokensOf(...)', function ( .returns( fundingCycle, /* reclaimAmount */ redeemedAmount, - /* delegateAllocations */ [ + /* delegateAllocations */[ { delegate: mockJbRedemptionDelegate.address, amount: delegateAmount }, ], ADJUSTED_MEMO, @@ -412,7 +412,7 @@ describe('JBPayoutRedemptionPaymentTerminal3_1::redeemTokensOf(...)', function ( .returns( fundingCycle, /* reclaimAmount */ redeemedAmount, - /* delegate */ [ + /* delegate */[ { delegate: mockJbRedemptionDelegate.address, amount: delegate1Amount }, { delegate: mockJbRedemptionDelegate2.address, amount: delegate2Amount }, ], @@ -569,7 +569,7 @@ describe('JBPayoutRedemptionPaymentTerminal3_1::redeemTokensOf(...)', function ( // Keep it simple and let 1 token exchange for 1 wei await mockJBPaymentTerminalStore.mock.recordRedemptionFor .withArgs(holder.address, PROJECT_ID, /* tokenCount */ AMOUNT, MEMO, METADATA) - .returns(fundingCycle, /* reclaimAmount */ 0, /* delegateAllocation */ [], ADJUSTED_MEMO); // Set reclaimAmount to 0 + .returns(fundingCycle, /* reclaimAmount */ 0, /* delegateAllocation */[], ADJUSTED_MEMO); // Set reclaimAmount to 0 await setBalance(jbEthPaymentTerminal.address, AMOUNT); @@ -672,7 +672,7 @@ describe('JBPayoutRedemptionPaymentTerminal3_1::redeemTokensOf(...)', function ( // Keep it simple and let 1 token exchange for 1 wei await mockJBPaymentTerminalStore.mock.recordRedemptionFor .withArgs(holder.address, PROJECT_ID, /* tokenCount */ AMOUNT, MEMO, METADATA) - .returns(fundingCycle, /* reclaimAmount */ 0, /* delegateAllocation */ [], ADJUSTED_MEMO); // Set reclaimAmount to 0 + .returns(fundingCycle, /* reclaimAmount */ 0, /* delegateAllocation */[], ADJUSTED_MEMO); // Set reclaimAmount to 0 await expect( jbEthPaymentTerminal diff --git a/test/jb_payment_terminal_3_1/set_fee.test.js b/test/jb_payment_terminal_3_1/set_fee.test.js index a50cf6dd0..80e12f389 100644 --- a/test/jb_payment_terminal_3_1/set_fee.test.js +++ b/test/jb_payment_terminal_3_1/set_fee.test.js @@ -35,7 +35,7 @@ describe('JBPayoutRedemptionPaymentTerminal3_1::setFee(...)', function () { const jbCurrenciesFactory = await ethers.getContractFactory('JBCurrencies'); const jbCurrencies = await jbCurrenciesFactory.deploy(); - const CURRENCY_ETH = await jbCurrencies.ETH(); + const CURRENCY_ETH = await JBCurrencies.GAS_CURRENCY(); let jbTerminalFactory = await ethers.getContractFactory( 'contracts/JBETHPaymentTerminal3_1.sol:JBETHPaymentTerminal3_1', diff --git a/test/jb_payment_terminal_3_1/set_fee_gauge.test.js b/test/jb_payment_terminal_3_1/set_fee_gauge.test.js index 1936dbce8..933960387 100644 --- a/test/jb_payment_terminal_3_1/set_fee_gauge.test.js +++ b/test/jb_payment_terminal_3_1/set_fee_gauge.test.js @@ -35,7 +35,7 @@ describe('JBPayoutRedemptionPaymentTerminal3_1::setFeeGauge(...)', function () { const jbCurrenciesFactory = await ethers.getContractFactory('JBCurrencies'); const jbCurrencies = await jbCurrenciesFactory.deploy(); - const CURRENCY_ETH = await jbCurrencies.ETH(); + const CURRENCY_ETH = await JBCurrencies.GAS_CURRENCY(); let jbTerminalFactory = await ethers.getContractFactory( 'contracts/JBETHPaymentTerminal3_1.sol:JBETHPaymentTerminal3_1', diff --git a/test/jb_payment_terminal_3_1/set_feeless_terminal.test.js b/test/jb_payment_terminal_3_1/set_feeless_terminal.test.js index 7a8ece9f4..d2ec68565 100644 --- a/test/jb_payment_terminal_3_1/set_feeless_terminal.test.js +++ b/test/jb_payment_terminal_3_1/set_feeless_terminal.test.js @@ -35,7 +35,7 @@ describe('JBPayoutRedemptionPaymentTerminal3_1::setFeelessAddress(...)', functio const jbCurrenciesFactory = await ethers.getContractFactory('JBCurrencies'); const jbCurrencies = await jbCurrenciesFactory.deploy(); - const CURRENCY_ETH = await jbCurrencies.ETH(); + const CURRENCY_ETH = await JBCurrencies.GAS_CURRENCY(); let jbTerminalFactory = await ethers.getContractFactory( 'contracts/JBETHPaymentTerminal3_1.sol:JBETHPaymentTerminal3_1', diff --git a/test/jb_payment_terminal_3_1/use_allowance_of.test.js b/test/jb_payment_terminal_3_1/use_allowance_of.test.js index fb70e3d33..b879feab7 100644 --- a/test/jb_payment_terminal_3_1/use_allowance_of.test.js +++ b/test/jb_payment_terminal_3_1/use_allowance_of.test.js @@ -69,7 +69,7 @@ describe('JBPayoutRedemptionPaymentTerminal3_1::useAllowanceOf(...)', function ( const jbCurrenciesFactory = await ethers.getContractFactory('JBCurrencies'); const jbCurrencies = await jbCurrenciesFactory.deploy(); - const CURRENCY_ETH = await jbCurrencies.ETH(); + const CURRENCY_ETH = await JBCurrencies.GAS_CURRENCY(); const jbTerminalFactory = await ethers.getContractFactory( 'contracts/JBETHPaymentTerminal3_1.sol:JBETHPaymentTerminal3_1', @@ -349,7 +349,7 @@ describe('JBPayoutRedemptionPaymentTerminal3_1::useAllowanceOf(...)', function ( /* memo */ '', ethers.utils.hexZeroPad(ethers.utils.hexlify(PROJECT_ID), 32), ) - .returns(fundingCycle, 0, /* delegateAllocation */ [], ''); + .returns(fundingCycle, 0, /* delegateAllocation */[], ''); await mockJbDirectory.mock.primaryTerminalOf .withArgs(1, ETH_ADDRESS) @@ -442,7 +442,7 @@ describe('JBPayoutRedemptionPaymentTerminal3_1::useAllowanceOf(...)', function ( /* memo */ '', ethers.utils.hexZeroPad(ethers.utils.hexlify(PROJECT_ID), 32), ) - .returns(fundingCycle, 0, /* delegateAllocation */ [], ''); + .returns(fundingCycle, 0, /* delegateAllocation */[], ''); await mockJbDirectory.mock.primaryTerminalOf .withArgs(1, ETH_ADDRESS) @@ -531,7 +531,7 @@ describe('JBPayoutRedemptionPaymentTerminal3_1::useAllowanceOf(...)', function ( /* memo */ '', ethers.utils.hexZeroPad(ethers.utils.hexlify(PROJECT_ID), 32), ) - .returns(fundingCycle, 0, /* delegateAllocation */ [], ''); + .returns(fundingCycle, 0, /* delegateAllocation */[], ''); await mockJbDirectory.mock.primaryTerminalOf .withArgs(1, ETH_ADDRESS) @@ -620,7 +620,7 @@ describe('JBPayoutRedemptionPaymentTerminal3_1::useAllowanceOf(...)', function ( /* memo */ '', ethers.utils.hexZeroPad(ethers.utils.hexlify(PROJECT_ID), 32), ) - .returns(fundingCycle, 0, /* delegateAllocation */ [], ''); + .returns(fundingCycle, 0, /* delegateAllocation */[], ''); await mockJbDirectory.mock.primaryTerminalOf .withArgs(1, ETH_ADDRESS) @@ -717,7 +717,7 @@ describe('JBPayoutRedemptionPaymentTerminal3_1::useAllowanceOf(...)', function ( /* memo */ '', ethers.utils.hexZeroPad(ethers.utils.hexlify(PROJECT_ID), 32), ) - .returns(newFundingCycle, 0, /* delegateAllocation */ [], ''); + .returns(newFundingCycle, 0, /* delegateAllocation */[], ''); await mockJbDirectory.mock.primaryTerminalOf .withArgs(1, ETH_ADDRESS) @@ -826,7 +826,7 @@ describe('JBPayoutRedemptionPaymentTerminal3_1::useAllowanceOf(...)', function ( /* memo */ '', ethers.utils.hexZeroPad(ethers.utils.hexlify(PROJECT_ID), 32), ) - .returns(newFundingCycle, 0, /* delegateAllocation */ [], ''); + .returns(newFundingCycle, 0, /* delegateAllocation */[], ''); await mockJbDirectory.mock.primaryTerminalOf .withArgs(1, ETH_ADDRESS) @@ -939,7 +939,7 @@ describe('JBPayoutRedemptionPaymentTerminal3_1::useAllowanceOf(...)', function ( /* memo */ '', ethers.utils.hexZeroPad(ethers.utils.hexlify(PROJECT_ID), 32), ) - .returns(newFundingCycle, 0, /* delegateAllocation */ [], ''); + .returns(newFundingCycle, 0, /* delegateAllocation */[], ''); await mockJbDirectory.mock.primaryTerminalOf .withArgs(1, ETH_ADDRESS) diff --git a/test/jb_payment_terminal_3_1/view.test.js b/test/jb_payment_terminal_3_1/view.test.js index 73533727c..ad8d301ce 100644 --- a/test/jb_payment_terminal_3_1/view.test.js +++ b/test/jb_payment_terminal_3_1/view.test.js @@ -21,7 +21,7 @@ describe('JBPayoutRedemptionPaymentTerminal3_1::getters', function () { before(async function () { const jbCurrenciesFactory = await ethers.getContractFactory('JBCurrencies'); const jbCurrencies = await jbCurrenciesFactory.deploy(); - CURRENCY_ETH = await jbCurrencies.ETH(); + CURRENCY_ETH = await JBCurrencies.GAS_CURRENCY(); }); async function setup() { diff --git a/test/jb_payment_terminal_store/current_overflow_of.test.js b/test/jb_payment_terminal_store/current_overflow_of.test.js index 94001fdd9..a0e4a840a 100644 --- a/test/jb_payment_terminal_store/current_overflow_of.test.js +++ b/test/jb_payment_terminal_store/current_overflow_of.test.js @@ -33,7 +33,7 @@ describe('JBSingleTokenPaymentTerminalStore::currentOverflowOf(...)', function ( const jbCurrenciesFactory = await ethers.getContractFactory('JBCurrencies'); const jbCurrencies = await jbCurrenciesFactory.deploy(); - const CURRENCY_ETH = await jbCurrencies.ETH(); + const CURRENCY_ETH = await JBCurrencies.GAS_CURRENCY(); const CURRENCY_USD = await jbCurrencies.USD(); const token = ethers.Wallet.createRandom().address; diff --git a/test/jb_payment_terminal_store/current_reclaimable_overflow_of.test.js b/test/jb_payment_terminal_store/current_reclaimable_overflow_of.test.js index b53c25eee..4978ce0be 100644 --- a/test/jb_payment_terminal_store/current_reclaimable_overflow_of.test.js +++ b/test/jb_payment_terminal_store/current_reclaimable_overflow_of.test.js @@ -32,7 +32,7 @@ describe('JBSingleTokenPaymentTerminalStore::currentReclaimableOverflowOf(...)', const jbCurrenciesFactory = await ethers.getContractFactory('JBCurrencies'); const jbCurrencies = await jbCurrenciesFactory.deploy(); - const CURRENCY_ETH = await jbCurrencies.ETH(); + const CURRENCY_ETH = await JBCurrencies.GAS_CURRENCY(); const JBPaymentTerminalStoreFactory = await ethers.getContractFactory( 'contracts/JBSingleTokenPaymentTerminalStore.sol:JBSingleTokenPaymentTerminalStore', diff --git a/test/jb_payment_terminal_store/current_total_overflow_of.test.js b/test/jb_payment_terminal_store/current_total_overflow_of.test.js index 20093124f..19fa88ff9 100644 --- a/test/jb_payment_terminal_store/current_total_overflow_of.test.js +++ b/test/jb_payment_terminal_store/current_total_overflow_of.test.js @@ -37,7 +37,7 @@ describe('JBSingleTokenPaymentTerminalStore::currentTotalOverflowOf(...)', funct const jbCurrenciesFactory = await ethers.getContractFactory('JBCurrencies'); const jbCurrencies = await jbCurrenciesFactory.deploy(); - const CURRENCY_ETH = await jbCurrencies.ETH(); + const CURRENCY_ETH = await JBCurrencies.GAS_CURRENCY(); const CURRENCY_USD = await jbCurrencies.USD(); const JBPaymentTerminalStoreFactory = await ethers.getContractFactory( diff --git a/test/jb_payment_terminal_store/record_distribution_for.test.js b/test/jb_payment_terminal_store/record_distribution_for.test.js index 3d8d48a2b..1e31d6d5c 100644 --- a/test/jb_payment_terminal_store/record_distribution_for.test.js +++ b/test/jb_payment_terminal_store/record_distribution_for.test.js @@ -35,7 +35,7 @@ describe('JBSingleTokenPaymentTerminalStore::recordDistributionFor(...)', functi const jbCurrenciesFactory = await ethers.getContractFactory('JBCurrencies'); const jbCurrencies = await jbCurrenciesFactory.deploy(); - const CURRENCY_ETH = await jbCurrencies.ETH(); + const CURRENCY_ETH = await JBCurrencies.GAS_CURRENCY(); const CURRENCY_USD = await jbCurrencies.USD(); const JBPaymentTerminalStoreFactory = await ethers.getContractFactory( diff --git a/test/jb_payment_terminal_store/record_redemption_for.test.js b/test/jb_payment_terminal_store/record_redemption_for.test.js index 3db775dff..e53f3a4b1 100644 --- a/test/jb_payment_terminal_store/record_redemption_for.test.js +++ b/test/jb_payment_terminal_store/record_redemption_for.test.js @@ -40,7 +40,7 @@ describe('JBSingleTokenPaymentTerminalStore::recordRedemptionFor(...)', function const jbCurrenciesFactory = await ethers.getContractFactory('JBCurrencies'); const jbCurrencies = await jbCurrenciesFactory.deploy(); - const CURRENCY_ETH = await jbCurrencies.ETH(); + const CURRENCY_ETH = await JBCurrencies.GAS_CURRENCY(); const JBPaymentTerminalStoreFactory = await ethers.getContractFactory( 'contracts/JBSingleTokenPaymentTerminalStore.sol:JBSingleTokenPaymentTerminalStore', diff --git a/test/jb_payment_terminal_store/record_used_allowance_of.test.js b/test/jb_payment_terminal_store/record_used_allowance_of.test.js index 528e4edc5..479fbc8ad 100644 --- a/test/jb_payment_terminal_store/record_used_allowance_of.test.js +++ b/test/jb_payment_terminal_store/record_used_allowance_of.test.js @@ -33,7 +33,7 @@ describe('JBSingleTokenPaymentTerminalStore::recordUsedAllowanceOf(...)', functi const jbCurrenciesFactory = await ethers.getContractFactory('JBCurrencies'); const jbCurrencies = await jbCurrenciesFactory.deploy(); - const CURRENCY_ETH = await jbCurrencies.ETH(); + const CURRENCY_ETH = await JBCurrencies.GAS_CURRENCY(); const CURRENCY_USD = await jbCurrencies.USD(); const _FIXED_POINT_MAX_FIDELITY = 18;